message:
Display a Random Number to Display for T Seconds With Millis() for Dice Roller

I'm coding an electronic dice roller for a project. At the press of a push button (A2), the code must display a random number to the two digit seven segment display for 20 seconds, then display blank.

Currently, my code will display a random number every t seconds while the button is continuously held. I would like the user to be able to press the button and release to let the code do it's thing.

What type of examples should I look at to achieve this? I'm quite a beginner at arduino code.

        #include "SevSeg.h"
    SevSeg sevseg; //Instantiate a seven segment object

    int displayPeriod = 1000; //button press delay
    unsigned long time_now = 0;

    long randNumber;

    void setup() {

      pinMode(A2,INPUT);
     randomSeed(analogRead(3));

      byte numDigits = 2;
      byte digitPins[] = {2, 3};
      byte segmentPins[] = {4,5,6,7,8,9,10};
      bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
      byte hardwareConfig = COMMON_CATHODE; // See README.md for options
      bool updateWithDelays = false; // Default 'false' is Recommended
      bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
      bool disableDecPoint = true; // Use 'true' if your decimal point doesn't exist or isn't connected. Then, you only need to specify 7 segmentPins[]

      sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
      updateWithDelays, leadingZeros, disableDecPoint);

    }

    void loop() {

    if(digitalRead(A2) == HIGH){

      rollD20();

    }

    else{

      sevseg.setChars("");
      sevseg.refreshDisplay();
    }

    }

    void rollD20(){

    if(millis() >= time_now + displayPeriod){
            time_now += displayPeriod;
            time_now = millis();
            randNumber = random(21);
            }
            sevseg.setNumber(randNumber);
      sevseg.refreshDisplay();
      }

    void testInput(){
    sevseg.setNumber(0);
    sevseg.refreshDisplay();
    }

body:
I would recommend to not reinvent the wheel, and proper button management may not be so trivial. I would suggest [this library][1] to address your problem.

  [1]: https://github.com/JChristensen/JC_Button


sender: user

sender: assistant

body:
The problem is that your rollD20 function is only called when the button is pressed.  So once you release the button, it never goes back to that routine to finish.  You need to separate the calling of the function from the detecting of the button.

    bool rollingDice = false;

    void loop() {

    if(digitalRead(A2) == HIGH){
      rollingDice = true;
    }
    if(rollingDice){
      rollD20();
    }
    else{
      sevseg.setChars("");
      sevseg.refreshDisplay();
    }

And then in your rollD20 method you need to set that back to false when it is time to stop:

    void rollD20(){
      if(millis() >= time_now + displayPeriod){
            time_now += displayPeriod;
            time_now = millis();
            randNumber = random(21);
            rollingDice = false;
            }
      sevseg.setNumber(randNumber);
      sevseg.refreshDisplay();
      }


message:
Help reading orientation from gyroscope

I recently bought a [L3GD20H Triple-Axis Gyro][1] to use it to measure orientation, but found out it instead reports the **rate of rotation** in **degrees per second**. I was told this means that to detect the total degrees of rotation, I need to integrate the rate of rotation over time.
I was wondering if someone could help me with this since I'm having trouble wrapping my head around a formula to create. here is my code so far if it helps:

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_L3GD20_U.h>

    /* Assign a unique ID to this sensor at the same time */
    Adafruit_L3GD20_Unified gyro = Adafruit_L3GD20_Unified(20);

    void displaySensorDetails(void)
    {
      sensor_t sensor;
      gyro.getSensor(&sensor);
      Serial.println("------------------------------------");
      Serial.print  ("Sensor:       "); Serial.println(sensor.name);
      Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
      Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
      Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" rad/s");
      Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" rad/s");
      Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" rad/s");
      Serial.println("------------------------------------");
      Serial.println("");
      delay(500);
    }

    void setup(void)
    {
      Serial.begin(9600);
      Serial.println("Gyroscope Test"); Serial.println("");

      /* Enable auto-ranging */
      gyro.enableAutoRange(true);

      /* Initialise the sensor */
      if(!gyro.begin())
      {
        /* There was a problem detecting the L3GD20 ... check your connections */
        Serial.println("Ooops, no L3GD20 detected ... Check your wiring!");
        while(1);
      }

      /* Display some basic information on this sensor */
      displaySensorDetails();
    }

    void loop(void)
    {
      /* Get a new sensor event */
      sensors_event_t event;
      gyro.getEvent(&event);

      /* Display the results (speed is measured in rad/s) */
      Serial.print("X: "); Serial.print(event.gyro.x); Serial.print("  ");
      Serial.print("Y: "); Serial.print(event.gyro.y); Serial.print("  ");
      Serial.print("Z: "); Serial.print(event.gyro.z); Serial.print("  ");
      Serial.println("rad/s ");
      delay(1);
    }

So in summary, I need help creating the code/a formula that will use my Gyro to measure its orientation. Thank you for your time! I'm very lost.

  [1]: https://www.adafruit.com/product/1032

body:
Take a look at this example.

    #include <Wire.h>

    const int MPU = 0x68; // MPU6050 I2C address
    float AccX, AccY, AccZ;
    float GyroX, GyroY, GyroZ;
    float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
    float roll, pitch, yaw;
    float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
    float elapsedTime, currentTime, previousTime;
    int c = 0;

    void setup() {
      Serial.begin(19200);
      Wire.begin();                      // Initialize comunication
      Wire.beginTransmission(MPU);       // Start communication with MPU6050 // MPU=0x68
      Wire.write(0x6B);                  // Talk to the register 6B
      Wire.write(0x00);                  // Make reset - place a 0 into the 6B register
      Wire.endTransmission(true);        //end the transmission
      /*
      // Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
      Wire.beginTransmission(MPU);
      Wire.write(0x1C);                  //Talk to the ACCEL_CONFIG register (1C hex)
      Wire.write(0x10);                  //Set the register bits as 00010000 (+/- 8g full scale range)
      Wire.endTransmission(true);
      // Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
      Wire.beginTransmission(MPU);
      Wire.write(0x1B);                   // Talk to the GYRO_CONFIG register (1B hex)
      Wire.write(0x10);                   // Set the register bits as 00010000 (1000deg/s full scale)
      Wire.endTransmission(true);
      delay(20);
      */
      // Call this function if you need to get the IMU error values for your module
      calculate_IMU_error();
      delay(20);

    }

    void loop() {
      // === Read acceleromter data === //
      Wire.beginTransmission(MPU);
      Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
      //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
      AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
      AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
      AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
      // Calculating Roll and Pitch from the accelerometer data
      accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
      accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)

      // === Read gyroscope data === //
      previousTime = currentTime;        // Previous time is stored before the actual time read
      currentTime = millis();            // Current time actual time read
      elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
      Wire.beginTransmission(MPU);
      Wire.write(0x43); // Gyro data first register address 0x43
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
      GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
      GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
      GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
      // Correct the outputs with the calculated error values
      GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
      GyroY = GyroY - 2; // GyroErrorY ~(2)
      GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)

      // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
      gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
      gyroAngleY = gyroAngleY + GyroY * elapsedTime;
      yaw =  yaw + GyroZ * elapsedTime;

      // Complementary filter - combine acceleromter and gyro angle values
      roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
      pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;

      // Print the values on the serial monitor
      Serial.print(roll);
      Serial.print("/");
      Serial.print(pitch);
      Serial.print("/");
      Serial.println(yaw);
    }

    void calculate_IMU_error() {
      // We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
      // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
      // Read accelerometer values 200 times
      while (c < 200) {
        Wire.beginTransmission(MPU);
        Wire.write(0x3B);
        Wire.endTransmission(false);
        Wire.requestFrom(MPU, 6, true);
        AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
        AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
        AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
        // Sum all readings
        AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
        AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
        c++;
      }
      //Divide the sum by 200 to get the error value
      AccErrorX = AccErrorX / 200;
      AccErrorY = AccErrorY / 200;
      c = 0;
      // Read gyro values 200 times
      while (c < 200) {
        Wire.beginTransmission(MPU);
        Wire.write(0x43);
        Wire.endTransmission(false);
        Wire.requestFrom(MPU, 6, true);
        GyroX = Wire.read() << 8 | Wire.read();
        GyroY = Wire.read() << 8 | Wire.read();
        GyroZ = Wire.read() << 8 | Wire.read();
        // Sum all readings
        GyroErrorX = GyroErrorX + (GyroX / 131.0);
        GyroErrorY = GyroErrorY + (GyroY / 131.0);
        GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
        c++;
      }
      //Divide the sum by 200 to get the error value
      GyroErrorX = GyroErrorX / 200;
      GyroErrorY = GyroErrorY / 200;
      GyroErrorZ = GyroErrorZ / 200;
      // Print the error values on the Serial Monitor
      Serial.print("AccErrorX: ");
      Serial.println(AccErrorX);
      Serial.print("AccErrorY: ");
      Serial.println(AccErrorY);
      Serial.print("GyroErrorX: ");
      Serial.println(GyroErrorX);
      Serial.print("GyroErrorY: ");
      Serial.println(GyroErrorY);
      Serial.print("GyroErrorZ: ");
      Serial.println(GyroErrorZ);
    }

https://howtomechatronics.com/tutorials/arduino/arduino-and-mpu6050-accelerometer-and-gyroscope-tutorial/


message:
Make phone call over 4G LTE

I have used the SIM800L module in the past, but with Ting shutting down their 2G network, I have been looking for alternatives. I have a SIM7000A, but I can't seem to find a microphone or speaker pin. Can this make calls, or will I have to find something else? I am using an Arduino Mega.

body:
The SIM7000 doesn't have a microphone or speaker pin.  Instead it provides a PCM interface to connect to an external CODEC chip.

