message:
How do I make my LCD screen scroll text while allowing for button input?

Here's what I want my code to do: This is part of a tea infusing project that would automate the steeping of tea, part of this is initially having a selection of either Black/Herbal tea or White/Green tea, this will then set off several other factors down the timeline.
I want my LCD screen to display and scroll "Please select a tea" while still being able to take in pushbutton input.

I've been doing this all day, and I've tried several things. I firstly tried using a normal delay function so my text could scroll properly, but the problem with that is that it halts all the code and doesn't allow for any other input, so I quickly found millis() was likely what I needed to use. However, when I try to apply it to this specific example, it just scrolls all my text extremely quickly through the LCD.
Perhaps I'm being stupid and ignoring something obvious, but please let me know.

```

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

const int black_herbal_osb = 2;

int black_select;

//Timing
unsigned long prev_millis;
unsigned long current_millis;
const unsigned long LCD_delay = 500;

void setup() {

  //Tea selection buttons
  pinMode(black_herbal_osb, INPUT);

  //LCD screen setup
  lcd.init();
  lcd.backlight();

}

void loop() {

  lcd.autoscroll();
  lcd.setCursor(16, 0);
  lcd.print("Please");

  current_millis = millis();

  black_select = digitalRead(black_herbal_osb);

  if (black_select != HIGH) {

    if (current_millis - prev_millis >= LCD_delay) {
      lcd.print(" select ");
      prev_millis = current_millis;
    }
    if (current_millis - prev_millis >= LCD_delay * 2) {
      lcd.print("a ");
      prev_millis = current_millis;
    }
    if (current_millis - prev_millis >= LCD_delay * 3) {
      lcd.print("tea ");
      prev_millis = current_millis;
    }
  }

  else if (black_select == HIGH) {
    lcd.clear();
    lcd.autoscroll();
    lcd.setCursor(16, 0);
    lcd.print("Black/Herbal ");
    delay(500);
    lcd.print("tea ");
    delay(500);
    lcd.print("selected");
    delay(2000);
    lcd.noAutoscroll();
    lcd.clear();
  }

}

body:
See [my answer to a similar question][1] - about motors but the idea is the same. You call a function for each piece of the job that needs to be done. The function itself decides whether it needs to be done yet, and if so, does it and returns, otherwise it just returns. The loop() function just calls all your other action functions and *does nothing else* -- all of the real work takes place in those functions.

Looking at your scrolling code, I think one function could print successive pieces of the message by remembering what did last. Another could read and debounce the button(s) and save its/their state.

And once you get to controlling the infusing process, one (or maybe more) functions could be used to control that.

  [1]: https://arduino.stackexchange.com/questions/60759/how-to-rotate-two-or-more-steppers-simultaneously-by-giving-array-of-angles/66380#66380


sender: user

sender: assistant

body:
I figured it out. I was thinking about it all wrong, I just needed to figure out how the scrolling worked for the LCD and the rest was much easier. Only current issue with my code is that on the initial scroll of "Please select a tea" right after the "Booting..." process, it doesn't seem to start at (16,0) but nearer to the front which makes it not super easy to read initially but it corrects itself after a single scroll.

Here's the code for those interested:

```
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

const int black_herbal_pin = 2;
const int white_green_pin = 3;
const int LCD_scroll = 200;

int black_select;
int white_select;

unsigned long current_millis = 0;    // stores the value of millis() in each iteration of loop()
unsigned long previous_scroll_millis = 0;

void setup() {
  Serial.begin(9600);
  //Tea selection buttons
  pinMode(black_herbal_pin, INPUT);
  pinMode(white_green_pin, INPUT);

  //LCD screen setup
  lcd.init();
  lcd.backlight();

}

void loop() {

  if (current_millis == 0) {
    lcd.setCursor (0, 0);
    lcd.print("Booting");
    delay(500);
    lcd.print(".");
    delay(500);
    lcd.print(".");
    delay(500);
    lcd.print(".");
    delay(1000);
    lcd.clear();
  }

  lcd.setCursor(16, 0);
  lcd.print("Please select a tea ");

  current_millis = millis();
  for (int position_counter = 0; position_counter < 16; position_counter++) {

    if (current_millis - previous_scroll_millis >= LCD_scroll) {
      lcd.scrollDisplayLeft();

      previous_scroll_millis += LCD_scroll;
    }
  }

  if (digitalRead(black_herbal_pin) == HIGH) {
    lcd.clear();
    lcd.setCursor (16, 0);
    lcd.print("Black/Herbal tea selecte");
    for (int position_counter = 0; position_counter < 26; position_counter++) {
      lcd.setCursor (0, 0); //This part is likely not necessary for you as it seems to be a bug within my own LCD
      lcd.print("d"); // without this it prints "d" on the second row
      lcd.scrollDisplayLeft();
      delay (150);
    }

    delay(2000);
    lcd.clear();
  }

  if (digitalRead(white_green_pin) == HIGH) {
    lcd.clear();
    lcd.setCursor (16, 0);
    lcd.print("White/Green tea selected");
    for (int position_counter = 0; position_counter < 26; position_counter++) {
      lcd.scrollDisplayLeft();
      delay (150);
    }

    delay(2000);
    lcd.clear();
  }

}


message:
Timer question: Phase Correct PWM at specific frequency

I am trying to create a sinusoidal wave segmented in 64 **Frame**, each holding a **Duty cycle** precisely varying from 0x00 to 0xff. This is for an Arduino Nano.