As it says in the [Hardware Design Manual](http://mt-system.ru/sites/default/files/documents/sim7000_hardware_design_v1.05.pdf):

> SIM7000 provides a PCM interface for external codec, which can be used in master mode with short sync and 16 bits linear format.

If you want to use it for phone calls then you will need a module that also incorporates said CODEC chip and all the associated circuitry to connect to a microphone and speaker.


message:
Scroll Left to Right on MAX7219 Display

For scrolling from `left to right` (**Arabic** letters) I need a function to print **words/sentences** on the MAX7219 display. [By `setpixel(x, y)` function]

I did a lot of searching and my efforts failed. I found the [following example][1] but I couldn't change it. By default this example scrolls from `right to left`. (I need scroll from left to right.)

```
#include <LEDMatrixDriver.hpp>
const uint8_t LEDMATRIX_CS_PIN = 9;

// Number of 8x8 segments you are connecting
const int LEDMATRIX_SEGMENTS = 4;
const int LEDMATRIX_WIDTH    = LEDMATRIX_SEGMENTS * 8;

// The LEDMatrixDriver class instance
LEDMatrixDriver lmd(LEDMATRIX_SEGMENTS, LEDMATRIX_CS_PIN);

// Marquee text
char text[] = "** LED MATRIX DEMO! ** (1234567890) ++ \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" ++ <$%/=?'.@,> --";

// Marquee speed (lower nubmers = faster)
const int ANIM_DELAY = 30;

void setup() {
  // init the display
  lmd.setEnabled(true);
  lmd.setIntensity(2);   // 0 = low, 10 = high
}

int x=0, y=0;   // start top left

// This is the font definition. You can use http://gurgleapps.com/tools/matrix to create your own font or sprites.
// If you like the font feel free to use it. I created it myself and donate it to the public domain.
byte font[95][8] = { {0,0,0,0,0,0,0,0}, // SPACE
                     {0x10,0x18,0x18,0x18,0x18,0x00,0x18,0x18}, // EXCL
                     {0x28,0x28,0x08,0x00,0x00,0x00,0x00,0x00}, // QUOT
                     {0x00,0x0a,0x7f,0x14,0x28,0xfe,0x50,0x00}, // #
                     {0x10,0x38,0x54,0x70,0x1c,0x54,0x38,0x10}, // $
                     {0x00,0x60,0x66,0x08,0x10,0x66,0x06,0x00}, // %
                     {0,0,0,0,0,0,0,0}, // &
                     {0x00,0x10,0x18,0x18,0x08,0x00,0x00,0x00}, // '
                     {0x02,0x04,0x08,0x08,0x08,0x08,0x08,0x04}, // (
                     {0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20}, // )
                     {0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10}, // *
                     {0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08}, // +
                     {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08}, // COMMA
                     {0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00}, // -
                     {0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06}, // DOT
                     {0x00,0x04,0x04,0x08,0x10,0x20,0x40,0x40}, // /
                     {0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x38}, // 0
                     {0x04,0x0c,0x14,0x24,0x04,0x04,0x04,0x04}, // 1
                     {0x00,0x30,0x48,0x04,0x04,0x38,0x40,0x7c}, // 2
                     {0x00,0x38,0x04,0x04,0x18,0x04,0x44,0x38}, // 3
                     {0x00,0x04,0x0c,0x14,0x24,0x7e,0x04,0x04}, // 4
                     {0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x38}, // 5
                     {0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38}, // 6
                     {0x00,0x7c,0x04,0x04,0x08,0x08,0x10,0x10}, // 7
                     {0x00,0x3c,0x44,0x44,0x38,0x44,0x44,0x78}, // 8
                     {0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x78}, // 9
                     {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
                     {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x08}, // ;
                     {0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10}, // <
                     {0x00,0x00,0x7e,0x00,0x00,0xfc,0x00,0x00}, // =
                     {0x00,0x08,0x04,0x02,0x01,0x02,0x04,0x08}, // >
                     {0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10}, // ?
                     {0x00,0x30,0x48,0xba,0xba,0x84,0x78,0x00}, // @
                     {0x00,0x1c,0x22,0x42,0x42,0x7e,0x42,0x42}, // A
                     {0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x7c}, // B
                     {0x00,0x3c,0x44,0x40,0x40,0x40,0x44,0x7c}, // C
                     {0x00,0x7c,0x42,0x42,0x42,0x42,0x44,0x78}, // D
                     {0x00,0x78,0x40,0x40,0x70,0x40,0x40,0x7c}, // E
                     {0x00,0x7c,0x40,0x40,0x78,0x40,0x40,0x40}, // F
                     {0x00,0x3c,0x40,0x40,0x5c,0x44,0x44,0x78}, // G
                     {0x00,0x42,0x42,0x42,0x7e,0x42,0x42,0x42}, // H
                     {0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x7e}, // I
                     {0x00,0x7e,0x02,0x02,0x02,0x02,0x04,0x38}, // J
                     {0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44}, // K
                     {0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c}, // L
                     {0x00,0x82,0xc6,0xaa,0x92,0x82,0x82,0x82}, // M
                     {0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42}, // N
                     {0x00,0x3c,0x42,0x42,0x42,0x42,0x44,0x38}, // O
                     {0x00,0x78,0x44,0x44,0x48,0x70,0x40,0x40}, // P
                     {0x00,0x3c,0x42,0x42,0x52,0x4a,0x44,0x3a}, // Q
                     {0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44}, // R
                     {0x00,0x38,0x40,0x40,0x38,0x04,0x04,0x78}, // S
                     {0x00,0x7e,0x90,0x10,0x10,0x10,0x10,0x10}, // T
                     {0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e}, // U
                     {0x00,0x42,0x42,0x42,0x42,0x44,0x28,0x10}, // V
                     {0x80,0x82,0x82,0x92,0x92,0x92,0x94,0x78}, // W
                     {0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42}, // X
                     {0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10}, // Y
                     {0x00,0x7c,0x04,0x08,0x7c,0x20,0x40,0xfe}, // Z
                      // (the font does not contain any lower case letters. you can add your own.)
                  };    // {}, //

void loop()
{
 // Draw the text to the current position
 int len = strlen(text);
 drawString(text, len, x, 0);
 // In case you wonder why we don't have to call lmd.clear() in every loop: The font has a opaque (black) background...

 // Toggle display of the new framebuffer
 lmd.display();

 // Wait to let the human read the display
 delay(ANIM_DELAY);

 // Advance to next coordinate
 if( --x < len * -8 ) {
  x = LEDMATRIX_WIDTH;
 }
}

/**
 * This function draws a string of the given length to the given position.
 */
void drawString(char* text, int len, int x, int y )
{
  for( int idx = 0; idx < len; idx ++ )
  {
    int c = text[idx] - 32;

    // stop if char is outside visible area
    if( x + idx * 8  > LEDMATRIX_WIDTH )
      return;

    // only draw if char is visible
    if( 8 + x + idx * 8 > 0 )
      drawSprite( font[c], x + idx * 8, y, 8, 8 );
  }
}

/**
 * This draws a sprite to the given position using the width and height supplied (usually 8x8)
 */
void drawSprite( byte* sprite, int x, int y, int width, int height )
{
  // The mask is used to get the column bit from the sprite row
  byte mask = B10000000;

  for( int iy = 0; iy < height; iy++ )
  {
    for( int ix = 0; ix < width; ix++ )
    {
      lmd.setPixel(x + ix, y + iy, (bool)(sprite[iy] & mask ));

      // shift the mask by one pixel to the right
      mask = mask >> 1;
    }

    // reset column mask
    mask = B10000000;
  }
```

  [1]: https://github.com/bartoszbielawski/LEDMatrixDriver/blob/master/examples/MarqueeText/MarqueeText.ino

body:
To scroll in the opposite direction, change this if statement:

    if( --x < len * -8 ) {
        x = LEDMATRIX_WIDTH;
    }

to this:

    if( ++x > LEDMATRIX_WIDTH+len*8 ){
        x = 0;
    }

`x` (the start position of the text) is now incremented instead of decremented, until the whole text (consisting of `len*8` pixels in x direction) is out of the display, where it then gets reset to zero.

This assumes, that the printing of the arabic letters is done from right to left (You might want to implement this, when working with arabic text). The function in the example prints always from left to right, so you need to use this code:

    if( ++x > LEDMATRIX_WIDTH ){
        x = -len*8;
    }

since in this case the text will not be visible in the moment, that the position is over the matrix width.


message:
analogReference(INTERNAL) configuration

I need some help because I did not understand the configuration analogReference(INTERNAL).
I would measure the intensity of a Laser beam passing through a filter. This is the circuit I would implement, using the 3.3 V power supply:
[![figura][1]][1]
In order to rise up the resolution of the system, I would use the 1.1 V power supply (Arduino Uno) to feed the sensor, keeping the Laser power supply at 5 V. In the analogReference(EXTERNAL) configuration shown in the schematic, the sensor is powered by the 3V3 pin, which is connected to the AREF pin. How should I change the circuit in analogReference(INTERNAL) configuration?

  [1]: https://i.stack.imgur.com/t7Sak.png

body:
Changing the analog reference does *not* change the resolution.  All it does is change the measurement range. It compresses the existing resolution into a smaller voltage range.

If you then compress the voltage range of your signal in the same way to fit into the now compressed analog reference voltage range (for example by reducing the supply voltage to 1.1V) you end up achieving absolutely nothing.

The only time you would use the 1.1V internal reference is if your incoming signal is *already* between 0V and 1.1V and you would otherwise be wasting the resolution above the highest voltage the sensor gives out.


message:
Pca9685 & WS2818B, 1 Nano

Arduino n00b here. I currently have an Arduino Nano set up to run 6 servos from a PCA9685 board. I'm looking to add 6 switches and 6 LED indicators to switch servo positions. What I'm curious about is how to connect the WS2818B. I know they can be run through I2C, but the Pca9685 is using those wires. Can I run both the pca9685 and the LEDs through I2C or just run each LED through a separate pin?

body:
I was looking at WS2818B [datasheet][1], they do not use i2c. It just needs a single ( dedicated) pin to receive the color/brightness commands.

  [1]: https://www.tme.eu/Document/ddc250a349c0084fadc3ded4c327f335/WS2818B.pdf


message:
How to use I2S in ESP boards?

I have researched this a lot, but haven't found anything on which I can trust.
I want to use a particular ESP board to play audio. To play audio, I2S support is required. But, I know that not every ESP board break out the I2S pins from the chip. According to me, buying an ESP32 only to use the I2S would be a waste of money. So, my question is, if I just want to use I2S, which board is would be suitable? Please provide some references if you can.

body:
Few months ago I tested successfully I2S with [this library][1], I used the default pins:

    bck_io_num = 26
    ws_io_num = 25
    data_out_num = 22

which are available on many boards such as Lolin D32.

  [1]: https://github.com/earlephilhower/ESP8266Audio


message:
How to decrease a variable every second

I am trying to count down the variable "bankValue" with a certain costfactor
The code I tried will perfectly count down the bankValue..but..

    #define INTERVAL_MESSAGE1 1000

    unsigned long time_1 = 0;

    const float CostFactor = 1.0;
    float bankValue = 10.00;
    const float CostButton1 = 0.004167;

    void setup() {
        Serial.begin(115200);
    }

    void loop() {
        if(millis() >= time_1 + INTERVAL_MESSAGE1){
            bankValue = bankValue - (CostButton1 * CostFactor);
            time_1 +=INTERVAL_MESSAGE1;
            print_time(time_1);
            Serial.print("€");
            Serial.println(bankValue);
        }
       }

I want this the use in an if.
IF button1 is pressed then bankValue will be decreased by a costfactor every second.

I tried this in an if

      if(Pushed == HIGH){
        if(Pushed != StatePushed){
        Serial.println("Button1 OFF");
        }

        digitalWrite(relayPin, LOW);
      }else{
        if(Pushed != StatePushed){
        Serial.println("Button1 ON");
        }
                    if(millis() >= time_1 + INTERVAL_MESSAGE1){
            bankValue = bankValue - (Button1Value * CostFactor);
            time_1 +=INTERVAL_MESSAGE1;
            print_time(time_1);
            Serial.print("€");
            Serial.println(bankValue);
            }
        digitalWrite(relayPin, HIGH);
         }

If the button is pressed, bankValue will decrease.
But when the button is not active....the millis timer keeps on running.
When switching on the button again, I see the bankValue decrease rapidly and not every second.

So the main question:
How can I decrease a variable every second when a button is active.

body:
Your basic main problem is that you don't know when the button was pressed.  Your timing algorithm always works from the "last time the value was decremented" - and that could be hours ago.  When you press the button the difference between `millis()` and `time_1` could be massive, and it has to count up one second at a time until `time_1` passes `millis()`.

What you really need to do is separate out the button from the action. That makes it easier to manage.  You need to find the times when the button transitions from HIGH to LOW (pressed) and from LOW to HIGH (released). You're almost doing that right now, but not quite.  Then when you find the moment of being pressed you can say "From this moment forth you shall count."

For example you might change the first part of your code to be:

```c++
if (Pushed != StatePushed) {
    StatePushed = Pushed; // Remember the current state for the next time round
    if (StatePushed == HIGH) { // Released
        Serial.println("Button1 OFF");
    } else { // Pressed
        Serial.println("Button1 ON");
        time_1 = millis(); // Remember what the time is right now
    }
}
```

That then is a single atomic operation and you can now at any time examine `StatePressed` to see if the button is pressed or not, and also at the moment of pressing `time_1` is set to the current `millis()` value, so you now know when the button was pressed.

Now you can add your second part using `StatePressed` as the trigger:

```c++
if (StatePressed == LOW) { // Button pressed
    if(millis() >= time_1 + INTERVAL_MESSAGE1){
        bankValue = bankValue - (Button1Value * CostFactor);
        time_1 +=INTERVAL_MESSAGE1;
        print_time(time_1);
        Serial.print("€");
        Serial.println(bankValue);
    }
}
```
However your method of comparing the time is not good. It doesn't handle the *millis rollover* problem.  Instead you should be using something more like:

```c++
if (millis() - time_1 >= INTERVAL_MESSAGE1) {
    time_1 = millis();
    ... etc ...
}
```


body:
I tried to use the solution post by Majenko and came up with something like this:

      if(Pushed != StatePushed) {
        if(Pushed == HIGH){
          if(Pushed != StatePushed){
            Serial.println("LED OFF");
            }
            digitalWrite(ledPin, LOW);  // turn LED OFF
            }else{
            if(Pushed != StatePushed){
            Serial.println("LED ON");
            time_1 = millis();
            }
            digitalWrite(ledPin, HIGH);  // turn LED OFF
            }
      }
             StatePushed = Pushed;

      delay(100);

      if(Pushed == LOW){
        if(millis() >= time_1 + INTERVAL_MESSAGE1){
          time_1 = millis();
            bankValue = bankValue - (coinValueB * CostFactor);
            time_1 +=INTERVAL_MESSAGE1;
            Serial.print("€");
            Serial.println(bankValue);
                    Serial.println(INTERVAL_MESSAGE1);
        }
      }

Pretty much how you suggested it...
but I realize I absolutely do not understand how millis() exactly works.

I have no idea what this does:

    if(millis() >= time_1 + INTERVAL_MESSAGE1)

In a way, the loop works. But the timing is really off.
With my settings, every second subtracting 0.004167, should be 0,25 is one minute.
But it was only around half...0,13 or so


body:
This answer is in response to Niles's answer based on Majenko's answer (phew! that was a bit of a mouthful).

**millis()** returns how many milliseconds have passed since your program started.

And your timing is off because you are adding **INTERVAL_MESSAGE1** with **time_1** i.e. instead of waiting for one second you are actually subtracting after every two seconds. Hence, you got half the value you expected. Remove that line. (And also don't use delay).

I have isolated your substracting part of the code. Run this and you should see the result (button is connected to D4):

    unsigned long PreviousTime = 0;
    const unsigned long THRESHOLD = 1000;
    const float CostFactor = 1.0;
    float bankValue = 10.00;
    const float CostButton1 = 0.004167;

    void setup()
    {
      Serial.begin(9600);
      pinMode(4, INPUT_PULLUP);
    }

    void loop()
    {
      if(digitalRead(4) == 0)
      {
        if((unsigned long)(millis() - PreviousTime) >=  THRESHOLD) // You need to check time like this to avoid overflow
        {
          PreviousTime = millis();
          bankValue = bankValue - (CostButton1 * CostFactor);
          Serial.println(bankValue);
        }
      }
    }


message:
ESP32 Bluetooth SPP Max Speed

I am trying to understand the maximum BT SPP transmission speed that can be achieved using ESP32.

What my project requires is to send 2bytes of data every 200us (5kHz) AND additional 15bytes of data every 50ms(20Hz) via BT.

I am trying to achieve that using BT SPP, however, I could not understand the speed of BluetoothSerial::write AND BluetoothSerial::print.

Based on my testing for 5kHz, the BluetoothSerial::write freezes after 2-3 seconds of connection.

BluetoothSerial::println function doesn't seem to freeze, however, the time taken for the function to complete doesn't seem to be constant. Please refer to the code below on how I measure the time taken for the function to complete.

The picture below shows the time in microseconds each time the function (dataFormat()) takes place. If you look through, there are 2 instances where the time duration is more than an average 0f 80us.

I would like to know, ESP32 BT SPP can achieve such a speed or there is another way I could achieve this.

Thank you for your time and assistance in this matter.
I have asked the same question in ESP32 Forum as well [here](https://www.esp32.com/viewtopic.php?f=19&t=14682&sid=b2acf337a80e803849127e85a16bbe33  "ESP32 Arduino BluetoothSerial Max Speed").

```
void dataFormat(record r){
  serialBtPrint_dur = micros();
  char msg[20];
  sprintf(msg,"ddd",r.e, r.r, r.p, r.y);
  SerialBT.println(msg);
  serialBtPrint_dur = micros() - serialBtPrint_dur;
  }
}

void loop() {
  char msg[20];
  uint8_t testMsg[20] = "abcdefghijklmnop\n";
  if(!structs.isEmpty()){
    dataset[local_rd_ptr].yawData);
    data::dataFormat(structs.shift());
    Serial.println(serialBtPrint_dur);
  }
}

```
[![duration for each fuction call of dataFormat in us][1]][1]

  [1]: https://i.stack.imgur.com/o7mat.jpg

body: This seems more like an overflow issue with something than an actual delay.  If you look at the time in the log, it seems you aren't skipping seconds in the log (aka, 19:12:32.234 in two sequential log entries when you claim a delay).  I think it's an error of working with larger than 8-bit data sizes.  I know this is an old question, but I was looking for info and came upon it and figured I'd ask.


message:
Blink not working

I have written this code to write and receive signals over i2c between two Uno's. I have a master and a slave code, this is working fine. Now I want the led to blink, for this I added the blink without delay example. Unfortunately I can't get it working at all...

    // Wire Slave Receiver

    #include <Wire.h> //include Library
    // define Led Pins
    #define LED1 3 //Pin 3
    #define LED2 4 //Pin 4
    #define LED3 5 //Pin 5

    int ledState = LOW;             // ledState used to set the LED
    unsigned long previousMillis = 0;        // will store last time LED was updated
    const long interval = 500;           // interval at which to blink (milliseconds)

    void setup()
    {
      Wire.begin(4);                // join i2c bus with address #4
      Wire.onReceive(receiveEvent); // register event
      Serial.begin(9600);           // start serial for output

      //set Pin modes
      pinMode(LED1, OUTPUT);
      pinMode(LED2, OUTPUT);
      pinMode(LED3, OUTPUT);
      //intern pulldown
      digitalWrite(LED1, LOW);
      digitalWrite(LED2, LOW);
      digitalWrite(LED3, LOW);

    }

    void loop()
    {
      unsigned long currentMillis = millis();
      delay(100);
    }

    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany)
    {
      while (1 < Wire.available()) // loop through all but the last
      {

        char c = Wire.read(); // receive byte as a character
        Serial.print(c, BIN);     // print the character as Binary

      }
      int x = Wire.read();    // receive byte as an integer
      Serial.println(x, BIN); // print the integer as Binary

      if (x == 1) { //turn LED1 on
        digitalWrite(LED2, LOW);
        digitalWrite(LED3, LOW);
        digitalWrite(LED1, HIGH);
        Serial.println("LED1 on");
      }
      if (x == 2) { //blink LED1
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED1, ledState);
        }
      }

      if (x == 3) { //turn LED2 on
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, HIGH);
        delay(100);
      }
      if (x == 4) { //blink LED2
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED2, ledState);
        }
      }
      if (x == 5) { //turn LED3 on
        digitalWrite(LED2, LOW);
        digitalWrite(LED3, HIGH);
      }
      if (x == 6) { //blink LED3
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED3, ledState);
        }
      }
      if (x == 7) { //turn LED1 nad 2 on
        digitalWrite(LED3, LOW);
        digitalWrite(LED1, HIGH);
        digitalWrite(LED2, HIGH);
      }
      if (x == 8) { //Blink LED1 and 2
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, LOW);
      }
      if (x == 9) { //turn LED2 and 3 on
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, LOW);

        digitalWrite(LED2, HIGH);
        digitalWrite(LED3, HIGH);
      }

    }

---

Thanks for your response. I tried to put all the of statements into the loop, but it's still not working. :P I have no idea how to put it into the loop so it works.

```
// Wire Slave Receiver

#include <Wire.h> //include Library
// define Led Pins
#define LED1 3 //Pin 3
#define LED2 4 //Pin 4
#define LED3 5 //Pin 5

int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 500;           // interval at which to blink (milliseconds)

void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output

  //set Pin modes
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  //intern pulldown
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);
  digitalWrite(LED3, LOW);

}

void loop()
{
    if (x == 1) { //turn LED1 on
    digitalWrite(LED2, LOW);
    digitalWrite(LED3, LOW);
    digitalWrite(LED1, HIGH);
    Serial.println("LED1 on");
  }
  if (x == 2) { //blink LED1
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(LED1, ledState);
    }
  }

  if (x == 3) { //turn LED2 on
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, HIGH);
    delay(100);
  }
  if (x == 4) { //blink LED2
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(LED2, ledState);
    }
  }
  if (x == 5) { //turn LED3 on
    digitalWrite(LED2, LOW);
    digitalWrite(LED3, HIGH);
  }
  if (x == 6) { //blink LED3
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (ledState == LOW) {
        ledState = HIGH;
      } else {
        ledState = LOW;
      }
      digitalWrite(LED3, ledState);
    }
  }
  if (x == 7) { //turn LED1 nad 2 on
    digitalWrite(LED3, LOW);
    digitalWrite(LED1, HIGH);
    digitalWrite(LED2, HIGH);
  }
  if (x == 8) { //Blink LED1 and 2
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, LOW);
  }
  if (x == 9) { //turn LED2 and 3 on
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, LOW);

    digitalWrite(LED2, HIGH);
    digitalWrite(LED3, HIGH);
  }
  unsigned long currentMillis = millis();
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
  while (1 < Wire.available()) // loop through all but the last
  {

    char c = Wire.read(); // receive byte as a character
    Serial.print(c, BIN);     // print the character as Binary

  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x, BIN); // print the integer as Binary

}

body:
You are misinterpreting how the `onReceive` callback works. The `millis()` code like in the `BlinkWithoutDelay` example relies on the fact, that it is run repeatedly very fast, so that effectively the time is checked regularily very fast.

The `onReceive` callback is only called once every time, that the `Wire` library received an I2C message, from an interrupt service routine. It is not called repeatedly. So the `millis()` code in there, will only be executed once. Since no time has passed (and `millis()` wouldn't increment inside an ISR either way) nothing happens there and the callback exits. After that the code is not executed further times.

You need to put the `millis()` code into the `loop()` function, so that it is executed repeatedly. In fact you can put all the if statements with `x` into the `loop()` function.

---

EDIT:

Your second version of the code should result in compilation errors (which you really should have included into your question). They will say, that `x` is not declared in this scope. You read the I2C data from the buffer in the `onReceive` callback and save it into a newly created variable `x`. Since `x` is declared inside the function, it will cease to exist right after the end of this function. The `loop()` function does not know about `x`. You need to define `x` globally outside of any function at the start of your sketch.

This results in this code:

    // Wire Slave Receiver

    #include <Wire.h> //include Library
    // define Led Pins
    #define LED1 3 //Pin 3
    #define LED2 4 //Pin 4
    #define LED3 5 //Pin 5

    uint8_t x=0;                    // define x at global scope, so that it is available everywhere
    int ledState = LOW;             // ledState used to set the LED
    unsigned long previousMillis = 0;        // will store last time LED was updated
    const long interval = 500;           // interval at which to blink (milliseconds)

    void setup()
    {
      Wire.begin(4);                // join i2c bus with address #4
      Wire.onReceive(receiveEvent); // register event
      Serial.begin(9600);           // start serial for output

      //set Pin modes
      pinMode(LED1, OUTPUT);
      pinMode(LED2, OUTPUT);
      pinMode(LED3, OUTPUT);
      //intern pulldown
      digitalWrite(LED1, LOW);
      digitalWrite(LED2, LOW);
      digitalWrite(LED3, LOW);

    }

    void loop()
    {
        if (x == 1) { //turn LED1 on
        digitalWrite(LED2, LOW);
        digitalWrite(LED3, LOW);
        digitalWrite(LED1, HIGH);
        Serial.println("LED1 on");
      }
      if (x == 2) { //blink LED1
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED1, ledState);
        }
      }

      if (x == 3) { //turn LED2 on
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, HIGH);
        delay(100);
      }
      if (x == 4) { //blink LED2
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED2, ledState);
        }
      }
      if (x == 5) { //turn LED3 on
        digitalWrite(LED2, LOW);
        digitalWrite(LED3, HIGH);
      }
      if (x == 6) { //blink LED3
        unsigned long currentMillis = millis();
        if (currentMillis - previousMillis >= interval) {
          previousMillis = currentMillis;
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
          digitalWrite(LED3, ledState);
        }
      }
      if (x == 7) { //turn LED1 nad 2 on
        digitalWrite(LED3, LOW);
        digitalWrite(LED1, HIGH);
        digitalWrite(LED2, HIGH);
      }
      if (x == 8) { //Blink LED1 and 2
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, LOW);
      }
      if (x == 9) { //turn LED2 and 3 on
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, LOW);

        digitalWrite(LED2, HIGH);
        digitalWrite(LED3, HIGH);
      }
      unsigned long currentMillis = millis();
      delay(100);
    }

    // function that executes whenever data is received from master
    // this function is registered as an event, see setup()
    void receiveEvent(int howMany)
    {
      while (1 < Wire.available()) // loop through all but the last
      {
        char c = Wire.read(); // receive byte as a character
        Serial.print(c, BIN);     // print the character as Binary
      }
      x = Wire.read();    // receive byte as an integer
      Serial.println(x, BIN); // print the integer as Binary
    }

Note, that I changed the type of `x` to `uint8_t`, an unsigned int of 8 bits. Restricting `x` to 8 bits prevents problems with writing a variable inside an ISR. The Uno has an 8-bit microcontroller, so it handles 8 bits at a time. `int` has 16 bits and is thus handled in two steps. An interrupt can occur at any time, so the ISR might write `x` in the middle of a calculation, which results in a totally garbled value of `x`. Handling a 1 byte/8 bits variable cannot be interrupted (also called "atomic") and prevents this issue.


message:
Typedef struct not working

I made this simple code but I'm getting the following error
```
exit status 1
'RGB' does not name a type
```

```
typedef struct
RGB
{
        double r;
        double g;
        double b;
};