I have trouble understanding the following:

 - Which Wave Generator Mode and Matches will cause an interrupt at the constant **Frame** as well as help do a phase correct/fast PWM for the varying **Duty Cycle**?
 - How to tell which pin to use? I guess OC0B means Pin5 [according to Pin Mapping](http://brittonkerin.com/cduino/pin_map.html) but I'm not sure I truly understand.

This is what I have for the moment.

    const byte waveFrame = 126;
    const byte wave[]    = {
        0x80,0x98,/*a total of 64 values*/,0x67
    };
    byte frame = 0;
    void setup(){
        pinMode(3,OUTPUT);
        noInterrupts();
        TCCR0A = (1<< WGM00)  // Phase correct PWM with top as OCR0A
               | (1<<COM0A0)  // Toggle OC0A on match
               | (1<<COM0B1); // Clear/Set OC0B on Compare Match when up/down-counting.
        TCCR0B = (1<<  CS01); // Prescaler of 8 (16MHz/8= 2MHz)
        TCNT0  = 0;           // Counter restarted
        OCR0A  = waveFrame;   // Constant frequency/64 for each frame
        OCR0B  = 0;           // Duty Cycle
        interrupts();
    }
    ISR(TIMER2_COMPA_vect){
        OCR0B = wave[frame & 0x3f]; //Rolls around
        frame++;
    }

Thank you! I've lost a little bit of hair on this.

body:
> pinMode(3,OUTPUT);

Pin 3 on the Nano is `OC2B`. It's PWM is controlled by Timer 2. You
want to use pin 5 (`OC0B`), since you are using Timer 0. Or
switch to Timer 2.

> Phase correct PWM with top as OCR0A

Note that this is the description of mode 5. If you want this mode, you
have to set both the bit `WGM00` in `TCCR0A` (which you did)
and the bit `WGM02` in `TCCR0B` (which you didn't). Here you have set
mode 1: phase correct PWM with top = 0xff.


message:
Convert Binary to char

I'm reading a text file saved on my ESP8266 device (using `LittleFS`).

    while (myFile.available()) {
         Serial.write(myFile.read());
        }

My goal is to save file content ( each line ) to a `String` / `char` array.
`myFile.read()` returns a binary - and I'm looking for a quick and elegant way to do so ( as in `Serial.write` which converts it to text ).

Guy

body:
`myFile.read()` returns one character. That character can be represented as a number (such as 65 for 'A') or a character, or whatever you want. Everything is just a number.

Letters are just our personal representation of certain numbers as humans. You could think of it as the numbers represented in base 256, where each value between 0 and 255 is assigned a unique symbol.

`Serial.write()` just passes that number verbatim to the computer which then maps it in the serial monitor to the corresponding letter in the ASCII table.

Thanks to the object-oriented and polymorphic nature of the Arduino API (see [C++ Polymorphism](https://www.w3schools.com/cpp/cpp_polymorphism.asp)) there is no difference between reading from a file and reading from serial. They all inherit the same `Stream` class that gives you the same functions regardless of what you're reading.

So you could, like Serial, read each byte from the file one at a time until you reach the line ending character(s) (`\n` for a Unix file, or `\r\n` for a Windows file) and append each to the end of a string (either a `String` object, which is frowned upon, though less so on more capable MCUs like the ESP8266 and ESP32, or a `char` array).

Alternatively you could use one of the helper functions of the `Stream` class, such as `readStringUntil()`, which reads an entire string up to (and discarding) the specified terminating character and returns a `String`.

However both those have problems when it comes to building up an array of all the results, especially if you don't know beforehand how many lines there are in the file - since in C++ arrays have a fixed size.

A better solution, if you really *do* want it all in RAM (see below), might be instead to, at first, forget the idea of lines and just read the entire file into memory. Once it is in memory you can read through the entire block of data counting the number of `\n` bytes (and add one if it doesn't end with `\n`). That will give you the number of lines in the file.

You can then allocate an array of pointers with the same number of entries as there are lines.

From there you can use `strtok()` on the data to split it into chunks on the `\n` bytes and assign each chunk to one of the pointers in your array.  That array then becomes a kind of index to the data.

But one has to ask... why do you want to store this data in RAM anyway? You have it in flash, and that is quite fast to access (not as fast as internal flash in a traditional MCU, but still many times faster than an SD card for example). If ease of navigating the data is your goal, maybe you should be thinking of better ways of storing your data. Depending on what that data is maybe a fixed size record based file structure using a `struct` to manipulate the data would be a better solution - then you can just seek to multiples of the record (or struct) size to almost instantly get to different entries in the file.

If it's textual data then maybe reading through the file and recording the file offsets of the start of each line in an array (note: two passes - one to count the lines for allocating the array and one for recording the offsets into the array) similar to the indexing of the data block described above would be a better solution. That way you're only storing 4 bytes per entry in your array rather than all the data. Seeking is instant (just seek to the offset stored in the array for the line you want) and you're not having to store all the data in RAM.


message:
Missing ACKs on I²C

I am using a GY-521 accelerometer as well as BMP280 pressure sensors via I²C on an ESP8266.

When I analyze I²C data with the oscilloscope, I can see missing ACKs on both of them as shown in the pictures.

Is that something to worry about or is it just normal, considering I bought cheap Chinese sensors?

[![Missing ACK on GY-521][1]][1]

[![Missing ACK on BMP280][2]][2]

My BMP280 code is this:

    // https://github.com/mahfuz195/BMP280-arduino-library
    #include <BMP280.h>
    BMP280 bmp280;

    #include "Wire.h"
    TwoWire i2c = TwoWire();

    // Hardware setup
    #define CLOCK_PIN D1
    #define DATA_PIN D2
    #define I2C_SPEED 400000

    // I²C response codes
    #define FOUND 0
    #define NORESPONSE 2

    bool sensorAvailableAt(byte address)
    {
       i2c.beginTransmission(address);
       byte response = i2c.endTransmission();
       return response == FOUND;
    }

    void stop(char* message){
      Serial.println(message);
      while(true);
    }

    void setup() {
      Serial.begin(115200);
      while(!Serial){} // Waiting for serial connection

      i2c.begin(DATA_PIN, CLOCK_PIN, I2C_SPEED);
      if (!sensorAvailableAt(0x76))
      {
        stop("BMP280 sensor not found");
      }

      if (bmp280.begin())
      {
        Serial.println("BMP280 init success");
      }
      else
      {
        stop("BMP280 initialization failed.");
      }
    }

    void loop() {
      double temperature;
      double pressure;
      bmp280.getTemperatureAndPressure(temperature, pressure);
      double sealevel = bmp280.sealevel(pressure, 800);

      Serial.print("Temperature: ");
      Serial.print(temperature,1);
      Serial.println(" °C");

      Serial.print("Pressure: ");
      Serial.print(pressure, 1);
      Serial.println(" mbar (absolute)");

      Serial.print("Pressure: ");
      Serial.print(sealevel);
      Serial.println(" mbar (sealevel, compensated for 800 m height)");

      delay(50);
    }

  [1]: https://i.stack.imgur.com/n7kjX.png
  [2]: https://i.stack.imgur.com/Hwfrl.png

body:
The NACK at the end of a master read/slave send transmission is normal expected behavior.

In I2C communication the acknowledgement is a possibility to react to send data. For example, when the slave sends a NACK while the master sends data to it, it might be, because it currently cannot process further data. Acknowledgement goes in both ways, depending on the direction of transmission. The reader always needs to acknowledge the data to mark a successful transmission. It is normal for the master to send a NACK on the end of it's reading cycle to mark, that it doesn't want to receive more data. While this isn't strictly logically needed (since the end of a transmission is marked by the master by a STOP or RESTART condition), it is done nonetheless.

I think I have also seen this behavior with the `Wire` library of Arduino. So it comes down to the implementation of the I2C protocol in your case. As your library simply uses the `Wire` library, the behavior is not part of it. The I2C protocol is implemented by `Wire`. You would see the same behavior in every sensor library, that uses the `Wire` library.

You can read more about the I2C protocol at [this site][1].

  [1]: https://i2c.info/i2c-bus-specification


message:
Code for 2 ultrasonic sensors

This is my code:

    int trigPin=13; //Sensor Trig pin connected to Arduino pin 13
    int echoPin=11;  //Sensor Echo pin connected to Arduino pin 11
    float pingTime;  //time for ping to travel from sensor to target and return
    float targetDistance; //Distance to Target in inches
    float speedOfSound=776.5; //Speed of sound in miles per hour when temp is 77 degrees.
    int trigPin1=2;
    int echoPin1=3;
    float pingTime1;  //time for ping to travel from sensor to target and return 1
    float targetDistance1; //Distance to Target in inches 1
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
      pinMode(trigPin1, OUTPUT);
      pinMode(echoPin1, INPUT);
    }

    void loop() {
      // put your main code here, to run repeatedly:

      digitalWrite(trigPin, LOW); //Set trigger pin low
      delayMicroseconds(2000); //Let signal settle
      digitalWrite(trigPin, HIGH); //Set trigPin high
      delayMicroseconds(15); //Delay in high state
      digitalWrite(trigPin, LOW); //ping has now been sent
      delayMicroseconds(10); //Delay in low state
      digitalWrite(trigPin1, LOW); //Set trigger pin low
      delayMicroseconds(2000); //Let signal settle
      digitalWrite(trigPin1, HIGH); //Set trigPin high
      delayMicroseconds(15); //Delay in high state
      digitalWrite(trigPin1, LOW); //ping has now been sent
      delayMicroseconds(10); //Delay in low state

      pingTime1 = pulseIn(echoPin1, HIGH);  //pingTime is presented in microceconds
      pingTime1=pingTime1/1000000; //convert pingTime to seconds by dividing by 1000000 (microseconds in a second)
      pingTime1=pingTime1/3600; //convert pingtime to hourse by dividing by 3600 (seconds in an hour)
      targetDistance1= speedOfSound * pingTime;  //This will be in miles, since speed of sound was miles per hour
      targetDistance1=targetDistance1/2; //Remember ping travels to target and back from target, so you must divide by 2 for actual target distance.
      targetDistance1= targetDistance*63360;    //Convert miles to inches by multipling by 63360 (inches per mile)
      pingTime = pulseIn(echoPin, HIGH);  //pingTime is presented in microceconds
      pingTime=pingTime/1000000; //convert pingTime to seconds by dividing by 1000000 (microseconds in a second)
      pingTime=pingTime/3600; //convert pingtime to hourse by dividing by 3600 (seconds in an hour)
      targetDistance= speedOfSound * pingTime;  //This will be in miles, since speed of sound was miles per hour
      targetDistance=targetDistance/2; //Remember ping travels to target and back from target, so you must divide by 2 for actual target distance.
      targetDistance= targetDistance*63360;    //Convert miles to inches by multipling by 63360 (inches per mile)

      Serial.println(targetDistance);

      Serial.println(targetDistance1);

      delay(100); //delay tenth of a  second to slow things down a little.
    }
Python code:

    import serial #Import Serial Library

    arduinoSerialData = serial.Serial('com3',9600) #Create Serial port object called arduinoSerialData

    while (1==1):
        if (arduinoSerialData.inWaiting()>0):
            myData = arduinoSerialData.readline()
            myData=str(myData)
            myData= myData.replace("b'",'')
            myData=myData.replace("\\r\\n'",'')
            if myData<"3":

                print( myData)

When I compile the sketch, it shows no error.But when I run the file in python, output=0.However, when they are run individually, python gives me a valid input.so is this code correct?Also, is there a way to call for the exact c++file in python?Thanks for the help!

body:
You are trying to measure with 2 ultrasonic sensors at once. You cannot do that so easily. You need to measure sequentially for 2 reasons:

1. The ultrasonic sensors might get confused by the others signal
2. You will miss the pulse of the one sensor, while you are reading the pulse of the other via `pulseIn()`.

So the order of actions is like this:

1. Trigger sensor 1
2. Read sensor 1 with `pulseIn()`
3. Trigger sensor 2
4. Read sensor 2 with `pulseIn()`


message:
Do I need a resistor to control a servo with a PWM signal?

I working with Arduino Nano Every that has several analog PWM pins. I want to use one to control a small servo.

Do I need to put a resistor between PWM pin and the servo signal?

body:
No, you don't.

Resistors are used to limit and control current (amongst other things) and you don't need to do that when sending a signal from one digital device to another.


message:
Check if any of loop's insides returns 1 and hold it until the whole loop is 0 again

I'm new to this, so, please, don't crucify me.

I have a function that checks if an entry in multilevel array is in a certain range. Using FOR loop I check the whole array with this function, which gives me true/false value for each record.

And now the problem:
I need to check if ANY entry in that loop returns true and hold it until every result of that loop is false again.

Any tips?

Thanks a lot.

There is my for loop:

      for(int i = 0; i < arrayTop; i++){
    for(int j = 0; j < arrayDay; j++){
      for(int k = 0; k < arrayTime; k++){
        timeCompare(timeArray[i][j][k][0], timeArray[i][j][k][1], timeArray[i][j][k][2], timeArray[i][j][k][3], timeArray[i][j][k][4], timeArray[i][j][k][5], timeArray[i][j][k][6]);

        //Serial.print(i);Serial.print(j);Serial.print(k);Serial.print(" ");
        Serial.println(compareVar);

        if(i == 0){

          //set water switch
          if(compareVar == 1){
            waterOn = 1;
            Serial.println("Water ON");

            goto bailout;
          }
          else {
            waterOn = 0;
            Serial.println("water OFF");
          }
        }
        else if(i == 1){

          //set light switch
          if(compareVar == 1){
            lightOn = 1;
            Serial.println("Light ON");
            goto bailout;
          }
          else {
            lightOn = 0;
            Serial.println("light OFF");
          }
        }
      }
    }
  }
  bailout:

and this is the called function:

    //time compare with ON/OFF switch
    int timeCompare(int hrOn, int minOn, int secOn, int hrOff, int minOff, int secOff, int timerSwitch){
      unsigned long int onTime = (hrOn*10000UL) + (minOn*100UL) + secOn;
      unsigned long int offTime = (hrOff*10000UL) + (minOff*100UL) + secOff;
      unsigned long int currentTime = (dt.hour*10000UL) + (dt.minute*100UL) + dt.second;

      if(timerSwitch == 1){
        if(onTime < currentTime && offTime > currentTime){
          compareVar = 1;
        }
        else {
          compareVar = 0;
        }
      }
     else if(timerSwitch == 0) {
        compareVar = 0;
      }

      //Serial.print("compare: "); Serial.println(compareVar);

    }

body:
First, you should really not use a global variable to get the result of your comparison function. That is only confusion and unnecessary complicated code. For that we have return values. So instead of setting the `compareVar` variable inside the `timeCompare()` function, you should just return the corresponding value. In the `timeCompare()` function replace

    compareVar = 1;

with

    return 1;

and

    compareVar = 0;

with

    return 0;

Then in your main code: As I understood, you only need `compareVar` in the for loops, so you could delete the globally defined `compareVar` and declare it directly before the for loops:

    int compareVar = 0;

Now we can do the magic trick. We want to go through our for loops and get a result of `1`, if for any of the elements `timeCompare()` returns 1. For that we just doing an OR operation:

    compareVar = compareVar || timeCompare(timeArray[i][j][k][0], timeArray[i][j][k][1], timeArray[i][j][k][2], timeArray[i][j][k][3], timeArray[i][j][k][4], timeArray[i][j][k][5], timeArray[i][j][k][6]);

This is a boolean OR `||`. In C++ zero is treated as `false`, while any other number is treated as `true`. We are starting with `compareVar` begin zero. When `timeCompare()` for the element returns also zero, it stays zero. If it returns 1, `compareVar` will become 1. If it returns 1 again, it will stay one. If it returns zero, it will stay zero.

So now you can check for `compareVar` after the for loops. It will be 1, if any of the elements gave you 1.

Similarly you could check for all elements returning 1, if you replace the OR `||` by an AND `&&` operation.

---

Lastly I want to strongly discourage you from using `goto`. It ignores some important principles and you can easily create really bad code with it. Refer to questions like [this one][1] to read more about it. I would say, that in every case you have better ways than `goto`. Here it seems, that you simply want to go out of both loops. I would pack these loops into a function, so that you could simply use a `return` statement to get out of them.

  [1]: https://stackoverflow.com/questions/3517726/what-is-wrong-with-using-goto


message:
Arduino I2C Multiplexing uisng TCA9548A

I am using 5 sensors out of which two have the same I2C address and are connected via TCA9548 multiplexer. The remaining 3 sensors are connected to the main arduino I2C bus. In example sketches online I see the following function to choose the specific port/channel on the multiplexer:

    #define MPLXADR 0x70 // Address of TCA9548A I2C Multiplexer
    void multiplexer (uint8_t ch) {
      if (ch > 7) return;
      Wire.beginTransmission(MPLXADR);
      Wire.write(1 << ch);
      Wire.endTransmission();
    }

I understand that this function should be called before executing instructions for the sensors with shared address but how would it still send the data to the right sensor when the last line "Wire.endTransmission();" just closes connection?

Since in my circuit there are sensors which are connected directly to the arduino I2C bus, I wonder if the code related to those sensors comes after the code for sensors with shared address, wouldn't those instructions also be sent to the ensors with shared I2C address? To me it makes more sense if the instructions for the shared address sensors are enclosed inside the above mentioned function as follows:

channel select -> execute instruction -> end transmission

But the usage I see in the tutorials baffles me. Could somebody please clarify these points? Thanks

Here is the complete sketch I am using:

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BME280.h>
    #include <AHT10.h>
    #include <HDC2080.h>

    Adafruit_BME280 bme1; // on Arduino I2C bus
    Adafruit_BME280 bme2; // on multiplexer I2C bus
    Adafruit_BME280 bme3; // on mulitplexer I2C bus
    AHT10 AHT(AHT10_ADDRESS_0X38); // on Arduino I2C bus
    HDC2080 HDC2080(0x41);// on Arduino I2C bus

    #define MPLXADR 0x70 // Address of TCA9548A I2C Multiplexer
    void multiplexer (uint8_t ch) {
      if (ch > 7) return;
      Wire.beginTransmission(MPLXADR);
      Wire.write(1 << ch);
      Wire.endTransmission();
    }

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

      while (AHT.begin() != true)
      {
        Serial.println(F("AHT10 not connected or fail to load calibration coefficient"));
        delay(5000);
      }
      Serial.println(F("AHT10 OK"));

      HDC2080.begin();

      // Begin with a device reset
      HDC2080.reset();

      // Set up the comfort zone
      HDC2080.setHighTemp(28);         // High temperature of 28C
      HDC2080.setLowTemp(22);          // Low temperature of 22C
      HDC2080.setHighHumidity(55);     // High humidity of 55%
      HDC2080.setLowHumidity(40);      // Low humidity of 40%

      // Configure Measurements
      HDC2080.setMeasurementMode(TEMP_AND_HUMID);  // Set measurements to temperature and humidity
      HDC2080.setRate(ONE_HZ);                     // Set measurement frequency to 1 Hz
      HDC2080.setTempRes(FOURTEEN_BIT);
      HDC2080.setHumidRes(FOURTEEN_BIT);

      //begin measuring
      HDC2080.triggerMeasurement();
      Serial.println();

      Serial.println(F("BME280 test"));

      //BME280 sensor 1
      multiplexer(0);
      if (! bme1.begin(0x77, &Wire)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
      }

      // weather monitoring
      Serial.println("-- Weather Station Scenario --");
      Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
      Serial.println("filter off");
      bme1.setSampling(Adafruit_BME280::MODE_FORCED,
                       Adafruit_BME280::SAMPLING_X1, // temperature
                       Adafruit_BME280::SAMPLING_X1, // pressure
                       Adafruit_BME280::SAMPLING_X1, // humidity
                       Adafruit_BME280::FILTER_OFF   );

      //BME280 sensor 2
      multiplexer(1);
      if (! bme2.begin(0x77, &Wire)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
      }

      // weather monitoring
      Serial.println("-- Weather Station Scenario --");
      Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
      Serial.println("filter off");
      bme2.setSampling(Adafruit_BME280::MODE_FORCED,
                       Adafruit_BME280::SAMPLING_X1, // temperature
                       Adafruit_BME280::SAMPLING_X1, // pressure
                       Adafruit_BME280::SAMPLING_X1, // humidity
                       Adafruit_BME280::FILTER_OFF   );

      //BME280 sensor 3
      if (! bme3.begin(0x76, &Wire)) {
        Serial.println("Could not find a valid BME280 sensor, check wiring!");
        while (1);
      }

      // weather monitoring
      Serial.println("-- Weather Station Scenario --");
      Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,");
      Serial.println("filter off");
      bme3.setSampling(Adafruit_BME280::MODE_FORCED,
                       Adafruit_BME280::SAMPLING_X1, // temperature
                       Adafruit_BME280::SAMPLING_X1, // pressure
                       Adafruit_BME280::SAMPLING_X1, // humidity
                       Adafruit_BME280::FILTER_OFF   );

      // suggested rate is 1/60Hz (1m)
     }

    void loop() {
      bme3.takeForcedMeasurement(); // has no effect in normal mode
      printValuesBME3();
      delay(5000);

      printValuesAHT();
      delay(5000);

      printValuesHDC2080();
      delay(5000);

      multiplexer(0);
      bme1.takeForcedMeasurement(); // has no effect in normal mode
      printValuesBME1();
      delay(5000);

      multiplexer(1);
      bme2.takeForcedMeasurement(); // has no effect in normal mode
      printValuesBME2();
      delay(10000);
    }

    void printValuesBME1() {

      Serial.println();
      Serial.print("BME1 Readings");

      Serial.print("Temperature = ");
      Serial.print(bme1.readTemperature());
      Serial.println(" *C");

      Serial.print("Humidity = ");
      Serial.print(bme1.readHumidity());
      Serial.println(" %");

      Serial.println();
    }

    void printValuesBME2() {

      Serial.println();
      Serial.print("BME2 Readings");

      Serial.print("Temperature = ");
      Serial.print(bme2.readTemperature());
      Serial.println(" *C");

      Serial.print("Humidity = ");
      Serial.print(bme2.readHumidity());
      Serial.println(" %");

      Serial.println();
    }

    void printValuesBME3() {

      Serial.println();
      Serial.print("BME3 Readings");

      Serial.print("Temperature = ");
      Serial.print(bme3.readTemperature());
      Serial.println(" *C");

      Serial.print("Humidity = ");
      Serial.print(bme3.readHumidity());
      Serial.println(" %");

      Serial.println();
    }

    void printValuesHDC2080() {
      Serial.println("HDC2080 Values");
      Serial.print("Temperature (C): "); Serial.print(HDC2080.readTemp());
      Serial.print("\t\tHumidity (%): "); Serial.println(HDC2080.readHumidity());
    }

    void printValuesAHT() {

      Serial.println(F("AHT10: read 12-bytes, show 255 if communication error is occurred"));
      Serial.print(F("Temperature: ")); Serial.print(AHT.readTemperature()); Serial.println(F(" +-0.3C")); //by default "AHT10_FORCE_READ_DATA"
      Serial.print(F("Humidity...: ")); Serial.print(AHT.readHumidity());    Serial.println(F(" +-2%"));   //by default "AHT10_FORCE_READ_DATA"
    }

body:
The TCA9548 is a switch.

You begin a transaction to it, change the channel that it allows through, and then end *that specific transaction.*

From that point on one and only one of the other two sensors are attached to your bus - the other doesn't exist.  When you communicate on the address of that sensor it passes through the TCA9548 as if it doesn't exist.

You can think of the TCA9548 as a controller that sits *next to* the switch:

<!-- 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/OjN94.png)

<!-- End schematic -->

Send channel 0 and it flips the switch one way. Send channel 1 and it flips the switch the other way. Once the switch is flipped it stays flipped until you tell it otherwise.

From your sketches perspective the two HDC2080s on the MUX are only one HDC2080. You just flip the switch to the right position to access the specific physical device you want at the time.


message:
else if is ignored if not Serial.println anything before

I encountered to me inexplicable behavior on an arduino uno.
I'm serial reading a string from the serial monitor/python serial. This string is the conditional on several if/else if statements.
The crazy thing is, some strings just get ignored, but if I print out the read string after reading it, the ignored statements then get executed and the script works the way it's supposed to.
This is the code:
```
// power outlet 1
# define OUT_1_1 2 // relay #4
# define OUT_1_2 3 // relay #3

// power outlet 2
# define OUT_2_1 4 // relay #2
# define OUT_2_2 5 // relay #1

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  // power outlet 1
  pinMode(OUT_1_1, OUTPUT);
  pinMode(OUT_1_2, OUTPUT);

  // power outlet 2
  pinMode(OUT_2_1, OUTPUT);
  pinMode(OUT_2_2, OUTPUT);

  // init outputs to HIGH
  digitalWrite(OUT_1_1, HIGH);
  digitalWrite(OUT_1_2, HIGH);
  digitalWrite(OUT_2_1, HIGH);
  digitalWrite(OUT_2_2, HIGH);

  Serial.begin(9600);
}

void loop() {
  String str = "";

  // checking for bytes in the buffer
  if (Serial.available() > 0) {
    str = Serial.readStringUntil("\n");
  }
  // Serial.println(str); // if this line is uncommented serial input "2_ON\n" and "2_OFF\n" is recognized and outled 2 is successfully switched

  // identity
  if (str == "IDN\n") {
    Serial.println("Serial Power Outlet");
  }

  // controlling power outlet 1
  else if (str == "1_ON\n") {
    digitalWrite(OUT_1_1, LOW);
    digitalWrite(OUT_1_2, LOW);
  }
  else if (str == "1_OFF\n") {
    digitalWrite(OUT_1_1, HIGH);
    digitalWrite(OUT_1_2, HIGH);
  }

  // controlling power outlet 2
  else if (str == "2_ON\n") {
    digitalWrite(OUT_2_1, LOW);
    digitalWrite(OUT_2_2, LOW);
  }
  else if (str == "2_OFF\n") {
    digitalWrite(OUT_2_1, HIGH);
    digitalWrite(OUT_2_2, HIGH);
  }
  delay(1000);
}
```
If I serial input `2_ON\n` or `2_OFF\n` the according else if blocks are just ignored (all other inputs work correctly).

But after I've uncommented `// Serial.println(str);` these blocks are executed the way they are supposed to and all works just fine.

Where is my mistake, what am I getting wrong here?
These blocks also get executed if I `Serial.println` any random output.
Why do I have to Serial.println something first so my script works according to plan? What am I missing?

EDIT: added all of the code.

body:
Even though you read until \n, that just controls the ending of your buffered string.  It does not control it's start.  There may be some garbage before the command that you have not cut out.  In other words, I suggest you check if the string endsWith as opposed to == the command string.

As for what noise could be causing garbage or why activity on the tx side of the serial cleaned it up, i do not know.  Heck something might just be weird enough in the wiring that '2' is just the set of bits needed to aggravate it.


message:
Anyone have example code for ESP32 as media controller for Android/iPhone Media Apps

There's actually another post with this very same topic but no answers on that post. Back in January of 2020, the last commenter said he had sample code and then he went dark without posting the actually code. The thread is here:

https://arduino.stackexchange.com/questions/25593/want-to-create-bluetooth-audio-control-volume-up-down-play-pause-etc-for-s/71423#71423?newreg=f9eaf7e88f3c4c3b90e72b4e070f9e5a

My problem is the exactly the same as the original post. Amazon and Aliexpress have literally hundreds of these "media buttons" that you can buy and pair via bluetooth with your Android or iOS. You can then playback media on iOS/Android and the "media buttons" can control the playback. Pretty common controls are volume up/down, next, previous, play and pause.

I've written a lot of Arduino code for Nano, Uno and even MKR. I've written a bunch of ESP8266 and ESP32 code as well. Usually when I try and learn something, a few google searches will find an example that I can figure out. For this, I've been able to find nothing.

Every tutorial or sample code is about how to send commands to the ESP32 via Bluetooth or pair an ESP32 with a bluetooth joystick, etc. None of those examples help me understand what's needed for an ESP32 to pair with my Android and act as media buttons, sending volume up, down and play/pause commands via bluetooth.

Can anyone help with example code for doing this with an ESP32? (by the way, this forum would not let me comment on the original post or I would have. it said I didn't have enough karma points or something)

body:
Well after I posted this question, I kept googling. Literally hours of googling at this point. Then I stumbled across this example:

https://github.com/T-vK/ESP32-BLE-Keyboard

I wrote that sketch to my ESP32, paired my iPhone and it immediately starting controlling music playback on my phone. After looking at the code, it's so simple that I'm embarrassed I couldn't figure this out on my own. In case the link goes dead, I'll paste the code here:

<pre>
#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleKeyboard.begin();
}

void loop() {
  if(bleKeyboard.isConnected()) {
    Serial.println("Sending 'Hello world'...");
    bleKeyboard.print("Hello world");

    delay(1000);

    Serial.println("Sending Enter key...");
    bleKeyboard.write(KEY_RETURN);

    delay(1000);

    Serial.println("Sending Play/Pause media key...");
    bleKeyboard.write(KEY_MEDIA_PLAY_PAUSE);

    delay(1000);

    Serial.println("Sending Ctrl+Alt+Delete...");
    bleKeyboard.press(KEY_LEFT_CTRL);
    bleKeyboard.press(KEY_LEFT_ALT);
    bleKeyboard.press(KEY_DELETE);
    delay(100);
    bleKeyboard.releaseAll();

  }
  Serial.println("Waiting 5 seconds...");
  delay(5000);
}
</pre>


message:
Calling a localhost php script from arduino

Is it possible to connect arduino uno to call a php script using ONLY an arduino uno board, and an esp8266-01 wifi module.? That is, I lack wifi shield such as node MCU.
I just need the setup to call a php script on my localhost server.
I'm using arduino IDE 1.8.13.
Gracias

body:
You can program the ESP-01 module using the arduino IDE. There are instructions in the README here: https://github.com/esp8266/Arduino

You can program the ESP-01 to connect to WiFi and communicate with your arduino sketch using the serial port. Don't forget the ESP-01 runs at 3.3V while the arduino runs at 5V. You'll need to shift the voltages somehow, otherwise you'll burn the arduino uno.

Here's an example of code you can run on the ESP-01 to connect to WiFi and start a TCP connection: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino

All that's missing is making an HTTP request instead of a "raw" TCP connection. You can probably find that in the examples. Then, add code for serial communication back to your arduino uno.

Good luck!


message:
Jumping to bootloader from application code in atmega328p

I'm trying to program an Arduino Uno (atmega328p) using only the serial Tx/Rx lines (no DTR, so no automatic reset). This is so I can upload code via WiFi/TCP using an ESP-01.

To achieve this, I need to Arduino sketch/application to reset itself (and run the bootloader) whenever it sees avrdude trying to upload code (e.g. when `0 0 ` appears in the serial port).

I've tried a few approaches to jumping to the bootloader from application code but had no success so far.

 1. **Using the watchdog timer**
```
void reset_to_bootloader() {
 // see 11.2.2 MCUCR – MCU Control Register
 // Enable change of interrupt vectors
 MCUCR = (1<<IVCE);
 // Move interrupts to Boot Flash section
 MCUCR = (1<<IVSEL);

 // enable watchdog timer
 wdt_enable(WDTO_30MS);

    // block waiting for the watchdog to timeout and jump to the bootloader
 while(1);
}
```
Unfortunately, the datasheet[1] mentions the `IVSEL` bit is not available in atmega328p, so even though this compiles, it simple resets the MCU and the bootloader does not run.

2. **Jumping to the bootloader address directly**

There is a table in the datasheet (Table 26-7. Boot Size Configuration, ATmega328P) that specifies the bootloader start address for the 4 supported bootloader section sizes, which are configured by the BOOTSZ fuse.

I have read the fuses and confirmed the bootloader section is 512-bytes (256 words) long.
Therefore, according to the datasheet, the Boot Loader Flash Section is `0x3F00 - 0x3FFF`. So, the start of the bootloader should be at word-address 0x3F00.

I have even dumped the whole 32768-byte flash off the MCU and confirmed the bootloader is at byte-address `0x7e00`, which matches the expected word-address `0x3F00` (`0x7e00 / 2 = 0x3F00`).

I have tried a couple methods of jumping to address 0x3F00. Here's a few. None of them seem to work. They just reset the MCU and the bootloader doesn't seem to run.

```
void jump_to_bootloader() {
 size_t bootloader_addr = 0x3F00;

 void (*bootloader_ptr)() = (void (*)())(bootloader_addr);

 SREG = 0;
 wdt_disable();
 bootloader_ptr();
}

void jump_to_bootloader2() {
 asm volatile ("ijmp" ::"z" (0x3F00));
}
```

3. **Jumping and updating the value of `MCUSR`**

I then realised the bootloader[4] checks the reset source and only runs on an external reset:

```
ch = MCUSR;
if (! (ch &  _BV(EXTRF))) // if its a not an external reset...
    pp_start();  // skip bootloader
```

So I tried faking it before jumping, but it didn't work either:

```void jump_to_bootloader2() {
    MCUSR = _BV(EXTRF);
 asm volatile ("ijmp" ::"z" (0x3F00));
}
```

Any help is appreciated. Thanks in advance!

---
edit:

4. **Jumping to after the bootloader checks the reset source**

Following @Edgar Bonet's suggestion, avoiding the `if (!(ch & _BV(EXTRF))) appStart();` check in the bootloader by jumping to the instruction that follows it:
```
void jump_to_bootloader2() {
 // the bootloader assumes these are true:
 cli();
 SP = RAMEND;
 SREG = 0;
 MCUSR = 0;
 asm volatile ("eor __zero_reg__, __zero_reg__");
 asm volatile ("eor r1, r1");
 // jump to after the bootloader checks the reset source
 asm volatile ("ijmp" ::"z" (0x7e0au / 2));
 while(1);
}
```

I could see it entered the bootloader (LEDs flashed a couple times), but avrdude was not able to upload code.

The bootloader sets up a watchdog timer (WDT), so I'm suspecting avrdude waits for to long after sending the initial `0 0 0 ` and since the bootloader does not see anything on the serial port the WDT resets it.

---

References:

  - [1] AVR Instruction Set Manual: http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf
  - [2] atmega328p datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
  - [3] random forum thread I have also read: https://www.avrfreaks.net/forum/jump-bootloader-app-help-needed
  - [4] bootloader code: https://github.com/sparkfun/Arduino_Boards/blob/805def002e815509032fde37a674d2916af8aecc/sparkfun/avr/bootloaders/atmega/ATmegaBOOT_168.c#L299-L307

body:
The source of Optiboot on Uno is [here][1].

I would prefer a simple watchdog reset with
```
  wdt_enable(WDTO_15MS);
  while (true);
```
But I am not sure now if it runs sketch upload detection in bootloader.

For direct jump to Optiboot on Uno (one flash page) this should work
```
typedef void (*bootloader_jump_t)();
const bootloader_jump_t bootloader_jump = (bootloader_jump_t)((FLASHEND-511)>>1);
```
and then you can call `bootloader_jump();`

EDIT:
while the Optiboot 4 on Uno from factory doesn't check for new upload after watchdog reset or direct jump, Optiboot 8 has checks to handle this right

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/optiboot/optiboot.c


body:
Maybe you could jump to right after the line

```c
if (!(ch & _BV(EXTRF))) appStart();
```

Here is an [excerpt of the disassembly][disasm]:

```c
  if (!(ch & _BV(EXTRF))) appStart();
    7e06: 81 ff        sbrs r24, 1
    7e08: f0 d0        rcall .+480     ; 0x7fea <appStart>

#if LED_START_FLASHES > 0
  // Set up Timer 1 for timeout counter
  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
    7e0a: 85 e0        ldi r24, 0x05 ; 5
    7e0c: 80 93 81 00  sts 0x0081, r24
```

The conditional call to `appStart()` is made by the instructions `sbrs`
and `rcall`. The instruction right after that is the `ldi` at byte
address 0x7e0c (word address 0x3f05). I would try jumping right there.
You won't miss much:

 * `eor r1, r1` is not needed when jumping from C++, as the value of r1
   is already enforced by the compiler as per the ABI.
 * `in r24, 0x34` reads `MCUSR` into a register that is clobbered right
   away
 * `out 0x34, r1` clears `MCUSR`; if this turns out to be useful, you
   could do it right before jumping to the bootloader.

You may want to check that the bootloader you have matches the
disassembly I linked to.

[disasm]: https://github.com/arduino/ArduinoCore-avr/blob/master/bootloaders/optiboot/optiboot_atmega328.lst#L48-L56


message:
Issues with Arduino UNO printing repeated "double" on serial monitor

A weird is happening which i can't figure out why. First I had issue communicating with SIM800L.
So i tried checking the USART Hardware to see what UNO sends to SIM800 using small piece attached below.
The sketch is to compares what i send from serial monitor with strings "Hello", "heLLo" and "Hello" expecting to get Found .... or No match found.
each line string i send, the serial monitor prints twice WHY?,
The first says not found and the second say Received == ........ WHY?

**See the output of serial terminal
when i typed "Hello" with quotes.

    12:03:46.536 -> Buffer Received= " No match found
    12:03:46.569 ->
    12:03:46.569 -> Buffer Received= Hello"
    12:03:46.603 ->  Found Hello
    when i typed "HELLO" with quotes.
    12:03:55.855 -> Buffer Received= " No match found
    12:03:55.888 ->
    12:03:55.888 -> Buffer Received= HELLO"
    12:03:55.921 ->  Found HELLO**

****when i typed "heLLo" with quotes.

    12:04:04.016 -> Buffer Received= " No match found
    12:04:04.049 ->
    12:04:04.049 -> Buffer Received= heLLo"
    12:04:04.082 ->  Found heLLo
    12:04:04.115 ->****

When i typed without quotes, all i get No match found

    char buffer[100];
    uint8_t index=0;

    void setup()
    {
      Serial.begin(9600);
      _delay_ms(4000);
    }

    void loop()
    {
      if(Serial.available()>0)
      {
        index=0;
        while(Serial.available())
        {
          buffer[index++]=Serial.read();
        }

        buffer[index]='\0';
        Serial.println(' ');
        Serial.print("Buffer Received");
        Serial.print(buffer);
        Serial.print('\t');
        if(strstr(buffer, "Hello")!=NULL) Serial.println("Found Hello");
        else if(strstr(buffer, "HELLO")!=NULL) Serial.println("Found HELLO");
        else if(strstr(buffer, "heLLo")!=NULL) Serial.println("Found heLLo");
        else Serial.println("No match found");
        Serial.flush();
      }
    }

Note: Suspecting my PC hardware and serial driver,
so I tried it in my Ubuntu 20.04 and window 10 installed with Arduino IDE 1.8.13
suspecting it may be crystal, i tried two different boards and used even Atmega328P core.
I also suspected my keyboard "ENTER" key, so i tried the serial monitor "send" button. \
with no difference.

I seems to run short is ideas so i am posting to the community. Let me have your advice and experience too.

Thanks.

body:
As Majenko and DataFiddler already stated in the comments, you are reading the Serial interface in the wrong way, because you seem to misunderstand a specific point involving the interface.

The Serial (UART) interface knows only of individual bytes, which are send asynchronously over the lines. It does not have any context of a full packet or message. When you type in some data into the Serial Monitor and then press "Send", the data will be send, but not as one big bunch of data. The individual bytes are delayed.

The first delay comes with the nature of the interface itself, as you send with a limited baudrate. With a baudrate of 9600 the Arduino is way faster, than the bytes can arrive. So when you first get a result higher than zero from `Serial.available()`, the rest of the message is not yet received. Thus with your current code you would only process only the first part of the message.

The second delay comes with the fact, that you and the Serial program on your PC cannot control, when exactly each byte is send. Thats done by the driver. So it might happen, that there is a small gap between 2 bytes somewhere in your message. You cannot mitigate this without writing your own driver and you cannot predict this.

**So, what to do now?** You should read data, when it is available, and put it into a buffer. And only, when a full message was received, you should process the data. Now you need to know, where the end of a message is. Mostly a delimiting character (like the newline character `\n`) at the end of the message is used. So you read, if available, and only process the message, when you have read the delimiting character. Something like this:

    unsigned int buffer_pos = 0;
    char buffer[50]="";

    void loop(){
        if(Serial.available()){
            char c = Serial.read();
            if(c == '\n'){
                buffer[buffer_pos] = '\0'; // End the message as C string with a null character
                // process the message here
                buffer_pos = 0;
            } else {
                buffer[buffer_pos] = c;
                buffer_pos++;
            }
        }
    }

`buffer` holds the message. `buffer_pos` is the current position in the buffer. We terminate the message with the null character, to get a valid C string in the buffer. After processing the message, we set the position back to zero, to receive the next message. When you send data from your PC, you need to make sure, that the message is ended with the newline character.

Now you are independent on when exactly the data is send.

---

DataFiddler stated in the comments, that without a delimiting character you can simply delay for enough time, so that the data has enough time to arrive. He also stated, that it is ugly. It is a bad coding style. A long delay will impact the responsiveness of your program, while a short delay may give you problems with longer messages. So I suggest, that you directly use the correct way to read the Serial interface. Then you don't have such pitfalls.


message:
String array length in function

I know this question has been asked a thousand times, but I can't find a solution for my case.

I what to get the length of a string array in a given function. This is for an arduino board.

```cpp
#define LEN(x) sizeof(x)/sizeof(x[0])
const char* mainMenu[] = {"FirstWord", "SecondWord", " "};

void myFunction(const char** m) {
  int a = LEN(m);

  /* Do something */
};

void setup(){
   myFunction(mainMenu);
};
```

The `LEN(m)` works fine in the `setup()` function. But in `myFunction()` it either gives me 1 (i guess the length of the pointer) or 9 (length of the 0th element of the array)

body:
The problem is that LEN is evaluated locally for each usage replacing it with the content. In `myFunction` the parameter being passed to it is a pointer, not the array.

You need to evaluate the size once and once only in the context where the array hasn't collapsed into a pointer. That is usually done immediately where the array is defined:

```
const char* mainMenu[] = {"FirstWord", "SecondWord", " "};
#define MAINMENU_LEN (sizeof(mainMenu) / sizeof(mainMenu[0]))
```

Because `mainMenu` is a global it's always available, and when you require the length you get the length of the global array.

If you want to keep things local you will have to pass the number of elements in the array as a parameter to the function that uses that information.

    myFunction(mainMenu, MAINMENU_LEN);

Another common alternative is to have some "end of array" marker and you loop through your array until you find that marker (that's how strings work - with `\0` for the end of array marker):

    const char* mainMenu[] = {"FirstWord", "SecondWord", " ", 0};

Then:

    for (int i = 0; m[i] != 0; i++) {
        ...
    }


message:
error at compiling : 'class TwoWire' has no member named 'setClock'

I am a newbie C programmer and I just started with Arduino **web editor** (Win10-Firefox)to code for a **Raspberry Pi** (3B) board. RPi is on line via ethernet connection.

I tried to compile an example from Garmin Lidar_lite v3HP for I2C, as available in the library collections for Arduino.
When compiling the example I get after a while this error message:

*Using library Wire in folder: /home/builder/.arduino15/packages/arduino/hardware/mraa/1.0.8/libraries/Wire (legacy)*

*Using library lidar_lite_3_0_3 at version 3.0.3 in folder: /home/builder/opt/libraries/latest/lidar_lite_3_0_3*

*/tmp/967842743/v3HP_I2C/v3HP_I2C.ino: In function 'void setup()':*

*/tmp/967842743/v3HP_I2C/v3HP_I2C.ino:51:18: error: 'class TwoWire' has no member named 'setClock'*

*Wire.setClock(400000UL); // Set I2C frequency to 400kHz (for Arduino Due)*

^
*exit status 1*

Checking the arduino forum I find some similar question, but of many years ago and likely not applicable any longer.

I appreciate your expert inputs on how to resolve in simple terms.
Thanks a lot! Greetz, Ivan

body: Thanks for the reply. I tried again with the arduino on PC with RasPiDuino librarie and had no further problem. The resulting executable does work on a RPi3 with Buster OS. Apparently the arduino webeditor lacks some libraries to succesfully compile for raspberry . I continue this road. Item can be closed.


message:
Ardutester Millenium I2c Lcd Not Showing Anything!

Hiii Friends....,
                  I am Trying to Build Components tester Using Arduino Specifically Atmega328p Chip .
I Downloaded The Ardutester Millenium Code From Here ..  https://create.arduino.cc/projecthub/plouc68000/ardutester-millenium-the-ultimate-uno-mega-versions-c81db4

Edited Makefile.h By Enabling i2c lcd Interface And Adding My I2c Lcd Adress ...   But it wont work

I tried On Uno And Mega Also Serial Monitor Output seems ok But It Doesnt Display anything on 16*2 lcd

Thanks ...... :)
![enter image description here](https://i.stack.imgur.com/YghPT.jpg)![enter image description here](https://i.stack.imgur.com/LNLV0.jpg)

Code is available at that page sir...
Thanks for your reply

body: The schematic you posted is not for I2C. You have a connection to the regular 2x16 LCD character display. For the I2C an SSD1306.


message:
Cant upload arduino code when ESP8266-01 module is connected

I'm using [this tutorial][1] to connect my ESP8266-01 WiFi Module to Arduino UNO with Arduino IDE v. 1.8.13.

[![Tutorial snippet][2]][2]

It works and the module can connect to my WiFi.
However, when I try to upload my code, it says:

`avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x30`

What could be the problem, since when I remove the reset pin it uploads the code, but now the WiFi goes down.

  [1]: http://www.teomaragakis.com/hardware/electronics/how-to-connect-an-esp8266-to-an-arduino-uno/
  [2]: https://i.stack.imgur.com/QJYqb.png

body:
Your problem is that there are two ways of wiring your ESP-01 module to the Arduino:

1. Wired so the PC has access to it and the Arduino is effectively disabled, and
2. Wired so the Arduino has access to it

You are wired in configuration 1 at the moment whereby the Arduino is effectively turned off and the USB connection goes direct to the ESP-01. When you try and upload code to the Arduino it's the ESP-01 that the computer is talking to, not the Arduino.

You need to wire it in configuration 2. In this configuration the TX/RX pins of the ESP-01 connect to any two pins of the Arduino except pins 0 and 1, and the RESET pin is not connected to anything. Then you can't talk to the ESP-01 through the serial monitor - instead you have to write code for the Arduino that uses SoftwareSerial to communicate for you.

There are many many tutorials online about communicating between the Arduino and the ESP-01.


message:
Where is the Arduino IDE log file located? Not the Serial Monitor

"An error ocurred while uploading the sketch"

I'm having this specific error when uploading a sketch to my board and the IDE doesn't specify the problem correctly.

It's version is 1.8.13 for Windows 10.

I would like to get a file with detailed information about the IDE's error. Where should I look for it?

body:
There is no log file. Instead you need to turn on both "compilation" and "upload" under the "Show verbose output during:" option in Preferences.

This will give you far more information about any errors in the output scroll pane at the bottom of the IDE.

On Linux if you run the IDE from the command line you get large amounts of logging on stdout. There may be a way of doing the same from Windows.


message:
Relay + Arduino uses too much power for battery to handle. Which solution is best?

You can see in my crumby schematic that I am using a Non-latching relay to turn on a 3A circuit (one of them arc lighters), which is powered by a 25C (supposedly) lipo battery. That same battery also powers an Arduino through a TP4056. This works fine when I first turn it all on, but once the relay is activated by the Arduino, the lighter + Relay only turn on for a split second before stopping (when the Arduino is powered via USB, it works fine). I am thinking that the Arduino+Relay+Lighter is too much for the battery, even though it claims to be 25C. It is just strange because the Arduino+Activated Relay consume what, like 200 mA?

Notes:
When I manually turn on the lighter, the light on the Arduino dims a fair bit, but stays on.
The Arduino is running at logic level of 3.3V so that I didn't need a booster.
[![enter image description here][1]][1]
As for fixes, I was thinking about trying to use a transistor or SSR instead of the chunky relay I have now (which would be good, I need this to be compact). Or maybe the TP4056 is failing to provide enough output despite a decent input?

I am FAR from an electrical engineer so if anyone has any pro tips for improving this it would be much appreciated.

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

body:
The TP4056 is a battery charger, not a voltage regulator. It cannot be used to supply power to a device like an Arduino. It is designed for charging the Lithium Ion battery from a 5V (e.g., USB) source.

By trying to use it as a power supply you're asking for trouble. It thinks it's trying to charge a battery (from a 3.7V nominal source) and will be doing things like:

* Running constant current making the voltage fluctuate wildly as current demands change
* Running constant voltage with limited current causing starving of power
* Shutting off when it thinks it sees the non-existent battery being fully charged.

The TP4056 should be connected to a 5V USB power source and to the battery for charging it. The battery should be then through a (very) low-dropout regulator (ideally a switching regulator with zero dropout bypass ability) to power the Arduino at 3.3V.

Alternatively, if you don't need a (reasonably) precise 3.3V then you can power the Arduino directly from the battery.


message:
I want 2 output pins to working alternately

I have given pwm output on pin(9) and I Want pin(10) to be high when pin(9) is low and pin(10) to be low when pin(9) is high.  So what should i add to my code?

body:
would something like the following work?

```
digitalWrite(9,  !digitalRead(10));
```

like this: https://forum.arduino.cc/index.php?topic=128698.0


body:
You can set pin 10 to run in “inverted PWM” mode, and leave
pin 9 in the default non-inverted mode. Pin 9 is the “OC1A”
pin of the AVR microcontroller (output compare of Timer 1,
channel A), whereas pin 10 is OC1B (channel B of the same
timer). Inverting the PWM mode of channel B is a matter of changing
a single bit in one of the control registers of Timer 1:

```cpp
TCCR1A |= _BV(COM1B0);
```

You can do this once in `setup()`, the setting should persist. Then just
`analogWrite()` the same value to both pins. For some background on how
all this works, see the [datasheet of the ATmega328P
microcontroller][datasheet] (the MCU at the hearth of your Uno),
especially section 16 “16-bit Timer/Counter1 with PWM” and table
16-3 “Compare Output Mode, Phase Correct and Phase and Frequency Correct
PWM”.

[datasheet]: http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf


message:
Breaking out of the arduino fingerprint enroll loop

I am using the Arduino's Adafruit Finger Sensor library, and it has an example to enroll a fingerprint. I want it to enroll one print and exit/break out of the loop because it currently enrolls a user, then goes back to asking for a fingerprint.
Here is the code:

    #include <Adafruit_Fingerprint.h>
    SoftwareSerial mySerial(2, 3);
    Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
    uint8_t id;
    void setup()
    {
      Serial.begin(9600);
      while (!Serial);  // For Yun/Leo/Micro/Zero/...
      delay(100);
      Serial.println("\n\nAdafruit Fingerprint sensor enrollment");

      // set the data rate for the sensor serial port
      finger.begin(57600);

      if (finger.verifyPassword()) {
        Serial.println("Found fingerprint sensor!");
      } else {
        Serial.println("Did not find fingerprint sensor :(");
        while (1) { delay(1); }
      }
    }

    uint8_t readnumber(void) {
      uint8_t num = 0;

      while (num == 0) {
        while (! Serial.available());
        num = Serial.parseInt();
      }
      return num;
    }

    void loop()                     // run over and over again
    {
      Serial.println("Ready to enroll a fingerprint!");
      Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as...");
      id = readnumber();
      if (id == 0) {// ID #0 not allowed, try again!
         return;
      }
      Serial.print("Enrolling ID #");
      Serial.println(id);

      while (!  getFingerprintEnroll() );
    }

    uint8_t getFingerprintEnroll() {

      int p = -1;
      Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
      while (p != FINGERPRINT_OK) {
        p = finger.getImage();
        switch (p) {
        case FINGERPRINT_OK:
          Serial.println("Image taken");
          break;
        case FINGERPRINT_NOFINGER:
          Serial.println(".");
          break;
        case FINGERPRINT_PACKETRECIEVEERR:
          Serial.println("Communication error");
          break;
        case FINGERPRINT_IMAGEFAIL:
          Serial.println("Imaging error");
          break;
        default:
          Serial.println("Unknown error");
          break;
        }
      }

      // OK success!

      p = finger.image2Tz(1);
      switch (p) {
        case FINGERPRINT_OK:
          Serial.println("Image converted");
          break;
        case FINGERPRINT_IMAGEMESS:
          Serial.println("Image too messy");
          return p;
        case FINGERPRINT_PACKETRECIEVEERR:
          Serial.println("Communication error");
          return p;
        case FINGERPRINT_FEATUREFAIL:
          Serial.println("Could not find fingerprint features");
          return p;
        case FINGERPRINT_INVALIDIMAGE:
          Serial.println("Could not find fingerprint features");
          return p;
        default:
          Serial.println("Unknown error");
          return p;
      }

      Serial.println("Remove finger");
      delay(2000);
      p = 0;
      while (p != FINGERPRINT_NOFINGER) {
        p = finger.getImage();
      }
      Serial.print("ID "); Serial.println(id);
      p = -1;
      Serial.println("Place same finger again");
      while (p != FINGERPRINT_OK) {
        p = finger.getImage();
        switch (p) {
        case FINGERPRINT_OK:
          Serial.println("Image taken");
          break;
        case FINGERPRINT_NOFINGER:
          Serial.print(".");
          break;
        case FINGERPRINT_PACKETRECIEVEERR:
          Serial.println("Communication error");
          break;
        case FINGERPRINT_IMAGEFAIL:
          Serial.println("Imaging error");
          break;
        default:
          Serial.println("Unknown error");
          break;
        }
      }

      // OK success!

      p = finger.image2Tz(2);
      switch (p) {
        case FINGERPRINT_OK:
          Serial.println("Image converted");
          break;
        case FINGERPRINT_IMAGEMESS:
          Serial.println("Image too messy");
          return p;
        case FINGERPRINT_PACKETRECIEVEERR:
          Serial.println("Communication error");
          return p;
        case FINGERPRINT_FEATUREFAIL:
          Serial.println("Could not find fingerprint features");
          return p;
        case FINGERPRINT_INVALIDIMAGE:
          Serial.println("Could not find fingerprint features");
          return p;
        default:
          Serial.println("Unknown error");
          return p;
      }

      // OK converted!
      Serial.print("Creating model for #");  Serial.println(id);

      p = finger.createModel();
      if (p == FINGERPRINT_OK) {
        Serial.println("Prints matched!");
      } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
        Serial.println("Communication error");
        return p;
      } else if (p == FINGERPRINT_ENROLLMISMATCH) {
        Serial.println("Fingerprints did not match");
        return p;
      } else {
        Serial.println("Unknown error");
        return p;
      }

      Serial.print("ID "); Serial.println(id);
      p = finger.storeModel(id);
      if (p == FINGERPRINT_OK) {
        Serial.println("Stored!");
      } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
        Serial.println("Communication error");
        return p;
      } else if (p == FINGERPRINT_BADLOCATION) {
        Serial.println("Could not store in that location");
        return p;
      } else if (p == FINGERPRINT_FLASHERR) {
        Serial.println("Error writing to flash");
        return p;
      } else {
        Serial.println("Unknown error");
        return p;
      }
    }

Output is that after storing the fingerprint, it requests for finger to enroll, but I want it to exit after storing. Is this possible?

body:
Your `getFingerprintEnroll()` function is missing a return statement. Inside the `if (p == FINGERPRINT_OK)` statement, you need to insert

    return 0;

after the Serial print. Only when returning zero, you will exit the while loop inside the `loop()` function.


message:
Digispark ATtiny85 not recognized (bootloader problem)

I recently bought an ATtiny85 based development board. (picture below)

[![Digispark clone][1]][1]

I managed to install it correctly following the official guides, without a problem.
Drivers are installed correctly, and I used the Arduino IDE to actually upload a few sketches and tested them in two computers.

*SUDDENLY*

It has stopped working, based on my research, it seems that the bootloader got damaged. Any idea on how to fix this? I thought about burning the bootloader using Arduino, but I have barely got an idea on how to begin.

Backside of the Attiny85
[![Digispark clone][2]][2]

  [1]: https://i.stack.imgur.com/5OnaW.jpg
  [2]: https://i.stack.imgur.com/vN5xq.jpg

body:
The 3 [default][4] ways to re-program your tiny on that board are:
- [micronucleus][1] bootloader (sketches only)
- ISP prog. (sketches & set-fuses, InSystemProgramming)
- HV prog. (re-set fuses, HighVoltage = 12V don't worry)

The bootloader in itself is like a sketch on the chip (at the beginning, taking up flash space) and talks through the software USB port on that board. It then rewrites parts of its own flash from the data the host sends, when you upload new sketches.

If that part gets damaged it won't get recognized by the host anymore and you can't use the board to reprogram itself. Unless the chip/parts died to ESD or other reasons, **you still can use ISP/HV programming on the chip, which is the solution to your problem.**

Read up on [fuses][2], they are the init settings of your chip (like a BIOS) defining its behaviour. There are some fuses which can only be set once, after which they can only be changed by the HV method. Depending their setting on your chip, this could also be done with normal ISP programming.

This [instructables][3] shows how to build a HV programmer, but also demonstrates using an Arduino as normal ISP programmer (Step 4).

The original Digispark comes with the RSTDISBL fuse set, meaning you can't directly use ISP (which requires the reset pin). Thats why HV programming is neccessary, to regain the reset pin, after that you can reflash the bootloader via ISP. From then on you can use the bootloader again, to reprogram (upload) your sketches.

  [1]: https://github.com/micronucleus/micronucleus
  [2]: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf#G1.2073549
  [3]: https://www.instructables.com/How-to-unlock-Digispark-ATtiny85-and-convert-it-to/
  [4]: https://digistump.com/wiki/digispark/tutorials/programming


message:
How to prevent flickering relay upon waking from deep sleep using ESP01 board?

I have a cheap ESP01 relay module and am using it with ESPEasy. I soldered the GPIO pin 16 to RST to allow deep sleep and that all works great.

However when the unit wakes up the relay flickers quite a bit. The application I had in mind was for a 12v fridge which draws quite a bit of current on start up. I think this flickering would damage the fridge compressor or controller pretty quickly, not to mention wearing out the relay itself.

I need the unit to wake up from deep sleep, and keep the relay in the off position, unless triggered by some external criteria.

Perhaps a capacitor would absorb the pin high voltage for a short period until it's booted? Trouble is that I don't really want to hack the module, I'll probably break something.

[![ESP01 Module][1]][1]

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

body:
Apparently it's a pretty common issue for people using this board. There are a  couple of solutions here that I will try: https://github.com/IOT-MCU/ESP-01S-Relay-v4.0/issues/1

The most non invasive one with Tasmoto firmware didn't work in my case. So I will try another pin and if that fails, bite the bullet and introduce a capacitor.


body:
The only two pins that don't glitch or change state during reset and boot are GPIO4 and GPIO5, and neither of them are brought out to the 2x4 header on an ESP-01.
https://rabbithole.wwwdotorg.org/2017/03/28/esp8266-gpio.html

All of the other pins will make your relay click or chatter.  Pick a different module, or try soldering a wire onto GPIO4 or 5. The boot time is ~ 150ms long, so it'd take a long time constant R-C circuit to filter it out, on the order of 1/2 second or more.


message:
WeMos D1 ESP-Wroom-02 Mother Board ESP8266 - where is reset pin for deep-sleep

This [item][1] was bought for battery use with deep sleep purposes. For doing so in ESP8266 `reset` pin must be connected to `Gnd` pin in order to wake up. This board lacks a `reset` on- board pin.
Since spec states it has a such capabilities - I wonder if someone has succeeded with putting it to sleep ( and wake it back on ).

PS - I know that on-chip `gpio16` can be soldered to on-chip `gnd` - I'm hoping there is a more elegant, not soldering invloved, solution.
Guy

  [1]: https://www.aliexpress.com/item/32860090110.html?spm=a2g0s.9042311.0.0.70534c4dSBq9RI

body:
This support page has the instructions for enabling deep sleep:

[Support for WeMos D1 ESP-Wroom-02 Nodemcu][1]

edit by Guy: in short, solder/connect pins as shown circled in red:

[![image of board][2]][2]

  [1]: https://github.com/arendst/Tasmota/issues/1236
  [2]: https://i.stack.imgur.com/kRmHT.jpg


message:
ARDUINO expected ';' before 'delay'

I want to shine LED in 64 of 255 duty cycles = level of brightness but it pops up this error (see picture). Can anybody tell me why and help me ? Thank you.

    void setup() {
      // put your setup code here, to run once:

    }

    void loop() {

      analogWrite(11, 64)
      delay{1000};
      analogWrite(11, 0)
      delay(1000);

      // put your main code here, to run repeatedly:

    }

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

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

body:
You should write ";" end of each lines.

    analogWrite(11, 64);
    delay(1000);
    analogWrite(11, 0);
    delay(1000);


message:
How to post image using Arduino HTTPClient

I am using arduino HTTPClient to do the post request in ESP32. Can anyone help me with the part where I will be able to post an image file along with some data.

The below code works perfectly fine with only sending user_name and image_type-
```
#include <HTTPClient.h>

http.begin("https://www.somelink.com/post-image");

http.addHeader("Content-Type", "application/x-www-form-urlencoded");

String httpRequestData = "user_name=Shidhartha&image_type=Outdoor";

int httpResponseCode = http.POST(httpRequestData);
if(httpResponseCode > 0){
  String response = http.getString();
  Serial.println(response);
}else{
  Serial.print("Error on sending POST: ");
  Serial.println(httpResponseCode);
}
```

body:
Below is the perfectly working code I got from [here](https://RandomNerdTutorials.com/esp32-cam-post-image-photo-server/).
```
#include <Arduino.h>
#include <WiFi.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

String serverName = "192.168.1.XXX";   // REPLACE WITH YOUR Raspberry Pi IP ADDRESS
//String serverName = "example.com";   // OR REPLACE WITH YOUR DOMAIN NAME

String serverPath = "/upload.php";     // The default serverPath should be upload.php

const int serverPort = 80;

WiFiClient client;

// CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27

#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

const int timerInterval = 30000;    // time between each HTTP POST image
unsigned long previousMillis = 0;   // last time image was sent

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("ESP32-CAM IP Address: ");
  Serial.println(WiFi.localIP());

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  // init with high specs to pre-allocate larger buffers
  if(psramFound()){
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 10;  //0-63 lower number means higher quality
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_CIF;
    config.jpeg_quality = 12;  //0-63 lower number means higher quality
    config.fb_count = 1;
  }

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    delay(1000);
    ESP.restart();
  }

  sendPhoto();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= timerInterval) {
    sendPhoto();
    previousMillis = currentMillis;
  }
}

String sendPhoto() {
  String getAll;
  String getBody;

  camera_fb_t * fb = NULL;
  fb = esp_camera_fb_get();
  if(!fb) {
    Serial.println("Camera capture failed");
    delay(1000);
    ESP.restart();
  }

  Serial.println("Connecting to server: " + serverName);

  if (client.connect(serverName.c_str(), serverPort)) {
    Serial.println("Connection successful!");
    String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
    String tail = "\r\n--RandomNerdTutorials--\r\n";

    uint16_t imageLen = fb->len;
    uint16_t extraLen = head.length() + tail.length();
    uint16_t totalLen = imageLen + extraLen;

    client.println("POST " + serverPath + " HTTP/1.1");
    client.println("Host: " + serverName);
    client.println("Content-Length: " + String(totalLen));
    client.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
    client.println();
    client.print(head);

    uint8_t *fbBuf = fb->buf;
    size_t fbLen = fb->len;
    for (size_t n=0; n<fbLen; n=n+1024) {
      if (n+1024 < fbLen) {
        client.write(fbBuf, 1024);
        fbBuf += 1024;
      }
      else if (fbLen24>0) {
        size_t remainder = fbLen24;
        client.write(fbBuf, remainder);
      }
    }
    client.print(tail);

    esp_camera_fb_return(fb);

    int timoutTimer = 10000;
    long startTimer = millis();
    boolean state = false;

    while ((startTimer + timoutTimer) > millis()) {
      Serial.print(".");
      delay(100);
      while (client.available()) {
        char c = client.read();
        if (c == '\n') {
          if (getAll.length()==0) { state=true; }
          getAll = "";
        }
        else if (c != '\r') { getAll += String(c); }
        if (state==true) { getBody += String(c); }
        startTimer = millis();
      }
      if (getBody.length()>0) { break; }
    }
    Serial.println();
    client.stop();
    Serial.println(getBody);
  }
  else {
    getBody = "Connection to " + serverName +  " failed.";
    Serial.println(getBody);
  }
  return getBody;
}
```


message:
Relay with NodeMCU is not working

I'm using a Relay Channel and NodeMCU(8266-WIFI). When i trigger the connection, LED Turns ON in Node MCU But the Relay connection is not working. I'm not sure what is the issue, Please help to fix it..

My Pin connection as follows.

> 1. NodeMCU (VIN) -> Relay (VCC)
>  2. NodeMCU (G) -> Relay (G)
>  3. NodeMCU (D1) -> Relay (IN4)

My code as follows,

    #include <ArduinoJson.h>
    #include <ESP8266WiFi.h>
    #include <FirebaseCloudMessaging.h>
    #include <Firebase.h>
    #include <FirebaseHttpClient.h>
    #include <FirebaseArduino.h>
    #include <FirebaseError.h>
    #include <FirebaseObject.h>

    // Set these to run example.
    #define FIREBASE_HOST "xxx-xxxx.firebaseio.com"
    #define FIREBASE_AUTH "xxxxxx"
    #define WIFI_SSID "xxxx"
    #define WIFI_PASSWORD "xxxxx"

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

      // connect to wifi.
      WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
      Serial.print("connecting");
      while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
      }
      Serial.println();
      Serial.print("connected: ");
      Serial.println(WiFi.localIP());

      pinMode(D1, OUTPUT);
      pinMode(LED_BUILTIN, OUTPUT);

      Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
      Firebase.set("LED_STATUS",0);
    }

    int n = 0;

    void loop() {
      // Get value
      n=Firebase.getInt("LED_STATUS");

      if (n==1) {
         digitalWrite(D1, LOW);
         digitalWrite(LED_BUILTIN, LOW);
         Serial.print("LED is ON ");
         Serial.println(Firebase.getInt("LED_STATUS"));
         delay(1000);
      }
     else{
       //LED_BUILTIN
       digitalWrite(D1, HIGH);
       digitalWrite(LED_BUILTIN, HIGH);
       Serial.print("LED is OFF ");
       Serial.println(Firebase.getInt("LED_STATUS"));
       delay(1000);
     }

    }

[![Connection PICTURE][1]][1]

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

body:
I found that the 3V isn't enough to power the relay.
https://www.instructables.com/Getting-Started-With-ESP8266LiLon-NodeMCU-V3Flashi/ shows the board supplies USB power (pin VU).

You can remove the jumper that connects signal voltage to relay power and connect the relay board to the USB power.

After that change I could turn the relays on and off, but I could not reliably power 4 relays, 2 relays as shown below seems fine.

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

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


message:
inconsistent digital output on simple code

so im new on arduino coding, and i made this code, where i input from serial monitor and then use it as a command for digital write. the problem is, sometimes the code work perfectly but then when i input 4, both D3 ad D4 is high and that also happens in D5 and D6. but its inconsistent, and i also print the 'out' value and also which digital pin is high to make it easier.

    byte b;
    int out;
    int D3 = 3;int D4 = 4;int D5 = 5;int D6 = 6;int D7 = 7;int D8 = 8;
    void setup() {
      Serial.begin(9600);
      pinMode(out, OUTPUT);
      digitalWrite(D3, LOW);digitalWrite(D4, LOW);digitalWrite(D5, LOW);digitalWrite(D6, LOW);digitalWrite(D7, LOW);digitalWrite(D8, LOW);

    }

    void loop() {
      while (Serial.available() == 0) {}
      b = Serial.read() - 48;
      out = b;
      Serial.print("\n Out is ");
      Serial.println(out);
      digitalWrite(out, HIGH);
      delay(600);
     if (digitalRead(D3) == HIGH)
    {
       Serial.print("D3 HIGH");
    }
     if (digitalRead(D4) == HIGH)
    {
       Serial.print("D4 HIGH");}
     if (digitalRead(D5) == HIGH)
    {
       Serial.print("D5 HIGH");
    }
     if (digitalRead(D6) == HIGH)
    {
       Serial.print("D6 HIGH");
       }
     if (digitalRead(D7) == HIGH)
    {
       Serial.print("D7 HIGH");
    }
     if (digitalRead(D8) == HIGH)
    {
       Serial.print("D8 HIGH");
       }
      digitalWrite(out, LOW);
      delay(1000);

    }

does anyone know why this happens? or can anyone recommend another method to do what im tryinng to do? thank you guys!!!

body:
If I look at the first 5 lines:

    byte b;
    int out;
    int D3 = 3;int D4 = 4;int D5 = 5;int D6 = 6;int D7 = 7;int D8 = 8;
    void setup() {
      Serial.begin(9600);
      pinMode(out, OUTPUT);

You see that `pinMode`out, OUTPUT)` uses a variable `out` which is not initialized (it's only declared in `int out`'.

I assume `D3` to `D8` are all output pins, so you have to replace the last line with:

    pinMode(D3, OUTPUT);
    pinMode(D4, OUTPUT);
    pinMode(D5, OUTPUT);
    pinMode(D6, OUTPUT);
    pinMode(D7, OUTPUT);
    pinMode(D8, OUTPUT);

Also, since you are using all pins in the same way, I suggest you use two variables: `startPin` and `endPin`. Then you can use a `for` loop to iterate through all pins. Also

- always initialize variables.
- use '0' instead of 48 when you convert from a byte value to a character (since you don't need to know the ASCII value of '0').

I don't have an Arduino compiler at hand, but it should look something like:

    byte b = 0;
    int out = 0;
    const byte startPin = 3;
    const byte endPin = 8;

    void setup() {
      Serial.begin(9600);
      for (byte pin = startPin; pin <= endPin; pin++)
      {
          pinMode(pin, OUTPUT);
          digitalWrite(pin, LOW);
      }
    }

    void loop() {
      while (Serial.available() == 0) {}
      b = Serial.read() - '0';
      out = b;
      Serial.print("\n Out is ");
      Serial.println(out);
      digitalWrite(out, HIGH);
      delay(600);

      ...

However, from here you are using the pins as INPUT pins. You cannot change those on the fly, you might change them manually (by using `pinMode(pin, INPUT)`), but it does not seem normal to switch input and output pins, so maybe you should explain what you are intending with your application.


message:
What Minimum Value Can I Measure With ACS712 30A Current Sensor?

I am making an Arduino multimeter for current measurement. I first thought about using a shunt but that fails to work since I need to measure current in the mA range.

body:
That model has a sensitivity of 66mV/A which means for every 1A of current passing through it outputs 66mV.

The Arduino's ADC when running at 5V has a resolution of (5/1024) 4.88mV per LSB.

That means that 4.88/66 gives you 0.074 - or 74mA per LSB.

Since 1LSB is considered to be in the noise area of the signal you can expect the minimum usable value to be double that - 148mA

Which is pretty useless for measuring currents in the mA range.

You would get better results with the 5A variant, but still not great.


body:
The [datasheet for the ACS712][1] shows the following:

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

This means the 30A variant has a sensitivity of 66mV/A. This means a reading of 1A will show 66mV plus some bias voltage. The Arduino ADC is 10-bit, meaning it has 2^10 = 1024 increments across a default 5V voltage reference for the Uno, Nano, etc. This gives it a measuring resolution of 5V/1024 increments = 4.88mV voltage resolution. 4.88mV / 66mV/A = 0.074A, or 74mA.

So, the default _resolution_ of an Arduino Uno, Nano, etc, is **74mA.** Realistically it will bounce around this value, so your _precision_ might be about 3~4x this, or around **300mA**, and your accuracy is as good as you calibrate it, which could easily be around this value too if you calibrate it well.

74mA resolution isn't bad, but there are several tricks to improve this. Here are a few:

**1. External hardware solutions:**

1. **Use the 20A or 5A version instead of the 30A version of the ACS712.** The 5A version has a sensitivity of 185mV/A, which automatically improves your resolution to 4.88mV / 185mV/A = 0.026A, or **26mA**, which is 74mA/26mA = **2.8x better**.
1. **Buy an external ADC with high-resolution.** This [Adafruit ADS1115 16-Bit ADC](https://www.adafruit.com/product/1085) ([datasheet][3]) will improve your resolution on the 30A version of the ACS712 as follows. Minimum resolution of the ADC is now 5V/2^16 = 5V/65535 = 0.0763mV instead of 4.88mV, and 0.0763mV / 66mV/A = 0.001156A, or **1.156mA**.

**2. Software solutions (freebies!):**

1. **Change your voltage reference to use the internal 1.1V internal reference.** This is easy: call `analogReference(INTERNAL)` in your `setup()` function. Done! See: https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/. If I recall correctly, this is a diode-based internal voltage reference (see the ATmega328 datasheet), and can be off by as much as 10% from part to part, so calibrate it for each individual Arduino you have and you will get good results! Now, your ADC resolution is 1.1V/1024 = 1.07mV instead of the Arduino's default 4.88mV, so your current resolution is 1.07mV / 66mV/A = **16.2mA**, which is 74mA/16.2mA = **4.6x better**.
1. **Use oversampling to increase the Arduino's 10-bit ADC to up to ~16 bits or so.** Atmel Application Note [AVR121: Enhancing ADC resolution by oversampling][4] explains this very well, albeit it requires some serious study. There are libraries which exist to do this for you which you can Google for. I wrote one of them. [Here is a link to my website where I present one such library I wrote](https://www.electricrcaircraftguy.com/2014/05/using-arduino-unos-built-in-16-bit-adc.html). The gist is this: to get an 11-bit reading (which is 1-bit better than your hardware ADC resolution of 10-bits) you need to take 4^1 = 4 10-bit readings, sum them, then divide by 2^1 = 2. Your max value will be 1023 x 2 = 2046. To get a 16-bit reading (which is 6-bits better than your hardware ADC resolution of 10-bits) you need to take 4^6 = 4096 10-bit readings, sum them, and divide by 2^6 = 64. Your max value will be 1023 x 64 = 65472. Your voltage resolution will be improved from 4.88mV to ~0.0764mV _at best_. It won't be as good as a true 16-bit ADC, like the Adafruit one above, but it's good enough for many uses. Keep in mind that 4096 10-bit readings takes some time, so I also recommend you speed up the ADC clock to improve reading rate at 10-bits from ~10kHz to ~50kHz. This is also where a library comes in handy to make this easy to do. Free and open source solutions already exist. Here's a table I made back when I first read the  AVR121 application note and practiced oversampling. Consider the resolution values beyond ~16-bits to be purely theoretical. Oversampling has its limits.
    1. [![enter image description here][5]][5]

What would I do? I'd use the 1.1V internal voltage reference and oversampling with increased ADC clock speed on the ACS712 part which provides the minimum acceptable max current (ie: choose the 5A version not the 20A or 30A version if 5A is enough, or the 20A version not the 30A version if 20A is enough). **Just be sure that your max voltage now at the analog pins will not exceed the 1.1V Vref value**. If it will, use the standard 5V reference for the ADC, and just do oversampling alone. My current resolution would end up being a few mA in the end. If I can't sample at the desired frequency using oversampling (I don't know what dynamic effects you may be trying to measure), then I'd use an external high-resolution ADC which can sample faster than oversampling at high resolutions would allow.

----

And if that's not good enough, what would I do? I'd use a precision shunt, ie: "current resistor" with the right value such that I can measure values at the right range. If I need amplification I'd buy an external ADC and/or op-amp from Adafruit until I have everything sized just right. Remember, if your shunt (current resistor) is too small to measure the low currents you need, do the following:

1. Use a higher resistance value. V = IR (Voltage = Current x Resistance), so increase R to increase the V across it for a given current, I.
1. Use an op-amp to amplify the voltage drop across the resistor (go for an Adafruit one since Adafruit makes it easy and has the world's best examples).
1. Use a high-resolution ADC, and/or oversampling to increase your sensitivity to measure small voltage changes.

  [1]: https://www.sparkfun.com/datasheets/BreakoutBoards/0712.pdf
  [2]: https://i.stack.imgur.com/pvS2n.png
  [3]: https://cdn-shop.adafruit.com/datasheets/ads1115.pdf
  [4]: http://ww1.microchip.com/downloads/en/Appnotes/doc8003.pdf
  [5]: https://i.stack.imgur.com/hmZOq.png


message:
Extremely unstable analogRead() on Arduino Nano when powered from an external source

I'm doing a really simple project with an Arduino Nano and found a problem.
The circuit is a simple temperature sensor and a tension read from an analog pin everything showed on a Nokia 5110 LCD.

When the Nano is connected to the USB everything works and the reads are perfect.

When I install the circuit on my car taking the 12V to the Vin and the GND from the centraline everything goes bad: I certainly know that the 12V is obviously not stable and oscillates a lot (between 12V and 14V).

What can be the solution? Should I add some ref or should I regulate the input tension to maintain it stable to a certain quantity?

body:
You can use a branded 5 V charger made for cars. You can directly connect this to 5 V pin of the Arduino.

By doing this:

 1. you are protecting the Arduino from the noise as well as high voltage spikes coming from the car 12 V supply
2. protecting yourself and others coming in contact with the Arduino or the sensors connected to the Arduino.

You can also
1. consider filtering the analog data read
2. protection circuits such as surge protection diodes or a 5.7 V Zener across 5 V and Ground of Arduino


message:
Best way to ask Arduino for data from Python?

I'm trying to send numerical data from inertial sensors from my Arduino to a Python script via serial (PySerial).
I found that if I continuously send the data from the Arduino without stopping, the serial buffer fills up quickly and the sensor measurements that the Python reads becomes delayed.

To fix this, I thought of having the Python script send over a transmit command to the Arduino when it needs data. I'm sending a char 't' to signify this command, but the delay between Python sending the command and the Arduino sending the data is too large.

I'm wondering if there's a 'proper' way of doing this, as I'm sure it's probably been done before?

body:
This is not a complete answer to your problem, but currently you seem to have some misconceptions, that prevent you from pin pointing the actual problem.

The data transmission from the sensor, over the Arduino to your python script on the PC has multiple places, where a bottleneck can appear. The total data rate will then be at maximum as large, as the smallest bottleneck allows it to be.

First you have a potential bottleneck in the communication between sensor and Arduino. You haven't stated, what kind of IMU chip you have and how it communicates. Typical IMU chips like the MPU series are interfaces via I2C or SPI. SPI can be sped up rather greatly, while I2C is not that easy to speed up. But it depends greatly on the capabilities of the used chip. You can find information about that in the corresponding datasheet of the chip.

---

The next interface is the Serial (UART) interface between Arduino and PC. This interface has a fixed baudrate. When you use `Serial.write()` or its siblings, you simply fill the send buffer of the `Serial` library. The data will then be send out automatically at the correct timing for your baudrate. The transmission always happens, if the python script is reading or not. The transmission also happens, when the serial buffer of the script is full. The Arduino does not know about the buffer being full. So in this case the data is not delayed, but lost.

---

The last - and probably most important - potential bottleneck is how you read and send the data on Arduino and in the python script. Here I'm covering the Arduino side.

You should not use functions like `Serial.readString()`, as they work with a timeout, which will slow down your code drastically. Instead you should read the Serial data byte by byte into a buffer, delimiting your message with a special character (for example the newline character `\n`). You check, if there is any data `Serial.available()`, and if yes, you read one byte into a `char` array, which is your own buffer. You are doing that repeatedly, until you read the delimiting character. Then you process the complete message. That way will give you some important improvements:

- You can do things in the meantime (for example reading new data from your sensor)
- It works without any arbitrary timeout, thus not slowing down your code unnecessaryly
- The delimiting character frames a full message, so that you can distinguish two different messages from each other and thus easier process them

---

Considering the above, you should make the requirements clearer:

- How much latency between the actual sensor measurements and the receiving in the python script is ok for you, meaning: How old can the measurements be, that the python script gets? (You just stated, that it is too large, but you have not mentioned how large)

- Do you need continuous data transmission, or just one or a few sets of the IMU data?

Then you can check for the needed speed and data rate. Check, if all involved interfaces and codes can really handle your requirements.

Also it would be easier for us to help you, when you show your current code in your question.


message:
Can analog pins be defined as either their analog name (A0) or their digital pin number?

Can analog pins be defined by their digital pin number, and be used for analog purposes?

For example, instead of defining `A0` for a pinout with the Uno, it could be `14`?

Where is this documented? Is there a PDF type manual related to this, but not so low level to get into the ATmega chip?

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

https://www.arduino.cc/en/Hacking/PinMapping2560

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

body:
> For example, instead of defining A0 for a pinout with the Uno, it could be 14?

Yes. In fact A0 is just a placeholder for the number 14.

For all these things you should look in the `pins_arduino.h` file (Arduino\variants\wifio) for any variant you are interested in. That's where most of these symbols are defined. For example:

```
#define PIN_A0   (14)
#define PIN_A1   (15)
#define PIN_A2   (16)
#define PIN_A3   (17)
#define PIN_A4   (18)
#define PIN_A5   (19)
#define PIN_A6   (20)
#define PIN_A7   (21)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;
```

Incidentally, on the Uno you can also just use `0` for A0 with `analogRead()`.