RGB led;

RGB func(){
  RGB temp;
  return RGB;
}
```
I am not getting the error on "RGB led" but just on the function.
Does anyone know a solution for this? Thanks!

body:
There are 2 errors:

you are returning a class type, and not the *temp* object

      RGB func(){
        RGB temp;
        return RGB; --> return temp;
      }

To use your typedef you should put the struct "name" after the braced parenthesis:

    typedef struct
    {
        double r;
        double g;
        double b;
    } RGB;


body:
In plain C, structs are identified by "struc tags", which do not live in
the same namespace as type names. Thus, if you declare

```c++
struct RGB {
    ...
};
```

a variable of this type should be declared as

```c++
struct RGB led;
```

In order to avoid the inconvenience of repeatedly typing `struct`, a
common idiom is to define it as a type:

```c++
typedef struct {
    ...
} RGB;

RGB led;
```

The Arduino environment, however, is based on the C++ programming
language. In C++ struct tags _are_ types, and you thus do not need the
typedef:

```c++
struct RGB {
    ...
};

RGB led;
```

This is the recommended idiom in C++: just remove the typedef.


message:
Modifying smart watch or activity armband with further sensors

I want something like an activity armband where I would like to add an bend sensor or EMG sensor for simple hand gesture recognition tasks. I could probably build it from scratch with arduino-like parts, but it will be much more bulky then the ones on the market and I would rather not reinvent those things that already do what I want. [This][1] is the type of device I am thinking about.

Is there an feasible task to try to modify an existing activity armband or smart watch by adding one of these sensors? If so, do you have any suggestions of what should be considered? Should I try something completely different? I am open to ideas.
I have a background in Physics and Computer Science with an basic understanding of electronic devices but I am eager to learn.

  [1]: https://www.semanticscholar.org/paper/Exploring-the-Potential-of-Wrist-Worn-Gesture-Liu/17d44e5e303e78f261578e7ccb010048a2aaecad

body:
there are a few DIY, open source armband or watch models like :

https://www.tindie.com/products/ttgo/t-wristband-diy-programmable-smart-bracelet/

which has the sources and tutorials on :

https://github.com/Xinyuan-LilyGO/LilyGO-T-Wristband

it's based on ESP32 and is Arduino ready.the space constraint may not allow for adding a new sensor, but it already comes with a few onboard sensors.
after getting along with ESP32 and the TTGO libraries (which are all provided by the manufacturer LilyGo) that wouldn't be too hard to design a custom band.


message:
Reading out two sensors via Com-Port at the same time

I have two Arduino Nano Every and a sensor connected to each of them. Here is what's happening:

- I upload the sketch to the first Arduino on Com4 and see its output is correct via the Serial Monitor

- I open a new instance of the Arduino-software, upload the same sketch to the second Arduino on Com6 and see its output is correct. However, in the meantime the Arduino on Com4 has stopped sending or receiving data

- If I close the second IDE-instance and re-upload the sketch to the first Arduino on Com4, it starts working again.

So, essentially I have two Arduinos which I can't read out at the same time.

The sensors are not connected, so I don't know where the problem is. Shouldn't the Com-Ports be independent?

body:
> Shouldn't the Com-Ports be independent?

Not in the Arduino IDE, no. Basically the IDE is [expletive deleted] when it comes to using more than one board at a time.

You're better off using a proper serial terminal program, not the "serial monitor" in the IDE. Something like Teraterm or Putty, where you can have multiple instances on different ports at once.


body:
UPDATE, self answer:

It was a broken USB cable.


message:
NodeMCU ESP8266 disconnected from WiFi after several hours running

I tried to test NodeMCU ESP8266 with this code from [here][1]

        #include <ESP8266WiFi.h>
     #include <WiFiClient.h>
     #include <ESP8266WebServer.h>
     #include <ESP8266HTTPClient.h>

     /* Set these to your desired credentials. */
     const char *ssid = "dummy";  //ENTER YOUR WIFI SETTINGS
     const char *password = "12345678";

     //Web/Server address to read/write from
     const char *host = "192.168.43.128";   //https://circuits4you.com website or IP address of server

     //=======================================================================
     //                    Power on setup
     //=======================================================================

     void setup() {
       delay(1000);
       Serial.begin(115200);
       WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
       delay(1000);
                      WiFi.setSleepMode(WIFI_NONE_SLEEP);
       WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot

       WiFi.begin(ssid, password);     //Connect to your WiFi router
       Serial.println("");

       Serial.print("Connecting");
       // Wait for connection
       while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
       }

       //If connection successful show IP address in serial monitor
       Serial.println("");
       Serial.print("Connected to ");
       Serial.println(ssid);
       Serial.print("IP address: ");
       Serial.println(WiFi.localIP());  //IP address assigned to your ESP
     }

     //=======================================================================
     //                    Main Program Loop
     //=======================================================================
     void loop() {
       HTTPClient http;    //Declare object of class HTTPClient

       String ADCData, station, postData;
       int adcvalue=analogRead(A0);  //Read Analog value of LDR
       ADCData = String(adcvalue);   //String to interger conversion
       station = "A";

       //Post Data
       postData = "status=" + ADCData + "&station=" + station ;

       http.begin("http://192.168.43.128/c4yforum/postdemo.php");              //Specify request destination
       http.addHeader("Content-Type", "application/x-www-form-urlencoded");    //Specify content-type header

       int httpCode = http.POST(postData);   //Send the request
       String payload = http.getString();    //Get the response payload

       Serial.println(httpCode);   //Print HTTP return code
       Serial.println(payload);    //Print request response payload

       http.end();  //Close connection

       delay(5000);  //Post Data at every 5 seconds
     }
It was running well and posted data to Database after a few hours. Then It was disconnected from WiFi somehow . Of course I reset power supply again It's connected.

How should I do to fix with that code to reconnect WiFi right after that accident Or any other Solution  for that ? Thank you

  [1]: https://circuits4you.com/2018/03/10/esp8266-nodemcu-post-request-data-to-website/

body:
What you need to do is leave the board connected to your computer and watch the serial monitor to capture the output during the crash.  If the board has a true crash it will output a bunch of information which may tell you why you it is crashing.  It could be a strings/heap problem or maybe a memory issue since you are declaring a new http object every 5 seconds.  Maybe try putting the HTTPClient http; line up where you declare the host variable so that it is a global variable and not a local variable.

Since your loop doesn't test to make sure the wifi connection is still good then if you get a disconnection then the program will just fail and never try to re-connect.  So at the start of your main loop put the same wifi testing logic that is also in the setup function. If the connection is down then reset and start from the very beginning to re-establish the wifi connection.
```
if (WiFi.status() != WL_CONNECTED) {
    ESP.reset()
  }
```


body:
I also had the same issues. I've looked for some posting like [here.][1]
You can try these codes

    void loop()
     {
     WiFiClient client;

     Serial.printf("\n[Connecting to %s ... ", host);
    if (client.connect(host, 80))
    {
    Serial.println("connected]");

    Serial.println("[Sending a request]");
    client.print(String("GET /") + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n" +
                 "\r\n"
                );

    Serial.println("[Response:]");
    while (client.connected() || client.available())
    {
      if (client.available())
      {
        String line = client.readStringUntil('\n');
        Serial.println(line);
      }
    }
    client.stop();
      Serial.println("\n[Disconnected]");
     }
     else
     {
      Serial.println("connection failed!]");
      client.stop();
     }
     delay(5000);
     }

The seconds thing as @tavis said you can try [from here][2].
It sounds ESP.restart(); is recommended rather than ESP.reset();
It seems our issue is very hard.

  [1]: https://stackoverflow.com/questions/59697417/esp8266-crashes-after-simple-http-request
  [2]: https://www.pieterverhees.nl/sparklesagarbage/esp8266/130-difference-between-esp-reset-and-esp-restart


message:
Is it possible to connect a 36 pin 4 digit 7 segment display on an Arduino Uno R3?

First of all,here's the datasheet of the 4 digit 7 segment display that I'm using:
http://www.kingbrightusa.com/images/catalog/SPEC/ca56-11ewa.pdf

How can I make a counter or a clock out of this particular led display,considering the fact that I don't have enough digital pins to manipulate led's pins?

body:
As Juraj mentioned, you can use shift registers, such as 74HC595 which uses the SPI protocol.

To elaborate slightly on this:

- You can cascade 4 shift registers, totaling 32 pins for output
- If you need 36, you can use the remaining 4 as normal pins (this is probably the easiest solution)
- Or you can use the Chip/Slave Select feature of SPI to control two chains of shift registers. So e.g. one chain is doing 4 * 8 = 32 pins, the other (single shift register) using 8 pins (from where 4 pins are used only).

To make a clock, use a RTC (Real time clock) module/IC, a counter (unless very high frequency) does not need an external IC.


body:
You actually only need 12 pins for that display.

The display is made up of 4 separate common anode LED displays, and you can use that to your advantage.

Since the 4 anode clusters are separate you have the ability to switch an entire digit on or off. And as a result all the cathodes of the segments can be commoned together (that is, the cathodes of all the segment As can be commoned, and the cathodes of all the segment Bs, etc), which is then 8 clusters of 4 cathodes.

That means you can have 4 outputs controlling the for anodes (ideally through PNP transistors or P-channel MOSFETs to handle higher current), and 8 outputs to control all the cathodes (each through a resistor and ideally an NPN transistor or N-channel MOSFET to handle higher current).

The you rapidly switch between each digit displaying the right segment combination for that digit.

Here's a partial example showing 4 digits but just segments A and B. Youd expand this out for segments C through G.  GPIO_A1 to GPIO_A4 are activated to select which digit is being displayed. GPIO_CA through GPIO_CG would be to select the arrangement of segments on that digit.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/fTRar.png)

<!-- End schematic -->


body:
Only need 4, or 5 pins; SCK (D13), MOSI (D11), slave select (D10).
Maybe PWM (D9) for brightness.
D12 not used, but is tied up as part of SPI bus.

Connect the Anodes to +5.

Connect the cathodes, with a current limit resistor per cathode, to the outputs of 4 TPIC6C595, or TPIC6B595.

For the resistor, assume worst case voltage drop of 2V and 20mA current draw:
(5V - 2V)/.02A = 150 phm.

Use a PWM output pin to drive the OE/ pin of the '595s for brightness control.

Then shift data into the daisychained shift registers as an update is needed.

    byte dataMap[] = {
    0b00111111, // 0 with bits representing DP,g,f,e,d,c,b,a
    0b00000110, // 1
    0b01011011, // 2
    // etc
    };

where segments are layed at as

       a
    f     b
       g
    e     c
       d      DP or colon

then call the array in loop(), make it a function if you want.

    digitalWrite (ssPin, LOW); // D10 on Uno, used as Latch signal
    for (x = 0; x <4; x=x+1){
    SPI.transfer (mapArray[digit0]); // digit0 value mapped to segments
    SPI.transfer (mapArray[digit1]);
    SPI.transfer (mapArray[digit2]);
    SPI.transfer (mapArray[digit3]);
    }
    digitalWrite (ssPin, LOW); // outputs update on this rising edge

I wonder where DP5, DP6, which make the colon, are? I don't see them in the pinout.


message:
PCF8575c changes address in I2C Scanner

I want to connect a PCF8575c pin extender to an ESP32, so that I can light 12 LEDs. The problem is that after the connection, when I try to use an I2C Scanner, it shows me a lot of different addresses, not a constant one. Could this happen from a pin fault? I am using this library:
https://github.com/xreef/PCF8575_library

Also, the I2C scanner can be found here: https://playground.arduino.cc/Main/I2cScanner/

And the pins that I use for the LEDs are defined this way:

```
  pcf8575.pinMode(P0, OUTPUT);
  pcf8575.pinMode(P1, OUTPUT);
  pcf8575.pinMode(P2, OUTPUT);
  pcf8575.pinMode(P3, OUTPUT);
  pcf8575.pinMode(P5, OUTPUT);
  pcf8575.pinMode(P6, OUTPUT);
  pcf8575.pinMode(P11, OUTPUT);
  pcf8575.pinMode(P12, OUTPUT);
  pcf8575.pinMode(P14, OUTPUT);
  pcf8575.pinMode(P15, OUTPUT);
  pcf8575.pinMode(P16, OUTPUT);
  pcf8575.pinMode(P17, OUTPUT);
```

The link to the exact PCF8575c:
https://www.aliexpress.com/item/2038559527.html?spm=a2g0o.productlist.0.0.3f8331ebu0zuwr&algo_pvid=5e9fc157-a422-4847-acf4-8618a2d365ea&algo_expid=5e9fc157-a422-4847-acf4-8618a2d365ea-2&btsid=0ab6f82415840969999872503e3228&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_

body:
Look at the back of the module. There are 3 groups of 3 solder pads each, marked with A0, A1 and A2. With these pads you can set the 3 least significant bits of the address.

On the images in your product link these pads are unconnected. The middle pin is the address pin. The left pad (which is connected to a trace) is Vcc, the right pad (which is connected to the big trace area) is ground. By connecting the middle pad with ground, you set the address bit to zero. By connecting it to Vcc, you set it to 1.

As the pads are unconnected, the address pins are floating. In that state, the pin is reacting to random electrical noise, thus changing state randomly. So also the address changes randomly.

You need to connect every address pin to either ground or Vcc by adding a solder bridge to the pads.


message:
Scroll one line of text while another line is static on a SSD1306 OLED

I have an SSD1306 OLED that I have connected to a Wemos D1 Mini. It works like a charm, but I was wondering if it was possible to have two lines of code, where one line is static, and the other one scrolls? No example on the web as far as I have tried to find.

body:
I just found the answer on the following site: https://lastminuteengineers.com/oled-display-arduino-tutorial/

Basically, the method `startscroll*` on the display takes some arguments.
By passing the proper start page and stope page you can scroll parts of the screen.

[Refer to OLED Memory Map][1] for explanation of the pages on the screen. There are eight pages in the display from 0 to 7, so we can scroll a certain part of the screen by passing specific page numbers as parameters.

In this example, we pass both the parameters as 0x00. This will scoll the first page only (first 8 rows) of the display:

```
// Scroll part of the screen
display.setCursor(0,0);
display.setTextSize(1);
display.println("Scroll");
display.println("some part");
display.println("of the screen.");
display.display();
display.startscrollright(0x00, 0x00);
```

Source: https://lastminuteengineers.com/oled-display-arduino-tutorial/

  [1]: https://learn.sparkfun.com/tutorials/microview-hookup-guide/oled-memory-map


message:
How do I make a proper long string scanner to detect specific tags in a stream of characters?

Here's my code:

    #include <SoftwareSerial.h>
    SoftwareSerial BTserial(2, 3); // RX, TX

    void setup() {
        Serial.begin(9600);
        BTserial.begin(9600);
        Serial.println("Communication with HC-05 successfully started.");
    }

    bool is_uploading_book = false;
    char c = ' ';
    String recv_scanner = "";
    void loop(){
        if (BTserial.available()) {
            c = BTserial.read();
            recv_scanner += c;
            if(recv_scanner.length() >= 50) {
              recv_scanner.remove(0, 1);
            }
            // I believe there's something wrong with the recv_scanner.
            if(is_uploading_book) {
              Serial.write(c);
            } else {
              if(recv_scanner.indexOf("(__BOOK_UPLOAD_START__)") >= 0) {
                is_uploading_book = true;
              }
            }
            Serial.println("\n\n" + recv_scanner + "\n\n");
        }
    }

I'm sending a book (long text) in the form of characters one by one from my phone to my HC-05 module (and the Arduino).

My goal is to spot the tag "(_BOOK_UPLOAD_START_)" in the incoming characters.

Arduino allows me to receive the characters of the book one by one on each loop.

I'm storing those characters in a string called *recv_scanner* where I allow it's maximum size to be 50 characters and once it reaches those 50 characters, I start to remove the first character and add a new one on each loop (so it can only see 50 characters at a time because maximum String length is 200 and for my purposes, 50 is enough).

The thing is, it doesn't work properly.

When I Serial.println the *recv_scanner* on every loop (so I see how it progresses) it starts to look like this:

    ⸮qsnieq⸮cn .laslvanm.⸮⸮⸮d⸮alvuv⸮⸮urosqiam tr⸮⸮⸮
(It starts normally and then slowly progresses into this)

I have no idea what that is.

As far as my predictions go, it should show 50 characters and they should be parts of the books.

Is there something fundamental about Strings that I don't know of?

I'm doing this so I'm able to detect a tag (_BOOK_UPLOAD_END_) at the end of the book and finish uploading.

Feel free to ask my questions if something is unclear.

body:
I think your problem lies in the usage of the `String` class. Every time, that you concat a `String` variable, a new buffer for the result is allocated in the background via dynamic memory allocation. That can result in heap fragmentation, which eats up your memory pretty fast (especially on the smaller ones, like the Uno).

Instead you should use a `char` array as ring buffer. Let's define the buffer first and initialize it to zero:

    #define BUFFER_SIZE    50
    char buffer[BUFFER_SIZE] = {0};

Now we define position variables, where the valid data starts and ends in the buffer:

    uint8_t buffer_start = 0;
    uint8_t buffer_end = 0;

When `buffer_start == buffer_end`, the buffer is empty. When `buffer_end` is one position before `buffer_start`, the buffer is full. To put one character into the buffer we do the following (note, that `c` is the same variable, as in your code):

    if( ((buffer_end + 1) % BUFFER_SIZE) == buffer_start)
    {
        buffer_start = (buffer_start + 1) % BUFFER_SIZE;
    }
    buffer[buffer_end] = c;
    buffer_end = (buffer_end+1) % BUFFER_SIZE;

What are we doing here? First we need to check, if our buffer is full. We are doing this by comparing `buffer_start` to the next position of your `buffer_end`. The calculation of the new position is where the magic happens. First we increment `buffer_end` by one and then we are taking the modulus with the buffer size. The modulus is the rest of an integer division. When the position is at the end of the `buffer` array, it will be `(49 + 1) % 50`, which is zero. That wraps the array end to the array end for us.

If our buffer is full, then we increment the start counter of the buffer. That means, that we are ditching one character at the start of our buffer to add one at the end (which is what you want to do). (Note, that normally with ring buffers you don't want to throw away data, so you refuse to put more data into the buffer, when it is full).

Then we store the received character into our buffer and increment `buffer_end` like described above.

The above principle is also called circular FIFO buffer (First In First Out), though there are missing some function to a real FIFO buffer, that you don't need here.

---

Now, that we have a ring buffer, which gets filled with the data, we also need to implement a function to find a string in the buffer, meaning an equivalent to the `String.indexOf()` method. It might look something like this:

    int find_string(char str[], const char search[]){
        uint8_t start = buffer_start;
        uint8_t search_pos = 0;
        uint8_t result_pos = -1;
        while(start != buffer_end){
            if(str[start] == search[search_pos]){
                if(search_pos == 0) result_pos = start;
                search_pos++;
                if(search[search_pos] == '\0') return result_pos;
            } else {
                result_pos = -1;
                search_pos = 0;
            }
            start = (start + 1) % BUFFER_SIZE;
        }
        return -1;
    }

Note, that this implementation is only roughly tested, not thoroughly.


body:
Another option is to not save the characters in buffer but instead check each one as they arrive to see if the character is the next in the tag sequence.

This has the advantage that you don't need a buffer to match the tag and you don't have to repeatedly search for the string in the buffer.

    const char* TAG_STR="(__BOOK_UPLOAD_START__)";
    int tag_pos = 0;
    char c;
    bool is_uploading_book = false;

    void loop() {
      if (BTserial.available()) {
        c = BTserial.read();
        if (is_uploading_book) {
          //do book stuff
        } else {
          if (c == TAG_STR[tag_pos]) {
            // c matched the next character in the string
            tag_pos++;
          } else if (c == TAG_STR[0]) {
            // matched first char in the middle, restart
            tag_pos = 1;
          } else {
            // Did not match the next character so we should start over
            tag_pos = 0;
          }
          // The next character to match is the string terminator
          // so we must have matched the whole string.
          if (TAG_STR[tag_pos] == '\0') {
            is_uploading_book = true;
          }
        }
      }
    }


message:
Serial communication by bluetooth hc-05

i am making a ultrasonic radar using stepper motor and ultrasonic sensor , and displaying the output over a software(processing 3) which looks like a radar ppi on display ...is it possible ot replace the usb cable with a bluetooth connection to send data (serial) instead of using a usb cable i want the setup to be remote ..i am using a instructable https://www.instructables.com/id/Acoustic-Radar-Display/ for coding i just need to know how to make it wireless over bluetooth ...just changing the com over processing 3 works or i need to do some changes in command mode of bluetooth

body:
If you use a Bluetooth Module [like this][1], that has an SSP profile, it will show up as COM port on your windows machine.

Now if you want to use the Arduino's Hardware Serial (i.e. keep using Serial.print() but for Bluetooth) then you will connect the module like this:

 - Bluetooth HC06 TX to digital pin 0 (Arduino Rx)
 - Bluetooth HC06 RX to digital pin 1 (Arduino Tx)

But remember, you load your code using these pins too. Arduino has a "USB-to-Serial" IC on board that uses those two pins. So now two entities trying to use those same pins (U2S and BT) i.e. you will have to disconnect U2S connections:

[![enter image description here][2]][2]

The above image is a snippet from the Arduino schematic. One way to disconnect those connections is to remove those two resistors. But then again, next time you want to load your code, you won't be able to use USB cable anymore.

So, I will suggest you to use **SoftwareSerial** and choose any other two pins for Bluetooth Module and change in the code wherever you were communicating with the Processing using Serial.println(). replace that with SoftwareSerial println().

  [1]: https://www.amazon.com/DSD-TECH-HC-06-Bluetooth-Raspberry/dp/B074J5WMH1/ref=sr_1_4?keywords=HC-06+Bluetooth&qid=1584136558&sr=8-4
  [2]: https://i.stack.imgur.com/SldTw.png


message:
Running commands from string

I have a string:

    string s="digitalWrite(8,LOW);"
Is there any way to run it as a code?

body:
This is actually pretty simple:

```c++
if (s == "digitalWrite(8,LOW);") {
    digitalWrite(8,LOW);
}
```

Obviously, it will not work is `s` contains any other string... If you
want something more general, that is able to interpret a wide range of
possible commands, you will have to define a language, and write an
interpreter for that language. From the example you give, it seems you
would like your language to look like C++. This is most likely a bad
design choice. If you want an interpreter that understands the whole C++
language: forget it. You will never fit something this big into an
Arduino Uno.

Here is, for inspiration, [a very simple interpreter][interpreter] I
wrote that understand the following commands:

    mode <pin> <mode>: pinMode()
    read <pin>: digitalRead()
    aread <pin>: analogRead()
    write <pin> <value>: digitalWrite()
    awrite <pin> <value>: analogWrite()
    echo <value>: set echo off (0) or on (1)

You can use it a basis for writing your custom interpreter. Otherwise
you can do a Web search for “Arduino interpreter”: you should be able to
find interpreters implementing a wide variety of languages, including
compact binary languages ([Firmata][]), [Forth][] ([another one][]),
[Lisp][], [Basic][], and even [a C-like language][c].

[interpreter]: https://gist.github.com/edgar-bonet/607b387260388be77e96
[Firmata]: https://github.com/firmata/arduino
[Forth]: https://flashforth.com/
[another one]: https://github.com/tschaer/tofish
[Lisp]: http://www.ulisp.com/
[Basic]: https://github.com/robinhedwards/ArduinoBASIC
[c]: https://n.mtng.org/ele/arduino/iarduino.html


message:
How do I make a character array scanner properly?

I start with this:

```c++
char delay_chars[10];
```

then I have a stream of incoming characters that I need to assign like this:

```c++
['I', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'i', 'e']
```

I can do that, but then more characters come in so I need it like this:

```c++
[' ', 'l', 'o', 'v', 'e', ' ', 'p', 'i', 'e', ' ']
['l', 'o', 'v', 'e', ' ', 'p', 'i', 'e', ' ', 'a']
['o', 'v', 'e', ' ', 'p', 'i', 'e', ' ', 'a', 'n']
['v', 'e', ' ', 'p', 'i', 'e', ' ', 'a', 'n', 'd']
['e', ' ', 'p', 'i', 'e', ' ', 'a', 'n', 'd', ' ']
[' ', 'p', 'i', 'e', ' ', 'a', 'n', 'd', ' ', 'c']
['p', 'i', 'e', ' ', 'a', 'n', 'd', ' ', 'c', 'a']
['i', 'e', ' ', 'a', 'n', 'd', ' ', 'c', 'a', 'k']
['e', ' ', 'a', 'n', 'd', ' ', 'c', 'a', 'k', 'e']
```

You get the idea. I don't know how I can remove the first character of a char array (like I do with a String, `remove(0, 1)`) and I don't know how to add a new element at the end.

If I had to guess, I'd make a loop that will reassign the index of each character one step back or something like that but I'm not sure if that's how I should do it.

body:
> If I had to guess, I'd make a loop that will reasign the index of each character one step back or something like that but I'm not sure if that's how I should do it.

Yep, that's pretty much it...

Here's how I do it:

```c++
char data[10];

if (Serial.available()) {
    char inch = Serial.read();
    for (int i = 0; i < 9; i++) {
        data[i] = data[i+1];
    }
    data[9] = inch;
}
```

Every incoming character gets added to the end of the array after everything else has been shuffled down one place.


body:
You can use [SerialTransfer.h][1] to automatically packetize and parse your data for inter-Arduino communication without the headace. The library is installable through the Arduino IDE and includes many examples.

Here are the library's features:

> This library:
>
>  - can be downloaded via the Arduino IDE's Libraries Manager (search "SerialTransfer.h")
>  - works with "software-serial" libraries
>  - is non blocking
>  - uses packet delimiters
>  - uses consistent overhead byte stuffing
>  - uses CRC-8 (Polynomial 0x9B with lookup table)
>  - allows the use of dynamically sized packets (packets can have payload lengths anywhere from 1 to 255 bytes)
>  - can transfer bytes, ints, floats, and even structs!!

Example TX Arduino Sketch:

    #include "SerialTransfer.h"

    SerialTransfer myTransfer;

    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
      myTransfer.begin(Serial1);
    }

    void loop()
    {
      myTransfer.txBuff[0] = 'h';
      myTransfer.txBuff[1] = 'i';
      myTransfer.txBuff[2] = '\n';

      myTransfer.sendData(3);
      delay(100);
    }

Example RX Arduino Sketch:

    #include "SerialTransfer.h"

    SerialTransfer myTransfer;

    void setup()
    {
      Serial.begin(115200);
      Serial1.begin(115200);
      myTransfer.begin(Serial1);
    }

    void loop()
    {
      if(myTransfer.available())
      {
        Serial.println("New Data");
        for(byte i = 0; i < myTransfer.bytesRead; i++)
          Serial.write(myTransfer.rxBuff[i]);
        Serial.println();
      }
      else if(myTransfer.status < 0)
      {
        Serial.print("ERROR: ");
        Serial.println(myTransfer.status);
      }
    }

You can easily edit the above example code to transfer `['I', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'i', 'e']` instead of `['h', 'i', '\n']`.

  [1]: https://github.com/PowerBroker2/SerialTransfer


message:
Summarizing a repetitive code in a void loop function

How can I summarize dozens of code lines for blinking a red LED in Arduino Rich Shield? Is there a way or method to eliminate at least half of the code for repetitive scenarios?

    const int redPin = 4;

    void setup()
    {
     pinMode(redPin, OUTPUT);
    }

    void loop()
    {
      digitalWrite(redPin, HIGH);
      delay(250);
      digitalWrite(redPin, LOW);
      delay(250);
      digitalWrite(redPin, HIGH);
      delay(250);
      digitalWrite(redPin, LOW);
      delay(250);
      digitalWrite(redPin, HIGH);
      delay(250);
      digitalWrite(redPin, LOW);
    }

body:
    void loop()
    {
      digitalWrite(redPin, HIGH);
      delay(250);
      digitalWrite(redPin, LOW);
      delay(250);
    }

I'm not quite sure what you're after but this is shorter and would get you equivalent results.  Since loop is going to repeat anyway, there's no need to repeat yourself inside loop.

Per the comments, not that this is particularly useful...

    const int redPin = 4;

    int counter = 0;

    void setup()
    {
     pinMode(redPin, OUTPUT);
    }

    void loop()
    {
      if(counter < 4) {
         digitalWrite(redPin, HIGH);
         delay(250);
         digitalWrite(redPin, LOW);
         delay(250);
         counter++;
      }
    }


message:
WiFi.begin doesn't work with ArduinoJson's const char* output

I'm using [ArduinoJson][1] to parse a file full of JSON strings that contain the SSID and password for the registered networks. I have a little web interface that runs in soft AP mode so you can scan for networks and add them to the file. Adding networks to the file works fine, but reading them back and using them as input for WiFi.begin doesn't work. It moves to status code 1, which means it failed to find a network with that SSID.

<strike>I have compared the value of the result of `const char* ssid = networks[network]["ssid"];` with `const char* _ssid = "MySSID";` using strcmp and it returns 0, so I can't figure out why it's not working. It works if I replace `networks[network]["ssid]` with my SSID (though I need to replace the password with the string literal as well, otherwise it stays on status code 6, disconnected).

I can't figure out what it is about ArduinoJson, but it seems that the result of grabbing a string doesn't return a string that is formatted correctly for WiFi.begin, but it satisfies strcmp?</strike>

__Edit:__
I modified the code quite a bit in an effort to get it to work. I am no longer passing the ArduinoJson object, I'm now passing a struct with the data, and it still doesn't work. Is this the work of some advanced c++ constants/pointers stuff that I don't seem to understand?

main.cpp:
```c++
#include <ArduinoJson.h>
#include <ESPAsyncWebServer.h>
#include <ESPmDNS.h>
#include <SPIFFS.h>
#include <vector>
#include <elapsedMillis.h>

#include "config.h"
#include "restserver.h"
#include "scanwifiserver.h"

AsyncWebServer *Server = new AsyncWebServer(80);

ScanWifiServer *scanWifi;
RestServer *restServer;

struct Network {
 const char* ssid;
 const char* password;
};

std::vector<Network> readAP(fs::FS &fs) {
 //fs.remove("/ap.txt");
 File file = fs.open("/ap.txt");
 std::vector<Network> networks;
 if (!file) {
#ifdef DEBUG
  Serial.println("Failed to open file for reading");
#endif
  return networks;
 }

 while (file.available()) {
  DynamicJsonDocument n(JSON_CAPACITY);
  auto s = file.readStringUntil('\n');
  deserializeJson(n, s);
  struct Network network = {n["ssid"], n["password"]};
  networks.push_back(network);
  Serial.println(networks.back().ssid);
 }

 file.close();
 return networks;
}

void setup() {
#ifdef DEBUG
 Serial.begin(BAUDRATE);
 delay(2000);
#endif

 SPIFFS.begin();
 auto networks = readAP(SPIFFS);
 if (networks.size() > 0) {
  Serial.println("Networks:");
  int network = 0;
  Serial.println(networks.size());
  while (WiFi.status() != WL_CONNECTED && network < networks.size()) {
   const char* ssid = networks[network].ssid;
   const char* password = networks[network].password;
   Serial.printf("%s, %s\n", ssid, password);

   WiFi.begin(ssid, password);

   while (WiFi.status() != WL_CONNECTED) {
    if (WiFi.status() == WL_CONNECT_FAILED || WiFi.status() == WL_NO_SSID_AVAIL)
     break;
    delay(500);
    Serial.print(WiFi.status());
   }
   Serial.println("");
   network++;
  }
  if (WiFi.status() == WL_CONNECTED) Serial.println("Connected");
  else networks.clear();
 }
 if (networks.size() == 0) {
  Serial.println("Starting ScanWifiServer");
  WiFi.mode(WIFI_AP);

  scanWifi = new ScanWifiServer(Server);

  Server->begin();

  MDNS.begin("grow");
  MDNS.addService("http", "tcp", 80);
 }
}

void loop() {}

```

  [1]: https://arduinojson.org/

body:
I found the solution myself. I switched from using `struct Network network = {n["ssid"], n["password"]};` to declare the struct and const char pointers to using char arrays and `strcpy`

```c++
struct Network network;
strcpy(network.ssid, n["ssid"]);
strcpy(network.password, n["password"]);
```

Seems like the pointers were getting freed or something right at the same time that I tried to use the value to connect to the network?


message:
connected between 2 arduino

i want to connect  SPI 2 arduino master and slave through the MUX , to write  and read in external memory , when the master write in memory slave read .
pls help .
code to master

```c++
#include <SPI.h>
//-------FM------------------
#define WENB 0x06
#define RDSR 0x05
#define WRSR 0x01
#define PPROGRAM 0x02
#define SERASE 0x20
#define BERASE 0xd8
#define READ 0x03
#define RDSCUR 0x2B
#define CERASE 0x60//or 0xC7

//------------Specify the address-----------
int address = 0x00ff0000;
byte x, Y;
int IN = 5;
int SS1 = 9;
/*char data[]=("don't be afraid ");
char recived[15];*/
//--------------------------
void setup() {
 //------------------------------------------
 // pinMode(EN,OUTPUT);
 pinMode ( SS, OUTPUT ); //ss pin 10
 pinMode ( SS1, OUTPUT );
 digitalWrite ( SS1, HIGH );
 pinMode ( IN, OUTPUT );
 digitalWrite ( IN, LOW ); // MUX connect A
 //digitalWrite(CS,low);
 Serial.begin ( 9600 );
 SPI.begin();//start the SPI connection with the flash memory
 SPI.setClockDivider ( SPI_CLOCK_DIV8 );
 SPI.setBitOrder ( MSBFIRST );
 digitalWrite ( SS, HIGH );
 delay ( 10 );
 //-------erase the sector--//-----------
 digitalWrite ( SS, LOW );
 SPI.transfer ( WENB );
 digitalWrite ( SS, HIGH );
 //-------------------------------------
 digitalWrite ( SS, LOW );
 SPI.transfer ( SERASE );
 SPI.transfer ( ( address >> 32 ) & 0xff );
 SPI.transfer ( ( address >> 16 ) & 0xff );
 SPI.transfer ( ( address >> 8 ) & 0xff );
 SPI.transfer ( address & 0xff );
 digitalWrite ( SS, HIGH );
 delay ( 5000 );
 //------------------------------------------
 //Serial.println("okay fine")
 //-----Program Data Into Memory Array-----.
 //-----------interrupts the slave----------
 /* digitalWrite(SS1,LOW);
  SPI.transfer(0xff);//are you there?
  digitalWrite(SS1,HIGH);
  delay(1000);

  digitalWrite(IN,HIGH);*/
}

void loop()

{
 char c;
 int i = 0;
 char data[] = "Hello!:";
 char recived[7];
 byte x;
 //----------Enable the write in the memory-----.
 digitalWrite ( SS, LOW );
 SPI.transfer ( WENB );
 digitalWrite ( SS, HIGH );
 delay ( 20 );
 //-----Program Data Into Memory Array-----.
 digitalWrite ( SS, LOW );
 SPI.transfer ( PPROGRAM );
 SPI.transfer ( ( address >> 32 ) & 0xff );
 SPI.transfer ( ( address >> 16 ) & 0xff );
 SPI.transfer ( ( address >> 8 ) & 0xff );
 SPI.transfer ( address & 0xff );

 for ( int i = 0; i < sizeof ( data ); i++ ) {
  SPI.transfer ( data[i] );
  // Serial.print(data[i]);
 }

 // disable Slave Select
 digitalWrite ( SS, HIGH );
 //--------------------------------------------
 delay ( 1000 );
 //--------------------------- ----------
 i = 0;
 Serial.print ( "It's okay saved: " );

 while ( data[i] != NULL ) {
  Serial.println ( data[i] );
  i++;
 }

 // delay(100);
 //-----------interrupts the slave----------
 digitalWrite ( SS1, LOW );
 SPI.transfer ( 0xff ); //are you there?
 digitalWrite ( SS1, HIGH );
 delay ( 1000 );
 digitalWrite ( IN, HIGH ); // MUX connect B
}
```

code to slave

```c++
#include <SPI.h>
//-------FM------------------
#define WENB 0x06
#define RDSR 0x05
#define WRSR 0x01
#define PPROGRAM 0x02
#define SERASE 0x20
#define BERASE 0xd8
#define READ 0x03
#define RDSCUR 0x2B
#define CERASE 0x60//or 0xC7

//------------Specify the address-------------
int address = 0x00ff0000;

int SS1 = 9;
char data[] = "Hello!:";
char buff[7];

byte slave;
volatile bool process;
//----------------config slave----------------
void setup() {
 //pinMode(IN,OUTPUT);
 pinMode ( SS, OUTPUT ); //SS pin 10
 pinMode ( MISO, OUTPUT );
 pinMode ( SS1, INPUT );
 pinMode ( MOSI, INPUT );
 //--------------------------------------------------
 Serial.begin ( 9600 );
 ///SPCR |= bit (SPE);
 SPI.begin();//start the SPI connection with the flash memory
 SPI.setClockDivider ( SPI_CLOCK_DIV8 );
 SPI.setBitOrder ( MSBFIRST );
 // digitalWrite(SS,HIGH);
 //-------------master interrupts the slave----------------------------------------------
 // now turn on interrupts
 // SPCR |=bit(SPIE);
 //SPCR |=bit(SPE); //set SPE bit at the SPCR(spi control register) to enable SPI
 SPI.attachInterrupt();
}

ISR ( SPI_STC_vect ) {
 slave = SPDR;

 if ( slave = 0xff ) {
  pinMode ( MISO, INPUT );
  // pinMode(SS1,INPUT);
  pinMode ( MOSI, OUTPUT );
  //digitalWrite(IN,HIGH);
  digitalWrite ( SS, LOW );
  SPI.transfer ( READ );
  SPI.transfer ( ( address >> 32 ) & 0xff );
  SPI.transfer ( ( address >> 16 ) & 0xff );
  SPI.transfer ( ( address >> 8 ) & 0xff );
  SPI.transfer ( address & 0xff );

  for ( int n = 0; n < sizeof ( data ); n++ ) {
   data[n] = SPI.transfer ( 0 );
   Serial.print ( data[n] );
  }

  digitalWrite ( SS, HIGH );
 }
}
```

body:
Having a line from Arduino 1 to Arduino 2 to indicate that Arduino 2 should do something is sufficient.

Simple way: a line that is an input on both sides with internal pullups turned on.  Both sides monitor it.

When Arduino 1 wants to write, it checks to make sure the line is high, then it makes its pin an output and pulls it low, and when done releases it by going back to an input (using pinMode() command).

When Arduino 2 see the low, it waits for it to go high, then makes its input and output and pulls it low until it is done reading.

Arduino 1 sees the low and holds off on any writing until it goes back high again.

This is known as arbitration, and is an example of one simple method.


message:
Interrupting a servo sweep with a force sensor

this is my first time dealing with arduinos and I have a school assignment. I have a servo and a force sensor. When **"1"** (a character, not an integer) is typed in the serial monitor, the servo needs to rotate 180 degrees but can be interrupted when the force sensor sends a value over let's say 300. And when **"0"** is typed in, the servo goes back to its initial position.
I have been trying really hard figuring this out.

I basically need to exit a loop when the analog value exceeds 300.

here's my code:

```
#include <Servo.h>
Servo myservo;

int initpos; //initial position of the servo before the sweep (this doesn't change)
int angle; //used to store the servo angle value (this changes)
char code; //the value entered in the serial monitor
int force; //value of the analog force sensor

void setup()
{
  initpos = 10;
  Serial.begin(9600);
  myservo.attach(4);

  myservo.write(170); // makes the servo sweep(absolutelly useless for my project but I left it there)
  delay(500);         //
  myservo.write(10);  //
  delay(500);         //

  code = Serial.read();

}

void loop()
{

  if(Serial.available())
  {

    angle = initpos;
    force = analogRead(A1);
    Serial.println(force);

    for(angle = 0; angle < 180; angle += 1)
    {
      if (code == "1" and force <= 300)
      {
        angle += 1;
        Serial.print(code);
        myservo.write(angle);
      }

      else if(code == "0")
      {
        myservo.write(initpos);
      }
    }

  }
}
```
any help is deeply appreciated and if there is already a topic on this please redirect me to it

body:
I've written this code without access to a compiler,
so there might be errors. Use it as an idea how to solve the quest. Hopefully the comments are helpful. Don't hesitate to ask if you do not understand or correct me if you see an error.

    #include <Servo.h>

    Servo myservo;

    // end positions of the servo
    // declared as constant values
    const int minPos = 10;
    const int maxPos = 180;

    int servoAngle;

    int force;
    char code;

    void setup()
    {
      Serial.begin(9600);

      myservo.attach(4);
      // move the servo to minPos
      // or whatever you want/need
      servoAngle = minPos;
      myservo.write( servoAngle );

      // PPK: keep code as simple as possible -> sweep removed

      // PPK: removed - this makes no sense here
      // code = Serial.read();
    }

    void loop()
    {
      // PPK: here you check if data is available (I added "> 0")
      if( Serial.available() > 0 )
      {
        // PPK: but you did not read the data
        // Let's do it
        char newCode = Serial.read();
        If ( newCode == '0' || newCode == '1' )
        {
          // only "0" and "1" are valid codes
          code = newCode;
        }
      }

      if ( code == '0' && servoAngle > minPos )
      {
        servoAngle--;
        myservo.write( servoAngle );
      }
      else if ( code == '1' && servoAngle < maxPos )
      {
        force = analogRead( A1 );
        Serial.println( force );
        if ( force > 300 )
        {
          servoAngle--;

          // PPK: the next line is only necessary if you want the
          // servo to go towards the min position
          // if a force > 300 is detected
          // remove the line if you wish to
          // hold the servo at the position where
          // the force exceeds 300
          code = '0':
        }
        else
        {
          servoAngle++;
        }
        myservo.write( servoAngle );
      }
      // a little delay to slow down the servo
      // remove it if you want
      delay( 10 );
    }

**EDIT**

If you intend to stop the servo if `force > 300`, you can add a flag that indicates the exceptional state.

    #include <Servo.h>

    Servo myservo;

    const int minPos = 10;
    const int maxPos = 180;

    int servoAngle;

    int force;
    char code;
    int flagServoStopped = 0;

    void setup()
    {
      Serial.begin(9600);

      myservo.attach(4);
      servoAngle = minPos;
      myservo.write( servoAngle );
    }

    void loop()
    {
      if( Serial.available() > 0 )
      {
        char newCode = Serial.read();
        If ( newCode == '0' || newCode == '1' )
        {
          code = newCode;
        }
      }

      if ( flagServoStopped == 1 && code == '1' )
      {
        // The servo is frozen as long as the stop flag is set and
        // you have not entered a '0'.
        // leave the loop
        return;
      }

      // in case `code = '0'`, reset the flag if it is set.
      flagServoStopped = 0;

      if ( code == '0' && servoAngle > minPos )
      {
        servoAngle--;
        myservo.write( servoAngle );
      }
      else if ( code == '1' && servoAngle < maxPos )
      {
        force = analogRead( A1 );
        Serial.println( force );
        if ( force > 300 )
        {
          flagServoStopped = 1;
        }
        else
        {
          servoAngle++;
          myservo.write( servoAngle );
        }
      }
      delay( 10 );
    }


message:
Having issue with a redeclaration as a different kind of symbol

Been struggling with this for a few days and I suspect that i have several issues but I cannot find them.

Project: Need a serial count that counts by 5-50 and a button interrupt should trigger a display of the current time and then continue counting.

Issue: Cannot complete compiling because my "void rtcTime()" is saying I am redeclared as different kind of symbol.

Any help the community can provide is greatly appreciated.

Code:

    // Date and time functions using a DS1307 RTC connected via I2C and Wire lib
    #include "RTClib.h"
    #include <Wire.h>

    RTC_DS1307 rtc;

    int count = 5;
    int rtcTime = 0;
    int pin = 0;

    char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

    void setup (){

      pinMode(2, INPUT);

      rtc.begin();

      while (!Serial); // for Leonardo/Micro/Zero

      Serial.begin(9600);

      if (! rtc.begin()) {
       Serial.println("Couldn't find RTC");
       while (1);
          }

      if (! rtc.isrunning()) {
        Serial.println("RTC is NOT running!");
        // following line sets the RTC to the date & time this sketch was compiled
        // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
        // This line sets the RTC with an explicit date & time, for example to set
        // January 21, 2014 at 3am you would call:
        // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
         }

         attachInterrupt(pin, rtcTime, RISING);
    }

    void loop()
    {
      // Count X5 on Serial Monitor

      if (count > 50)
        {
        count=5;
        Serial.println(count);
        }

       else if (count<50)
        {
        count=count+5;
        Serial.println(count);
        delay(1000);
         }
      }

    void rtcTime() {
        DateTime now = rtc.now();

        Serial.print(now.year(), DEC);
        Serial.print('/');
        Serial.print(now.month(), DEC);
        Serial.print('/');
        Serial.print(now.day(), DEC);
        Serial.print(" (");
        Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
        Serial.print(") ");
        Serial.print(now.hour(), DEC);
        Serial.print(':');
        Serial.print(now.minute(), DEC);
        Serial.print(':');
        Serial.print(now.second(), DEC);
        Serial.println();

        }

Error Message:

> Arduino: 1.8.10 (Mac OS X), Board: "Arduino/Genuino Mega or Mega 2560,
> ATmega2560 (Mega 2560)"
>
> ds1307_workingCopy_Mod5:60:14: error: 'void rtcTime()' redeclared as
> different kind of symbol  void rtcTime() {
>               ^ /Users/kiko/Documents/Arduino/ds1307_workingCopy_Mod5/ds1307_workingCopy_Mod5.ino:9:5:
> note: previous declaration 'int rtcTime'  int rtcTime = 0;
>      ^~~~~~~ /Users/kiko/Documents/Arduino/ds1307_workingCopy_Mod5/ds1307_workingCopy_Mod5.ino:
> In function 'void setup()':
> /Users/kiko/Documents/Arduino/ds1307_workingCopy_Mod5/ds1307_workingCopy_Mod5.ino:38:42:
> warning: invalid conversion from 'int' to 'void (*)()' [-fpermissive]
>       attachInterrupt(pin, rtcTime, RISING);
>                                           ^ In file included from sketch/ds1307_workingCopy_Mod5.ino.cpp:1:0:
> /Users/kiko/Desktop/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Arduino.h:150:6:
> note:   initializing argument 2 of 'void attachInterrupt(uint8_t, void
> (*)(), int)'  void attachInterrupt(uint8_t, void (*)(void), int mode);
>       ^~~~~~~~~~~~~~~ /Users/kiko/Documents/Arduino/ds1307_workingCopy_Mod5/ds1307_workingCopy_Mod5.ino:
> In function 'void rtcTime()': ds1307_workingCopy_Mod5:60:14: error:
> 'void rtcTime()' redeclared as different kind of symbol  void
> rtcTime() {
>               ^ /Users/kiko/Documents/Arduino/ds1307_workingCopy_Mod5/ds1307_workingCopy_Mod5.ino:9:5:
> note: previous declaration 'int rtcTime'  int rtcTime = 0;
>      ^~~~~~~ Multiple libraries were found for "RTClib.h"  Used: /Users/kiko/Documents/Arduino/libraries/RTClib-1.3.3  Not used:
> /Users/kiko/Documents/Arduino/libraries/RTCLib_by_NeiroN Multiple
> libraries were found for "Wire.h"  Used:
> /Users/kiko/Desktop/Arduino.app/Contents/Java/hardware/arduino/avr/libraries/Wire
> exit status 1 'void rtcTime()' redeclared as different kind of symbol
>
> This report would have more information with "Show verbose output
> during compilation" option enabled in File -> Preferences.

body:
The Arduino builder doesn't create forward declarations of functions for functions used in code as callbacks. It has something to do with the occurrence of the name without the usual form of function call.

You could move the function rtcTime before setup() so it is visible for the use as parameter in attachInterrupt or you can create a forward declaration for the compiler. Your attempt to make the name of the function valid was to create a variable with this name. This way you created the error of duplicate name.

Add

    void rtcTime();

before setup() function and remove `int rtcTime = 0;`


message:
Problem to Setting up i2c OLED wemos D1 mini shiled (64*24)

*Hi*

*I used this shield before well. But it didn't work when I wanted to work with him last night!*

#*this is my wireing :*

[![enter image description here][1]][1]

*Now I want to know how to **test** that it is healthy? Is **i2c address missing or not**?*

*I tried **this code** to **find i2c address** but no answer appeared on Arduino Serial monitor !! nothing ..*

*and i uploaded any more example code on Uno but OLED not worked .*

    //     ~~~~~~~~~~~ i2c Address Scanner ~~~~~~~~~~~

    #include <Wire.h>

    void setup() {
    Serial.begin (115200);

    while (!Serial) {}

    Serial.println ();
    Serial.println ("I2C scanner. Scanning ...");
    byte count = 0;

    Wire.begin();
    for (byte i = 8; i < 120; i++){
    Wire.beginTransmission (i);
    if (Wire.endTransmission () == 0){
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);
       }
      }
      Serial.println ("Done.");
      Serial.print ("Found ");
      Serial.print (count, DEC);
      Serial.println (" device(s).");
      }
      void loop() {}

   .
   .

   *What is the problem ?*

  [1]: https://i.stack.imgur.com/ZHk00.jpg

body:
The main problem is, that the module does not get any supply voltage. You connected the Unos 5V to the OLED boards 5V. But this pin doesn't seem to be connected on the OLED shield. It is marked with 5V there, because this board is a shield to be stacked onto the Wemos D1. When you do this, you have 5V on this pin from the Wemos and can access it on the OLED shield for adding further components. (This is the principle of shields. Making even unused pins available on the shield, so that these pins don't get covered by the shield)

The shield needs to be supplied through the 3.3V pin, as it is a 3.3V device and it does not have an own voltage regulator (see the [schematics of the shield][1]).

Thus the shield cannot be found, because it is not turned on. It does not have a supply voltage.

---

That said, you may also get into trouble because of the communication voltage. The Uno works with 5V on the I2C lines, while the OLED shield works with 3.3V. The shield might get damaged by the higher voltage. The schematics the shield don't mention part names, so I cannot know, if they are 5V tolerant (there are 2 ICs in the schematics).

If the shield is not 5V tolerant on the I2C lines, you need to use a bidirectional level converter for both lines (or you can build your own with 2 MOSFETS for each line).

  [1]: https://docs.wemos.cc/en/latest/_static/files/sch_oled_v2.1.0.pdf