message:
Speaker-dependent Voice Recognition

I would like to install speaker-dependent voice recognition in a robot equipped with Arduino Uno compatible boards.
Specifically, I want to record the robot's name beforehand and have it respond when I call the robot's name.

Although it is not an Arduino, there is a person who has developed a function that I would like to realize with the M5StickV.
This person used [isolated_word.py][1], a library published by Sipeed, as a reference.

[【K210】マイク搭載版M5StickV,Sipeed Maixシリーズで音声認識をする][2]

After some research, I found [Maix_Speech_Recognition][3] in the library of Maixduino, which can use Arduino IDE.
Apparently, it uses Mel-frequency cepstrum coefficients analysis of speech input, and then uses dynamic time stretching to find the similarity.
The MFCC uses the K210 FFT on the Maixduino.

Arduino Uno does not have an FFT accelerator, but it can do FFT.
Therefore, I thought it would be possible to use Maix_Speech_Recognition for specific speaker speech recognition on ArduinoUno compatible devices.

**Question**
1. Is it possible to use Maix_Speech_Recognition for speaker-dependent voice recognition on Arduino Uno compatible boards?
2. What part of Maix_Speech_Recognition should I modify to make it work on Arduino Uno compatible boards?

  [1]: https://github.com/sipeed/MaixPy_scripts/tree/master/multimedia/speech_recognizer
  [2]: https://raspberrypi.mongonta.com/isorated-word-recognizer-k210/
  [3]: https://github.com/sipeed/Maixduino/tree/master/libraries/Maix_Speech_Recognition

body:
> Is it possible to use Maix_Speech_Recognition for speaker-dependent voice recognition on Arduino Uno compatible boards?

No. It's not.

> What part of Maix_Speech_Recognition should I modify to make it work on Arduino Uno compatible boards?

Don't even think about it. The UNO *cannot* do anything even remotely like speech recognition of any form without adding extra specific speech recognition hardware.

Just get a K210 board - they're cheap enough.


sender: user

message:
Substring: What is causing my output to be truncated?

I suspect that I might be using too many resources, because of the strings, but I am new to Arduino, so not sure where I am going wrong.  Any help would be appreciated.

What it should do when complete:
"Birthday Reminder"
 - Read the SD card for a "birthday" file ("MM-DD.txt" ) that matches
   "today".
 - The file contains the Name of the person and year of
   birth.
 - Flash LED's and display the person's name and age on the
   OLED.
 - The unit will not displayed anything until someone's birthday.

I am using the SD card with a simple format, to easily add new birthday's.

    Output:
    ⸮Initializing SD card...
    card initialized.
    25
    111
    opening: 04-25.txt
    2020"Test Person"
    bYearStr: 20

**The sd card file:**

    Name: MM-DD.txt
    Example: 04-25.txt

    Contents: Birthyear, Name
    Example: 2020"Test Person"

**The Sketch**

    #include <SPI.h>
    #include <SD.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>
    #include "RTClib.h"

    RTC_DS3231 rtc;

    int age;
    int led;
    int dly;
    String bName;
    String bYearStr;
    int bYear;
    int currentDay;
    int  tDy;
    int  tMth;
    int  tYr;

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels
    #define OLED_RESET -1
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

    void setup() {
      Serial.begin(9600);
      delay(3000); // wait for console opening

      // Setup Candle pins
      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      if (! rtc.begin()) {
        Serial.println("Couldn't find RTC");
        while (1);
      }

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

      display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
      display.clearDisplay();
      display.display(); // this command will display all the data which is in buffer
      display.setTextColor(WHITE, BLACK);

      const int SdCardPin = 10;
      Serial.println("Initializing SD card..."); // Verifying SD Card.
      //  if (!SD.begin(SdCardPin)) {
      if (!SD.begin(10)) {
        Serial.println("Card failed, or not present"); // don't do anything more:
        while (1);
      }
      Serial.println("card initialized.");

      currentDay = 111;
    }

    void loop() {
      age = 0;

      DateTime now = rtc.now();
      tDy = now.day();
      tMth = now.month();
      tYr = now.year();
      Serial.println(tDy);
      Serial.println(currentDay);

      if (currentDay != tDy) {
        String fileName;
        String m = String(tMth);
        String d = String(tDy);

        if (tMth < 10) {
          String mm = m;
          m = "0" + mm;
        }
        if (tDy < 10) {
          String dd = d;
          d =  "0" + dd;
        }
        fileName = m + "-" + d + ".txt";

        //String fileName = "01-01.txt";
        Serial.println("opening: " + fileName);
        File f = SD.open(fileName);
        delay(3000);

        if (!f) {
          Serial.println("open failed");
        } else {
          while (f.available()) {
            String line = f.readStringUntil('\n');
            Serial.println(line);
            bYearStr = line.substring(0, 4);
            bName = line.substring(4);
            delay(1000);
            currentDay = tDy;
            break;
          }
          f.close();
        }

        Serial.print("bYearStr: ");
        Serial.println(bYearStr);
        Serial.print("bName: ");
        Serial.println(bName);
        int bYear = bYearStr.toInt();
        age = tYr - bYear;
        Serial.print("Age: ");
        Serial.println(age);

      } else { // Start current day equal
        display.setTextSize(1);
        display.setCursor(38, 10);
        display.print("Birthday!");
        display.println();

        display.setTextSize(1);
        display.setCursor(0, 30);
        display.print("Name: ");
        display.print(bName);
        display.setCursor(0, 40);
        display.print("Age: ");
        display.print(age );
        display.println();

        led = random(3, 6);
        dly = random(80, 250);
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(dly);              // wait
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
      } // End current day

      display.display();

    } // End void Loop

sender: assistant

body:
It *is* quite likely you're out of memory. To know, really you need to keep track of the stack pointer and heap structure. There's enough going on in your code, that I'm not reasonably going to be able to set up an identical scenario to prove it.

### Display Library ###
The greatest use of SRAM in your project comes from the Adafruit SSD1306 library.  It's [allocating a buffer for the entire frame][1], which is 128 * 64 == 8192 bits, or 1024 bytes, half your Nano's SRAM.  It will use more than that for other data, though probably not a lot more by percentage.

You may be able to mitigate this usage with a library like trades some SRAM usage for extra execution time or lower frame rates.  One is the [U8g2 library][2].  You can read about [how it can use half-buffer][3] in some documentation to the older version of the library; the concept carries over to the newer library.

### SD Library ###
The next largest usage is the [SD card libraries sector buffer][4], which is 512 bytes.

So between the two of them, there go 3/4 of your SRAM in just the two buffers, nevermind anything else.

You may be able to avoid this buffer by using a different library.  You could try [PetitFS][5].  The library it wraps [says it uses something like 44 bytes][6] plus whatever call stack is needed.

### String Literals ###

You have at least 206 bytes of string literals in your sketch alone, assuming the compiler can't determine that any of them are in fact unused.  There *may* be others in the libraries, though probably not many. So now we're down to at least 306 bytes or less SRAM.

|Size|String                                 |
|----|---------------------------------------|
|35  | `"RTC lost power, lets set the time!"`|
|28  | `"Card failed, or not present"`       |
|24  | `"Initializing SD card..."`           |
|18  | `"Couldn't find RTC"`                 |
|18  | `"card initialized."`                 |
|12  | `"open failed"`                       |
|11  | `"bYearStr: "`                        |
|10  | `"opening: "`                         |
|10  | `"Birthday!"`                         |
|10  | `"01-01.txt"`                         |
| 8  | `"bName: "`                           |
| 7  | `"Name: "`                            |
| 6  | `"Age: "`                             |
| 5  | `".txt"`                              |
| 2  | `"-" `                                |
| 2  | `"0"`                                 |
|206 | *Total*                               |

The `"0"` is only counted once in the above, even though you have two of them.  *Fun fact: the C and C++ languages allow identical string literals to be colocated or overlap.  I don't know whether or not avr-gcc will combine `"Name: "` into `"bName: "`, since you have bigger problems to worry about, I'm just pretending it won't without looking.*

Mitigation can include [use of the `F()` macro][7] to move some of these string literals into PROGMEM (flash).  You can't do this to every string literal, but the ones where you're involving them in a `String(F("we're trying to avoid these right?"))` constructor or in Serial (or other Stream/Print instances)'s `.print(F("Hello World"));`

The guts of the `F()` macro is another called `PSTR()`, which does the actual work of putting the string literal into PROGMEM.  `F()` tags the resulting pointer with a dummy type that is used in function overloading in Arduino libraries.  The only reason why I mention this is because below, you'll see me use `PSTR` to do the same thing, only with a function that belongs to avr-libc rather than Arduino.

Note when you're initializing a `String` object from a regular string literal, you're paying the SRAM cost twice for the lifetime of the `String` object.  One copy is in SRAM for the literal used to call the String constructor, the other copy is in the dynamic memory allocated to the String object.

String class
------------

This was pointed out in the comments; and it's true that it's better to avoid them.  Although, I think not actually the greatest problem in your case.

I see you've avoided unnecessarily adding them together for Serial output and instead are using separate `.print()` calls, so you're ahead of the game there.

For your filename, mitigation could be using fixed size local `char` array and `snprintf_P()` to cobble together your filename, something like:

```c++
char filename[sizeof "MM-DD.txt"];
snprintf_P(
    filename, sizeof filename,
    PSTR("u-u.txt"),
    tMth, tDy
);
```

or if you wanted to avoid pulling the beast of `printf` into your sketch, assuming it's not already there, you could do something like:

```c++
const char filename[] = {
    '0' + tMth / 10,
    '0' + tMth % 10,
    '-',
    '0' + tDy  / 10,
    '0' + tDy  % 10,
    '.',
    't',
    'x',
    't',
    '\0'
};
```

Serial
-----------
What `Serial`?  Yup, I mean, there's not a lot you can do about it, but I bring it up because the last conservative figure above was 306 bytes, and we didn't try to account for the what String is doing in the heap at all.  Well Serial takes 157 bytes according to a simple test here, which makes sense, because on the UNO it has two ring buffers for transmit and receive that are 64 bytes in size each, half a dozen pointers for configuring hardware registers to use, and head and tail indices for those buffers.  There's also another 12 bytes that are used for HardWareSerial's vtable.

So that puts you down to conservatively 137 bytes of SRAM for well, everything else.

### Everything Else ###

There's a lot not accounted for here. Your globals, the libraries globals, other vtables, the String data on the heap, and the stack.  Those are just the ones coming to mind.  I mean just the `millis()`/`micros()` counter variables and fract take 9 bytes.  If you really want to dig into the details here, besides looking at the stack pointer and heap structure, the `avr-nm` command run on your sketch's .elf file with its `-D`, `-S`, and `--size-sort` is helpful for locating global variable usage and similar things.

  [1]: https://github.com/adafruit/Adafruit_SSD1306/blob/2.4.4/Adafruit_SSD1306.cpp#L466
  [2]: https://github.com/olikraus/u8g2
  [3]: https://github.com/olikraus/u8glib/wiki/tpictureloop
  [4]: https://github.com/arduino-libraries/SD/blob/1.2.4/src/utility/SdFat.h#L465
  [5]: https://github.com/greiman/PetitFS
  [6]: http://elm-chan.org/fsw/ff/00index_p.html
  [7]: https://www.arduino.cc/reference/en/language/variables/utilities/progmem/


message:
How do I get sensor values using transmitter and receiver?

I used an HC-SR04 sensor and connected it to an Arduino board (BOARD1) with a 433 MHz transmitter, and the other board (BOARD2) is connected to the 433 MHz receiver. I don't know how to see the sensor value readings from the (BOARD1) in the serial monitor.

**HERE IS THE CODE OF THE TRANSMITTER**

    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile

    RH_ASK driver;
    int echo=11;
    int trig=9; int sensorval;
    void setup() {
       Serial.begin(9600); // Debugging only
       driver.init();
    }

    void loop() {
       digitalWrite(trig,LOW);
       delayMicroseconds(10);
       digitalWrite(trig,HIGH);
       delayMicroseconds(10);
       digitalWrite(trig,LOW);
       delayMicroseconds(10);
       sensorval=pulseIn(echo,HIGH);
       const char *msg = sensorval;
       driver.send((uint8_t *)msg, strlen(msg));
       driver.waitPacketSent();
       delay(200);
    }

**HERE IS THE CODE OF THE RECEIVER**

    #include <RH_ASK.h>
    #include <SPI.h> // Not actually used but needed to compile

    RH_ASK driver;
    const int sensorval;
    void setup() {
        Serial.begin(9600); // Debugging only
        driver.init();
    }

    void loop() {
        uint8_t buf[4];
        uint8_t buflen = sizeof(buf);
        if (driver.recv(buf, &buflen)) // Non-blocking
        {
     Serial.print("message Received: ");
     Serial.println((char*)buf);
        }
    }

body:
**First: A short excourse about c-strings**

In C a string is an array of characters. Such an array is defined with

    char msg[10];

`10` being the size of the array. Every valid c-string needs to be terminated with the null character `\0`. This character is not printable, thus you don't see it normally. But the standard string functions (like `printf()`, `strlen()`, etc) use the null character to find the end of the string. So when handling strings as `char` arrays, you absolutely always need to terminate the string with the null character. The standard functions are incrementing through the array, until they find the null character. If it is missing, they don't stop at the end of the array.

Needing the null character also means, that the above `char` array can only hold 9 characters (since the 10th is the null character).

The standard functions for creating a string (like `printf()` and its siblings) already terminate the string correctly with the null character.

---

You are obviously trying to send an ASCII encoded string. But `sensorval` is not a string, it is of type `int` (a number). In C/C++ one does not simply implicitly convert a number to a string (please insert the image of boromir from Lord of the Rings here in your head). You actually have to say the compiler how to convert the number to a string. Also `sensorval` cannot itself hold that string (as it is an integer number). For that you need a `char` array (often called c-string) for saving all the characters of your string.

So first we need to define the `char` array to hold our string:

    char msg[10];

This creates a `char` array with 10 elements, each one can hold a character of your string. So you have space for 9 characters. If you need more, you can increase that number.

Now we need to build a string in `msg`, that represents the value of `sensorval`. For that we can use `sprintf()`, which lets us format a string out of data and save it in a `char` array.

    sprintf(msg, "%d", sensorval);

The first parameter is the `char` array to put the string in. The second parameter is called format-string. That is a string literal, that defines the format. `%d` represents an integer value; it is a placeholder for the actual data and describes, how it should be formatted (you can read about the different format options in the C++ documentation if you search for `printf()`). The following parameters (here only one) are the data values for the placeholders in the format string. Let's take an example: Assume `sensorval` is 1000. Then `msg` will be:

    1000\0

The `\0` being the null character.

So in your code you would replace

    const char *msg = sensorval;

with

    char msg[10];
    sprintf(msg, "%d", sensorval);

---

**What you have done in your code:**

This line

    const char *msg = sensorval;

will NOT create a string. You are defining `msg` as a pointer to a constant character (a pointer is a variable, that holds the address another variable in the memory, use google terms like "C pointers" for more info). And then you set the pointer to `sensorval`, which of course is not a valid pointer (valid meaning pointing to something reasonable here). It just points somewhere in the memory.

The example, that you got it from uses:

    const char *msg = "hello";

This works, because the compiler takes all string literals (the strings enclosed by the double quotes) and puts them fixed into the memory, somewhat like a variable without a name. So here the compiler instructs the microcontroller so save the string `"hello"` in the memory. With the above line we define a pointer to the place in the memory, where this string is saved.

So this works good for string literals, but not, if you first need to actually build the string.


message:
Basic hardware debouncing

I was watching Jeremy Blum's Arduino tutorial series, and he explained the need for debouncing in a simple circuit involving a pushbutton. Pressing the button once should mean the led *stays* on, and pushing the button again should mean the led should *stay* off, and so on.

He implemented hardware debouncing on this circuit: using an RC circuit along with an inverting Schmitt trigger.

https://www.youtube.com/watch?v=CRJUdf5TTQQ&list=PLA567CE235D39FA84&index=10 2:45-8:45.

However, the circuit isn't performing as expected, when I implemented the denbuncing. Its behaving as if the debouncing has no effect:-
[![enter image description here][1]][1]

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

If anyone wants to see the simulation:-
https://www.tinkercad.com/things/dniOQmnxJPY

Where exactly have I gone wrong? I have checked all the connections multiple times, it seems to be what Jeremy blum had in his video...

body:
You did not change the lastbutton, but you compared it to HIGH. Change your code to the one below.

You can more easily avoid such mistakes, if you put spaces around operators.

```
//sp is switchpin, lp is ledpin

int sp=2; //interrupt enabled pin (interrupt 0)
bool ledon=LOW;
bool lastbutton=LOW;
int lp=9;
void setup()
{
  Serial.begin(9600);
  pinMode(sp, INPUT);
  pinMode(lp,OUTPUT);
}

void loop()
{

   if (digitalRead(sp)==HIGH && lastbutton==LOW){
      ledon=!ledon;
      lastbutton = HIGH; // previously here was lastbutton==HIGH;
   }

   else {
     lastbutton=digitalRead(sp);
      }
   Serial.println(ledon);
   digitalWrite(lp,ledon);

     }
```


message:
Would someone provide an example of extracting data from a char array?

- I have tried so many things now that I am just confused.
 - I am not understanding the way *char arrays* work.
 - I can't get the date and names extracted.  And when I use just strings, I jam up the memory.

Below was my last attempt, before asking the question.

    while (f.available()) {
      String line = f.readStringUntil('\n');

      if (line.startsWith("04-23")) {
        currentDay = 1;
        int str_len = line.length() + 1;
        char char_array[str_len];
        line.toCharArray(char_array, str_len);
        Serial.println(char_array);                 // Everything works to here
        for (int j = 0; j < 2; j++) {
          b += char_array[j];
        }
        bMth = b.toInt (); // This should be an int of the birth month in this case: 04
      }
    }

    Var:
    format: MM-DD-YYYY,Name  // this is inside the file
    line = "04-23-2020,James"  // This is the output from - Serial.println(char_array);

**What I am trying to do is**
 - Extract the month/day so that I can compare it to today.
 - The year so I can calculate the age.
 - The name to display on OLED.
 - Everything else seems to work, but I can't get my head
   wrapped around the **char array** access.

To do this in PowerShell I would do:

    $line = "04-23-2020,James"

    $dob = ($line.Split(","))[0]
    $bMth = ($dob.Split("-"))[0] # This is not used in this example
    $bDy = ($dob.Split("-"))[1]  # This is not used in this example
    $bYr = ($dob.Split("-"))[2]

    $age = $(get-date -UFormat %Y) - $bYr

    Clear-Host
    Write-Host (@'
    Name: {0}
    Age:  {1}

    '@ -f $($line.Split(","))[1], $age)

In Python:

    import datetime as dt

    line = "04-23-2020,James"

    dob = (line.split(',')[0])
    bMth = (dob.split("-"))[0] # This is not used in this example
    bDy = (dob.split("-"))[1]  # This is not used in this example
    bYr = (dob.split("-"))[2]

    age = int(dt.datetime.now().year) - int(bYr)

    print('Name: ',(line.split(',')[1]))
    print('Age: ', age)

body:
You could try [sscanf][1] if your data format is fixed, something like this:

```c++
char line[] = "04-23-2020,James";
int day, month, year;
char name[100];
if (sscanf(line, "%d-%d-%d,%s", &month, &day, &year, name) == 4)
{
    // Process the four items.
}
```

  [1]: https://www.cplusplus.com/reference/cstdio/sscanf/


body:
When working with Arduino, [cplusplus.com][1] is your friend. Scroll down and look on the left side under **(string.h)**. Lot's of great `char` functions there. Other useful functions such as `iota()` - [cplusplus.com][2].

Here's one way to accomplish the parsing of the input data.

```
// Sketch uses 2064 bytes (6%) of program storage space.
// Global variables use 323 bytes (15%) of dynamic memory.
// Arduino IDE 1.8.9.
char line[] = "04-23-2020,James";
char Name[100];
unsigned int Month, Day, Year;

// Make an attempt to validate the input data.
byte Counter = 0;

void setup(){

  Serial.begin(9600);

  char * pch = strtok(line, "-,");

  while(pch != NULL){
    if(Counter == 0){Month = atoi(pch);}
    else if(Counter == 1){Day = atoi(pch);}
    else if(Counter == 2){Year = atoi(pch);}
    else if(Counter == 3){strcpy(Name, pch);}
    pch = strtok(NULL, "-,");
    Counter += 1;
  }

  // Print out the data.
  if(Counter == 4){
    Serial.println(Month);
    Serial.println(Day);
    Serial.println(Year);
    Serial.println(Name);
  }
  else{
    Serial.println("Error");
  }

}

void loop(){}
```

  [1]: https://www.cplusplus.com/reference/cstring/strcpy/
  [2]: https://www.cplusplus.com/reference/cstdlib/itoa/


message:
Networking Multiple Arduinos -- Is It "Rocket Science?"

Have a set of Arduinos that need to swap data--for a model rocket launch controller!

How to send 24 bits of info (launch commands) from a "master" Arduino, 12 bits each to two "slave" Arduinos that are 15' to 150' away from the "master.

Each "slave" needs to send 12 bits of info (continuity statii) to the "master."

"Master" <--- 15' to 115' ---> "Slave 1" <--- 10' to 35' --> "Slave 2"

Seems too long for I2C?

body:
The best solution would be to use an RS485 adapter connected to each Arduino via serial port. This is a tried and true solution that is perfect for a setup like this and only costs a [few bucks of extra hardware][1] per node.

If you can't use additional hardware, you can also create a poor-man's current loop system like RS485 using normal Arduino pins since they are capable of sourcing and sinking 20mA.

With either of these solutions, you can send however much data as you want as long as you have some kind of minimal protocol to serialize it into a sequence of bits on the wire. To send 12 bits, you might just define a start condition as an idle "0" on the wire for a certain period of time, followed by a "1" start bit, followed by you 12 data bits, followed  maybe a parity bit or a checksum, and completed by a "1" stop bit.

Check out how, say RS232 or RS485 serialize bits to get an idea of how this works. If you end up using hardware that only supports sending data in 8 bit chunks, then you could, say, send two bytes per data "packet" where each byte has 6 bits of your data, plus one bit that indicates if ths byte is the first group of 6 bits or the second group, and then one bit of parity for error checking.

  [1]: https://amzn.to/3nAAou3


body:
I've got I2C to work reliability between Arduinos with different byte sizes. I have copied the test code below. Note that there is separate code for sending and receiving. It may need to be tweaked but contains the basic idea.

One (or more) Arduinos sends to main I2C controller:

**Sender Code:**
```
//sender test

#include <Wire.h>

#include <Wire.h>
#define NUMDATA 4

byte byteData[2 * NUMDATA]; //= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

//test

void setup()
{
  Wire.begin(3);                // join i2c bus with address #3
  Wire.onRequest(requestEvent); // register event
}

void loop()
{
int aData;
  for(int i = 0; i < NUMDATA; i++){
    aData = analogRead(i);

    byteData[i*2 + 1] = ((aData >> 8)  & 0xFF);
    byteData[i*2] = (aData & 0xFF);

   // memcpy((void *)byteData[i*2], (void *) analogRead(i), sizeof(int));
  }

}

void requestEvent()
{
  Wire.write(byteData, 2 * NUMDATA);
}
```

**Receiving Code:**

```
#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus (address optional for main controller)
  Serial.begin(9600);  // start Serial for output
}

void loop()
{

  getSenderData();

  Serial.println("Hello");
  delay(500);
}

void getSenderData() {
//Gets sensor data for one grid

    //Byte Array to get raw bytes
    byte ICdataAsBytes[8];
    int i = 0;

    Wire.requestFrom(3,8);    // request 6 bytes from sending device #2

    while(Wire.available())    // sender may send less than requested
        ICdataAsBytes[i++] = Wire.read();

    int *tempData =(int*)&ICdataAsBytes;

    for( i = 0; i < 4; i++)
        Serial.println(tempData[i]);

}

```


message:
Interfacing LM35 and MQ2 with Arduino

When I interface LM35 temperature sensor and MQ-2 gas sensor with Arduino - my LM35 sensor gave incorrect values. From research I've found out that MQ-2 gas sensor dragging the AREF voltage down and causing the error due to its 31ohm heater that drawn 161mA current . What'll I do to solve this problem?

body:
A wiring diagram would help! But it sounds like you're powering your sensor from the Arduino's AREF pin. That is not the purpose of AREF; AREF is there for you to provide an accurate +5v or other reference voltage to the A/D convertor.

You need to power the sensor independently from your 5v supply (and not through the Arduino either, because of the sensors current draw); connect the sensor's Analog Out to one of the Arduino's A/D pins, sensor Ground to the supply ground. The digital out appears to be optional, if all you want is a go/no-go output that you adjust with the on-sensor potentiometer.


message:
Arduino Serial.readString() trouble

Hello everyone I write my code and have some troubles.
When I write on in my serial monitor my buzzer condition wasn't changed.
Can you help me realize the reason. I wrote code with int type and it works with Serial.parseInt() function properly.

    String ask="Please enter buzzer condition";
    int buzzerPin=2;
    String state;
    void setup() {
      pinMode(buzzerPin,OUTPUT);
      Serial.begin(115200);

    }

    void loop() {
     Serial.println(ask);
     state=Serial.readString();
     Serial.println(state);
     while(Serial.available()==0){

     }
     if(state=="on"){
      digitalWrite(buzzerPin,HIGH);
     }
     if(state=="off"){
      digitalWrite(buzzerPin,LOW);
    }
    }

body:
You need to use `Serial.readStringUntil('\n')` instead of `Serial.readString` if you use the Arduino IDE's serial monitor (where a `\n` is added as termination character when you press enter).
Also remove that `while(Serial.available()==0)`. It will wait as long as there are any bytes in the serial buffer and as you don't `Serial.read()` within the loop, the buffer will not be emptied. So, if anything is received while `Serial.println(state)` is called or if you send two termination characters, the program will be stuck in that loop.


message:
How do I make my piezo buzzer only hum once without repetition?

I have a problem with getting my buzzer to only do the tones I programmed in *once*. I know I have to add some sort of code but I'm relatively new to this so I don't really know. I want it to start playing the tones I have in the code once I press the button. After that it should immediately stop, without looping everything until I press the button again. Basically I have these LEDs that light up in a row with every time I press my button and once the last LED lights up, the buzzer should play its melody. After that, I can press my button again and the whole thing starts from the beginning. If anyone could help, I'd be more than grateful!

This is my code:

```
#define button 3

#define LED 1
#define twoLED 2
#define threeLED 4
#define fourLED 5
#define fiveLED 6
#define sixLED 7
#define sevenLED 8
#define eightLED 9
#define nineLED 10
#define tenLED 11

int state = 0;
int old = 0;
int buttonPoll = 0;

void setup() {
  pinMode (3,INPUT);
  pinMode (11,OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(twoLED, OUTPUT);
  pinMode(threeLED, OUTPUT);
  pinMode(fourLED, OUTPUT);
  pinMode(fiveLED, OUTPUT);
  pinMode(sixLED, OUTPUT);
  pinMode(sevenLED, OUTPUT);
  pinMode(eightLED, OUTPUT);
  pinMode(nineLED, OUTPUT);
  pinMode(tenLED, OUTPUT);

  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

}

void loop() {

  buttonPoll = digitalRead (3);
  if (buttonPoll ==1) {
    delay (50);
    buttonPoll = digitalRead (3);
    if (buttonPoll == 0) {
      state = old + 1;
    }
  }
  else {
    delay(100);

  }

  switch (state) {
    case 1:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 2:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 3:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 4:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 5:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 6:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 7:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 8:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 9:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 10:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, HIGH);
   old = state;

       tone (11,261);
      delay(250);

      tone(11, 330);
      delay(250);

      tone(11,391.99);
      delay(250);

      tone(11,440);
      delay(250);

      tone(11, 391.995);
      delay(250);

      tone(11, 330);
      delay(250);

        }

    break;

   default:
  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

    old = 0;

    break;

  }
}
```

body:
Enshrine the first section of the `loop()` code inside a `while` loop.

    while (condition)
    {
        // this code executes continually until 'condition' is true
    }

In your case, the variable `state` changes when an active button press is recorded: use that as your `condition`.

    while (state == old)
    {
      buttonPoll = digitalRead (3);
      if (buttonPoll ==1)
      {
        delay (50);
        buttonPoll = digitalRead (3);
        if (buttonPoll == 0)
        {
          state = old + 1;
        }
      }
      else
      {
        delay(100);
      }
    }

So long as `state` stays the same, i.e. it equals `old`, the code within the `while` loop will execute indefinitely.
*NOTE:* Any code outside the `while` loop will effectively only run once. You may find, if you expand the code, most of it lives within the `while` loop. If that is the case there may be better approach to consider.


body: Once the LEDs & Piezo sequence finishes, your code doesn't wait for the button to be pressed again. If the button is not pressed, the code doesn't wait, it merely delays for 100ms, then repeats the sequence.


body:
Welcome to ASE :)

1. You have mapped the Tone function and the LED to the same Pins. So, you may have to find another pin for the buzzer (pin 0 )
2. I have taken code from @charlieHanson as well.
3. The braces for the switch statement were put in the wrong place. I have fixed it.

Have a try: The code is here

    #define button 3

    #define LED 1
    #define twoLED 2
    #define threeLED 4
    #define fourLED 5
    #define fiveLED 6
    #define sixLED 7
    #define sevenLED 8
    #define eightLED 9
    #define nineLED 10
    #define tenLED 11

    int state = 0;
    int old = 0;
    int buttonPoll = 0;

    void setup() {
      pinMode (3, INPUT_PULLUP);
      pinMode (11, OUTPUT);
      pinMode(LED, OUTPUT);
      pinMode(twoLED, OUTPUT);
      pinMode(threeLED, OUTPUT);
      pinMode(fourLED, OUTPUT);
      pinMode(fiveLED, OUTPUT);
      pinMode(sixLED, OUTPUT);
      pinMode(sevenLED, OUTPUT);
      pinMode(eightLED, OUTPUT);
      pinMode(nineLED, OUTPUT);
      pinMode(tenLED, OUTPUT);

      digitalWrite(LED, LOW);
      digitalWrite(twoLED, LOW);
      digitalWrite(threeLED, LOW);
      digitalWrite(fourLED, LOW);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);

    }

    void loop() {

      while (state == old)
      {
        buttonPoll = digitalRead (3);
        if (buttonPoll == 1)
        {
          delay (50);
          buttonPoll = digitalRead (3);
          if (buttonPoll == 0)
          {
            state = old + 1;
          }
        }
        else
        {
          delay(100);
        }
      }

      switch (state) {
        case 1:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, LOW);
          digitalWrite(threeLED, LOW);
          digitalWrite(fourLED, LOW);
          digitalWrite(fiveLED, LOW);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 2:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, LOW);
          digitalWrite(fourLED, LOW);
          digitalWrite(fiveLED, LOW);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 3:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, LOW);
          digitalWrite(fiveLED, LOW);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 4:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, LOW);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 5:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 6:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, HIGH);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 7:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, HIGH);
          digitalWrite(sevenLED, HIGH);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 8:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, HIGH);
          digitalWrite(sevenLED, HIGH);
          digitalWrite(eightLED, HIGH);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 9:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, HIGH);
          digitalWrite(sevenLED, HIGH);
          digitalWrite(eightLED, HIGH);
          digitalWrite(nineLED, HIGH);
          digitalWrite(tenLED, LOW);
          old = state;
          break;

        case 10:
          digitalWrite(LED, HIGH);
          digitalWrite(twoLED, HIGH);
          digitalWrite(threeLED, HIGH);
          digitalWrite(fourLED, HIGH);
          digitalWrite(fiveLED, HIGH);
          digitalWrite(sixLED, HIGH);
          digitalWrite(sevenLED, HIGH);
          digitalWrite(eightLED, HIGH);
          digitalWrite(nineLED, HIGH);
          digitalWrite(tenLED, HIGH);
          old = 0;
          state = 0;

          tone (11, 261);
          delay(250);

          tone(11, 330);
          delay(250);

          tone(11, 391.99);
          delay(250);

          tone(11, 440);
          delay(250);

          tone(11, 391.995);
          delay(250);

          tone(11, 330);
          delay(250);
          noTone(11);

          break;

        default:
          digitalWrite(LED, LOW);
          digitalWrite(twoLED, LOW);
          digitalWrite(threeLED, LOW);
          digitalWrite(fourLED, LOW);
          digitalWrite(fiveLED, LOW);
          digitalWrite(sixLED, LOW);
          digitalWrite(sevenLED, LOW);
          digitalWrite(eightLED, LOW);
          digitalWrite(nineLED, LOW);
          digitalWrite(tenLED, LOW);

          old = 0;

          break;

      }
    }

Here is the preview :)
[![enter image description here][2]][2]

Here is the Arduino simulator link: [https://wokwi.com/arduino/projects/297098737606459913][1]

  [1]: https://wokwi.com/arduino/projects/297098737606459913
  [2]: https://i.stack.imgur.com/whbd9.gif


message:
MKR 1010 disconnects COM-port on each upload

Each time I attempt to upload to the *MKR WiFi 1010* board the COM-port gets disconnected, usually at one of the following points:

 1. Either it disconnects just after compiling/verifying. In this case the `LED_BUILTIN` pulsates slowly, and the USB-cable needs to be reconnected in order to try again. The next attempt usually results in `2.`.

 2. Or, it disconnects after a successful upload. The next attempt to upload will always result in `1.` occurring. When this happens the COM-port is still visible in Windows Device Manager but it can't be found by a Serial Monitor.

Any ideas what could be causing this or what could be done to have it stay connected? With an *UNO* this doesn't happen.

body: This was due to using a virtual machine (VMware) which apparently doesn't handle the MKR board COM-port so well. Moving the development environment to the host solved the problem. It still disconnects the COM-port after upload but then consistently reconnects to the same COM-port and that's good enough.


message:
Why does my stepper motor run when I open the Serial port?

For some reason my motor moves a certain amount every time I open the serial port without giving it any other instructions. It will move further by the same amount if I close and reopen the serial port. Please could someone tell me how to avoid this? I haven't had this problem before.

I am using two stepper motors with a A4988 driver each.

Here is my code so far

    #include <AccelStepper.h>
    #include <MultiStepper.h>

    // Define pin connections
    const int dirPin1 = 2;
    const int stepPin1 = 3;
    const int dirPin2 = 4;
    const int stepPin2 = 5;

    String incomingByte; // for incoming serial data

    // Define motor interface type
    #define motorInterfaceType 1

    // Creates an instance
    AccelStepper stepper1(motorInterfaceType, stepPin1, dirPin1);
    AccelStepper stepper2(motorInterfaceType, stepPin2, dirPin2);

    MultiStepper steppers;

    void setup() {
      Serial.begin(9600);
      String excess1 = Serial.readString();
      // Configure each stepper
      stepper1.setCurrentPosition(0);
      stepper2.setCurrentPosition(0);
      stepper1.setMaxSpeed(100);
      stepper2.setMaxSpeed(100);
      stepper1.setAcceleration(10);
      stepper2.setAcceleration(10);
      // Then give them to MultiStepper to manage
      steppers.addStepper(stepper1);
      steppers.addStepper(stepper2);
    }

    void loop() {
      // send data only when you receive data:
      if (Serial.available() > 0) {
        // read the incoming byte:
        incomingByte = Serial.readString();

        // say what you got:
        Serial.print("I received: ");
        //Serial.println(incomingByte, DEC);
        Serial.println(incomingByte);

        int x = incomingByte.toInt();

        long positions[2];

        positions[0] = x;
        positions[1] = 0;
        steppers.moveTo(positions);
        steppers.runSpeedToPosition();
      }
    }

body:
When you open or reopen the Serial port, the Arduino resets (depending on how you open it; some programs don't send the signal on DTR or RTS, which result in the reset).

My guess is, that the stepper driver reacts to the Arduino configuring its pins for the stepper. Difficult to say, what exactly happens there. To mitigate that, you can add an external pulldown resistor (assuming you have an active high stepper driver. For active low use a pullup resistor). That should keep the step line of the driver low even when its not actively driven by the Arduino.


message:
Blynk, but continue program if Blynk connection fails

I'm having an issue with Blynk.begin(auth, ssid, pass);
The problem is, when it fails to connect to the wifi, the rest of the program does not continue.

I'm using a Wemos D1 and it is also controlling some relays based on a temperature sensor.
But when there was a power outage and power comes back on, the programs should continue whether the wifi is working or not, so that relays can still be controlled by the temperature sensor reading.

What happens now is if there is a wifi issue when Wemos D1 is starting up again, the program simply stops in the void setup() at Blynk.begin(auth, ssid, pass); and the rest of the program cannot be executed.

Anyone knows how to avoid this?

Kind regards,
Peter

body:
You can try my [Blynk_WM](https://github.com/khoih-prog/Blynk_WM) or [Blynk_Async_WM](https://github.com/khoih-prog/Blynk_Async_WM) library with their Blynk.begin() functions are not blocking.

---

Check [Why using this Blynk_WiFiManager with MultiWiFi-MultiBlynk features](https://github.com/khoih-prog/Blynk_WM#why-using-this-blynk_wifimanager-with-multiwifi-multiblynk-features)

### Why using this [Blynk_WiFiManager](https://github.com/khoih-prog/Blynk_WM) with MultiWiFi-MultiBlynk features

You can see that the system **automatically detects and connects to the best or avaiable WiFi APs and/or Blynk Servers**, whenever interruption happens. This feature is very useful for systems requiring high degree of reliability.

Moreover, this `Blynk.begin()` is **not a blocking call**, so you can use it for critical functions requiring in loop().

Anyway, this is better for projects using Blynk just for GUI (graphical user interface).

In operation, if WiFi or Blynk connection is lost, `Blynk.run()` will try reconnecting automatically. Therefore, `Blynk.run()` must be called in the `loop()` function. Don't use:

```cpp
void loop()
{
  if (Blynk.connected())
     Blynk.run();

  ...
}
```
just

```cpp
void loop()
{
  Blynk.run();
  ...
}
```

---

It's also beneficial to search in [Blynk Forum](https://community.blynk.cc) for more information and examples


message:
why can Arduino variables of int type contain a value such as A2

How come the following statement is true:
```cpp
int inputPin = A2;
```
I thought int variables can only hold integer numbers. Is the `A` just a representation of a number?

Thanks for any help

body:
You are correct. `A2` is just a number (like everything in a microcontroller). We can look at the corresponding part in `pins_arduino.h` (a file defined in the variants folder of your used core and of your used board, for me: `~/arduino-1.8.9/hardware/arduino/avr/variants/standard/pins_arduino.h`):

    #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;

So here the core first defines the macro `PIN_A2` as 16 (which is the pin number of that pin) and then it declares a static constant `A2` with `PIN_A2`. So `A2` is just the pin number of that pin, `16` in this case.

This is done to make the code more readable. The analog pins are marked with `A0` to `A7`, so it is good to also be able to refer to that with these names. If you wanted, you could also use the pin number directly. But that wouldn't be as easy to read.


body: The value of the symbol 'A2' *is* an integer - it is an Arduino pin number. For an Uno, it is equal to 16. Are you maybe confusing the pin number, A2, with the value read from A/D channel 2? That would be the value returned by `analogRead(A2)` or `analogRead(PIN_A2)` as it has been #define'd. And even then, that value is also an integer between 0 and 1023, which represents the voltage on the pin, 0 representing 0v or Ground, and 1024 representing the reference voltage (therefore, 1023 represents any voltage that is greater or equal to ((1023/1024) * Vref).


message:
Can i use PL2303 USB to TTL Serial Converter Module send keystrokes using Arduino nano?

If I can, which library to use (an example code will be great).
Here is the module:
[![PL2303 USB to TTL Serial Converter Module][1]][1]

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

body:
No. That is serial. Just like every other USB to TTL Serial converter. The clue is in the name.

You need an Arduino with a dedicated native USB interface, like those based on the ATMega32U4 chip.

Or dedicated software on the PC that will read serial data and emulate keypresses (which is outside the scope of this website).


message:
Basic doubt regarding encoders with Arduino

I created a program that measures the pulses set out by the encoder (part of the dc motor with encoder inbuilt), and uses the ppr value (pulses per rotation) to calculate the rotations per minute (rpm)

However, the serial monitor continuously shows 0 for the variable "pulsecount", that maintains the total pulses sent.
[![enter image description here][1]][1]

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

code:

    float ppr=512.0;
    int encpin=3;
    volatile long pulsecount=0;
    float revs;
    float rps;
    float rpm;
    unsigned long time;

    void setup()
    {
      pinMode(encpin,INPUT);
      Serial.begin(9600);
      attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                               //interrupt triggered,
                                               //function callled
    }
    void function(){
      pulsecount+=1;
    }

    void loop()
    {
     revs= pulsecount/ppr ;
     time=millis()/1000;
     rps=revs/time ;
     rpm=revs*60;
     Serial.println(pulsecount);
    }

body:
You code counts pulses just fine when tested here.

Fan/motor tachometer outputs and encoders frequently are set to switch your signal contact to ground, either with a transistor or mechanically.  When the ground contact is not being made, the signal connection is floating and not reliably HIGH.  So, you need a pullup resistor on the pin, just like you do for a typical push button switch configured to switch to ground.

My comment on the question:

> What happens if you use `INPUT_PULLUP` rather than `INPUT`?

was referring to doing this in your code:

```c++
pinMode(encpin, INPUT_PULLUP);
```

At higher frequencies, higher RPM, you may need to use an external resistor to get a lower resistance value than the 20k-50k of the internal pullup resistor that `INPUT_PULLUP` enables.

It is best to turn off interrupts when you retrieve your `volatile` pulse counter variable so that there's no tearing of the value where the ISR interrupts your code mid-read and updates the latter half of the value.

e.g.:

```c++
// Note I've switched your pulsecount variable
//  to unsigned long for this example.
unsigned long get_pulsecount() {
  noInterrupts();
  const auto r = pulsecount;
  interrupts();
  return r;
}
```

Note you can probably avoid `float` usage altogether, and should if you can.


body:
It is hard to find the error in these TinkerCad examples, because I do not know where to find the datasheet of the components used there and I am never sure, what am I debugging, the program or Tinkercad?

Anyhow, the encoder simulated there needs to be connected with a pull-up resistor. Arduino has a built-in pullup and you can activate via the `pinmode()` function:

```
void setup()
{
  pinMode(encpin,INPUT_PULLUP); //  before here was pinMode(encpin,INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled
}
```

But notice: your types are all over the place and I expect that you get some bugs due to this. Avoid to divide float and int variables without converting, especially this can cause trouble, because you might divide by 0:

```
 time=millis()/1000;
 rps=revs/time ;
```
Also it is a long shot to have basic doubts regarding encoders and arduino, just because some code does not work. Many people are using encoders all the time and countless libraries of encoders have been published for arduino.


message:
How to implement Arduino NANO as a RS-232 to USB adapter (Or do I need a Arduino Mega?) For 3D printer comms

I have a PC upstairs running my 3D printing slicer program (Simplify 3D). In the basement, I have several USB-enable 3D printers. My PC upstairs has a USB-to-RS-232 serial adapter. The serial side of that USB-to-Serial adapter connects to the Serial port of a Moxa Nport 6150 RS232-to-Ethernet protocol adapter. I get those Moxa devices for free when they break at work and then fix them for a couple of dollars.

The other side of the Moxa connects to my home computer network router. In the basement I can plug another Moxa into an ethernet cable on my home network and the serial RS232 output I need to connect to the Micro-USB jack of the 3D printer. How can I use an Arduino Nano (or Uno or Mega if required) to convert the RS232 data to the USB input of my 3D printer?

So I have PC->(RS-232)->[MOXA(RS-232)->Moxa(Ethernet)]->Router->[Moxa(Ethernet)->Moxa(RS-232)]->[Arduino(RS-232)->Arduino(USB)]->3D Printer(USB)... How can I get the Arduino to do that function? Items within [ and ] brackets are single devices performing a protocol conversion.

I know people use Raspberry Pi's and a program called OctoPrint to remotely control their 3D printers but I get the Moxas for free and Uno's or Nanos are dirt cheap. RPi's are more expensive and for several 3D printers it can start adding up. Any ideas?   [![enter image description here][1]][1]

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

body:
The Nano, like the Uno, has an onboard serial ↔ USB converter. If you
can get a logic level serial from the Moxa, then you can use the Nano to
convert that to USB:

1. Load a do-nothing sketch in the Nano
2. Connect the Moxa TX to the Nano's Tx through a 1 kΩ resistor, and the
   Moxa RX to the Nano's RX.

Yes, the second step looks backwards. The reason is that the labels RX
and TX refer to the ATmega328P that runs your sketches on the Nano.
Internally, the pin labeled RX is connected (through a resistor) to the
TX pin of the serial ↔ USB converter, and this is thus the pin you want
to connect the Moxa's RX. And similarly for the pin label TX (it's the
RX of the onboard converter).

Step 1 is important because you do _not_ want the 328P to open its
serial port. The resistor is needed for the short time when the 328P is
running the bootloader, and has its serial port open.


body:
Its not as easy as you think. An Arduino will not be enough for connecting the USB of the 3D printer. The USB protocol is strictly divided into slaves and masters. A USB(us) has exactly one master, which totally controls, what the slave can do. The slave itself cannot do much of its own.

Your 3D printer is a USB slave device. That enables a USB master (like a computer) to control it. The Arduino is also a USB slave device. If you connect both, you have a USB connection without a master. Nothing will happen. So you need to implement a USB master on the Arduino, which can handle the UART communication; all in software. That is generally possible, but I wouldn't recommend it. Also you definitely need extra hardware, because D+ and D- on USB are also electrically totally different from the TTL lines RX and TX (and also from the RS232 lines). They work differentially. So you need extra hardware to do that.

The easiest way with an Arduino would be to buy a USB host shield. With that you may be able to build, what you want.

But I would dispute, if this really makes sense. The cheapest USB host shield for Arduino, that I could find at amazon is around 10€, plus the price for an Arduino and the hassle of getting it all to work. A RaspberryPi Zero W only costs 10€. If you don't want to use wifi, you can add a USB to Ethernet adapter. And depending on the used software and its installation you might even be able to handle multiple printers with only one Pi (I use the Repertier Server, which has the ability to control multiple printers, I think). (Though depending on the number of printers and the resulting load you might wanna step up the game to a full Pi4)

---

There might be an additional way, depending on your printers. The printers microcontroller board might break the TX and RX pins out for you. Then you could connect the Arduino to them, no need for USB in that case. But that might not be an option. If the used microcontroller has a direct USB interface, there are no RX and TX pins to break out.


body:
There's not enough information to provide a general solution at this time. As chrisl rightly says, the 3D printers are expecting a connection from a host. That host connection depends on whether the USB-serial interface inside the printer is supported. These are typically FTDI or WCH (QinHeng) chips, and would need the appropriate system driver for each type. This would be hard to implement on a USB host shield for Arduino.

Most 3d printers are, in essence, an Arduino inside. The typical 8-bit controller on the vast majority of 3d printers uses a very similar ATMega microcontroller. Some newer machines use 32-bit ARM microcontrollers, which are typically 3.3 V logic compared to the Arduino's (typical) 5 V. To add a standard RS-232 port you'd need to find the RX, TX, GND and Vcc points on each printer controller board and connect the right pins of your RS-232 to TTL converter boards to those points. This would bypass the USB ports on the printers entirely.

You might experience issues with flow control and buffering with multiple ports sending from one PC and Serial-Network-Serial latency. Marlin-style Gcode printers (= most filament printers that aren't Makerbot or Flashforge, approximately) don't use flow control: the printer sends back `ok` when it's ready for the next command. If your serial ports send data too slowly, the printer will pause and print quality may suffer. 3d printers don't need a really fast serial connections (under 20 kbit/s per printer, if using Gcode) but they need the data when they're ready to print.

OctoPrint can be quite an expensive option. The minimum supported platform is a Raspberry Pi 3b+ (+ power supply, SD card, USB cable, case, ...) dedicated to each printer. While you can run a very cut-down OctoPrint on a Raspberry Pi Zero, the author does not recommend it, and you have to click through an *Unsupported Configuration: Use at your own risk* dialogue.


message:
EtherCard library without TCP

I have connected some sensors to an Arduino Uno (but the final code should run on a Pro-Mini) with an ENC28J60 shield. The sensor code works fine - until I add EtherCard. I tried UIPEthernet first, but it's even worse. The problem is the memory footprint. The ethernet libraries are consuming so much memory that random malfunctions do occur.

So I was thinking about removing TCP from the EtherCard library, because I don't need it anyway. I only need IP, ARP, UDP, and based on that DHCP, DNS and NTP.

Has someone already done this?
Is there a stripped-down library?

The file `tcp.cpp` is pretty big (the biggest in this lib). Is it safe to remove all methods with "tcp" in their name?

Or is there a better solution for this situation?

body:
My EthernetENC library based on the original UIPEthernet library by Norbert Truchsess has [settings][1] to balance performance and memory usage. These settings are in utility/uipethernet-conf.h file or can be specified as -D parameters for compilation.

`UIP_CONF_MAX_CONNECTIONS` is a maximum number of connected EthernetClient connections. The default value s 4. You can set it to 0 if you don't use EthernetClient TCp connections. It will save a lot of dynamic memory.

Arduino IDE doesn't have the possibility to set defines for a sketch (For example Sloeber has it). As some workaround to set the defines for different boards for Arduino IDE, you can create a file boards.local.txt next to boards.txt file in hardware package. Set build.extra_flags for individual boards.

comment by OP:
> Setting uno.build.extra_flags= -DUIP_CONF_MAX_CONNECTIONS=0 in "boards.txt" in the arduino IDE folder reduced program memory usage by 2442 bytes and dynamic memory usage by 290 bytes.

  [1]: https://github.com/jandrassy/EthernetENC/wiki/Settings


message:
Can someone help me figure out why only one wheel is spinning?

I am attempting to use a code which I have posted below for two wheels. However, when connected to power, only one wheel spins. I am using a 9V battery which is what was suggested so I am not sure why only one wheel spins. When both wheels are connected, the wheel that was originally working stopped spinning.

~~~ c++
#include <SPI.h>      //SPI library for communication with the nRF24L01+
#include "RF24.h"  //The main library of the nRF24L01+
#include "Wire.h"

RF24 radio (8, 9); // CE,CSN

//Create a pipe addresses for  communication
const uint64_t pipe = 0xE8E8F0F0E1LL;

struct package
{
  int X = 1;
  int Y = 1;
};

typedef struct package Package;
Package pos;

int buttonState;
int spinnerState = false ;
int motora_1 = 3;
int motora_2 = 4;
int motorb_1 = 5;
int motorb_2 = 6;
int spinner = 2;

void setup()
{
  Serial.begin(9600);
  radio.begin();                    //Start the nRF24 communicate
  radio.openReadingPipe(1, pipe);   //Sets the address of the transmitter to which the program will receive data.
  radio.startListening();
  pinMode(motora_1, OUTPUT);
  pinMode(motora_2, OUTPUT);
  pinMode(motorb_1, OUTPUT);
  pinMode(motorb_2, OUTPUT);
  pinMode(spinner, OUTPUT);
  digitalWrite(spinner, LOW);
  delay(100);
}

void loop()
{

  if (radio.available()) {
    radio.read(&pos, sizeof(pos));
    radio.read(&buttonState, sizeof(buttonState));
    Serial.print("X:");
    Serial.print(pos.X);
    Serial.print("      Y");
    Serial.print(pos.Y);
    Serial.print("      buttonState");
    Serial.println(buttonState);
  }

  int xAxis = pos.X;
  int yAxis = pos.Y;
  int forward = map(yAxis, 570, 1024, 0, 255);
  int backward = map(yAxis, 480, 0, 0, 255);
  int right = map(xAxis, 570, 1024, 0, 255);
  int left = map(xAxis, 480, 0, 0, 255);

  if (yAxis > 570) {          // Move Forward
    // Set Motor A forward
    analogWrite(motora_1, forward);
    analogWrite(motora_2, 0);
    // Set Motor B forward
    analogWrite(motorb_1, forward);
    analogWrite(motorb_2, 0);
  } else if (yAxis < 480) {                     //Move Backward
    // Set Motor A backward
    analogWrite(motora_1, 0);
    analogWrite(motora_2, backward);
    // Set Motor B backward
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, backward);
  } else if (xAxis > 570) {                     // Move Right
    // Set Motor A forward
    analogWrite(motora_1, right);
    analogWrite(motora_2, 0);
    // Set Motor B stop
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, 0);
  } else if (xAxis < 480) {                     // Move Left
    // Set Motor A stop
    analogWrite(motora_1, 0);
    analogWrite(motora_2, 0);
    // Set Motor B foward
    analogWrite(motorb_1, left);
    analogWrite(motorb_2, 0);
  } else  {     //stop
    // Set Motor A stop
    analogWrite(motora_1, 0);
    analogWrite(motora_2, 0);
    // Set Motor B stop
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, 0);
  }

  if (buttonState == 0 ) {
    spinnerState = ! spinnerState;
    delay(50);
  }

  if (spinnerState == true) {
    digitalWrite(spinner, HIGH);    //turn On spinner
    delay(100);
  } else {
    digitalWrite(spinner, LOW);      //turn Off spinner
    delay(100);
  }

}
~~~

body:
Firstly, the 9V batery is going to struggle with driving two motors. Change this 9V battery out with another power source.

As @timemage points out in his comment, you are using a PWM command on a non-PWM pin. For the Arduino Uno, the PWM pins are: 3, 5, 6, 9, 10, 11. Move the wiring and change the code so that it is using pin 9, 10 or 11 instead of pin 4.

It sounds like you are trying to test your hardware setup and your firmware at the same time. It is much easier to test your hardware first and make sure that works as expected before testing your firmware. I suggest writing a simpler program (the simpler the better) that just drives the motors full forward - one at a time and then together. Verify that it works and then change your test program so the motors spin in (full) reverse. Then change your test program so it changes the speed of the motors. Then with known working hardware test your firmware.


message:
Millis timer question

Trying to figure out how to do this in millis. So right now the code works just fine, plays mp3_play(2) while a push button is closed then plays mp3_play(1) when its open. Lets say I want mp3_play(2) to play while the push button closed but after 4 seconds if the button is still closed another audio file will be triggered to play. Cant figure that one out.

thanks
Jason

```
void fire(){

  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {

    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        mp3_play (1); //power down sound
      }

      if (buttonState == LOW) {
        mp3_play (2);  // fire sound
      }

    }
  }
  lastButtonState = reading;
}
```

body:
You have to keep track of time once a button is pressed (LOW). So `buttonLowTime` is initialized every time you press the button. In the `if` logic, you first check if the `buttonstate` is `LOW` and if the said time has been passed.

But you also mentioned you want to play the audio once. So you need to keep track if you already played the audio. So, a flag, `timeoutAudioPlayed` has been created to keep track of that. So, now, the 3rd audio will only play if:
1. The button is pressed
2. and is pressed for more than said time (`BUTTON_LOW_TIME_MAX`)
3. and if the audio hasn't been played.
</br>
>

    void fire()
    {
      static int buttonLowTime = 0; <-------------------
      static bool timeoutAudioPlayed = true; <---------

      int reading = digitalRead(buttonPin);

      if (reading != lastButtonState)
      {
        // reset the debouncing timer
        lastDebounceTime = millis();
      }

      if ((millis() - lastDebounceTime) > debounceDelay)
      {
        if (reading != buttonState)
        {
          buttonState = reading;

          if (buttonState == HIGH)
          {
            mp3_play (1); //power down sound
          }

          if (buttonState == LOW)
          {
            mp3_play (2);  // fire sound
            buttonLowTime = millis(); <-----------
            timeoutAudioPlayed = false; <---------
          }
        }
      }

      // The logic for timeout audio <------------
      if((buttonState == LOW) && (millis() - buttonLowTime) > BUTTON_LOW_TIME_MAX && timeoutAudioPlayed == false)
      {
        mp3_play (3);
        timeoutAudioPlayed = true;
      }

      lastButtonState = reading;
    }


message:
ESP8266 ISO 8601 string to tm struct

I have a web service that returns timestamps in ISO 8601 format, e.g., `"2021-06-25T12:00:00"`
I'm trying to turn the timestamp string into a tm type struct from the ESP8266 library `<time.h>`, to perform time calculations using the `difftime()` function.

I've been referring to the Redhat time functions https://sourceware.org/newlib/libc.html#time, as it seem to be compatible with the ESP library, though all i can find are functions converting tm structs to timestamp strings. Are there any functions to convert a string timestamp into a tm struct and then back into epoch? Or what would be the best way to approach this kind of conversion on the ESP8266 platform?

body:
Try `strptime` from the `time.h`.

    void setup()
    {

      struct tm tm = {0};
      char buf[100];

      // Convert to tm struct
      strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);

      // Can convert to any other format
      strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
      Serial.printf("%s", buf);
    }

    void loop()
    {
        yield();
    }


message:
How to use millis instead of delay?

Sorry if something similar has been answered before...

I am working on a garden timer project that runs on a ESP8266 based NodeMCU and is integrated with Blynk.

I have a waterNow function that activates when I press a button on the Blynk app, it sets pin D5 to HIGH and waits 3 seconds with a delay function, the problem is that with delay the code just halts all other functions until the delay is complete.

After doing some research I found out that the millis function could be used to have a time delay and have the program still run, but I can't get it to work.

How do use the millis function to add a delay?

Any help is appreciated.

Code:-

```
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "DHT.h"
#include "LiquidCrystal_PCF8574.h"

#define BLYNK_PRINT Serial
#define DHT_PIN_DATA  12
// LCD definations
#define LCD_ADDRESS 0x27
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 25
#define DHTTYPE DHT22

char auth[] = "ymri204FL9_xZhf6WIRHtQ1qEWOt9zBy";

char ssid[] = "Aihertgtel-Hotspotgfdf-82DB";
char pass[] = "";
int autoSch;
int waterNow;
int morTime;
int afterTime;
int eveTime;
int schTime;
int x;

DHT dht(DHT_PIN_DATA, DHTTYPE);
LiquidCrystal_PCF8574 lcdI2C;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "in.pool.ntp.org", 19800, 600000);
// This function will be called every time Slider Widget
// in Blynk app writes values to the Virtual Pin 1

BLYNK_CONNECTED() {
  Blynk.syncAll();
}

BLYNK_WRITE(V0)
{
  autoSch = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1)
{
  morTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V2)
{
  afterTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V3)
{
  eveTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V10)
{
  waterNow = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V4)
{
  schTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

void time_run() {
  Blynk.virtualWrite(V11, int(timeClient.getHours()));
  Blynk.virtualWrite(V12, int(timeClient.getMinutes()));
  Blynk.virtualWrite(V13, float(dht.readTempC()));
  Blynk.virtualWrite(V14, float(dht.readHumidity()));
  Serial.println(dht.readTempC());
}

void auto_run1() {
  if (morTime == 1 && String(timeClient.getFormattedTime()) > "06:00:00" && String(timeClient.getFormattedTime()) < "06:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (afterTime == 1 && String(timeClient.getFormattedTime()) > "12:00:00" && String(timeClient.getFormattedTime()) < "12:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (eveTime == 1 && String(timeClient.getFormattedTime()) > "15:47:00" && String(timeClient.getFormattedTime()) < "13:48:00") {
   // digitalWrite(14, HIGH);
    for (x; x >  10; x++){
  digitalWrite(14, HIGH);
  delay(1000);
  }
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();

  }
  else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }
}

void sch_run2() {
  if (schTime == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  } else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
  }

}

void waterNowrun() {
  if (waterNow == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Watering Now     ");
    delay(3000); // I want to remove this for millis
    Blynk.virtualWrite(V10, 0);
    Blynk.syncAll();
  } else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
  }
}
void lcd() {
  delay(300);
  lcdI2C.clear();

  timeClient.update();
  lcdI2C.print(timeClient.getFormattedTime());

  if (autoSch == 0) {
    lcdI2C.setCursor(9, 0);
    lcdI2C.print("Auto");
  } else {
    lcdI2C.print(" Sch");
  }

  if (digitalRead(14) == 1) {
    lcdI2C.selectLine(2);
    lcdI2C.print("Watering Now");
  }
  else
  {

    if (int(timeClient.getHours()) < 6 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();

      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6");
    } else if (int(timeClient.getHours()) < 12 && afterTime == 1 && autoSch == 0) {
      Blynk.syncAll();

      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 12");
    } else if (int(timeClient.getHours()) < 18 && eveTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);

      lcdI2C.print("Auto Wtr at: 18");
    } else if (int(timeClient.getHours()) >= 18 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);

      lcdI2C.print("Auto Wtr at: 6");
    } else {
      Serial.println(timeClient.getHours());
    }

  }

}

void loop()
{
  Blynk.run();
  time_run();
  lcd();
  timeClient.update();

  if (waterNow == 1) {
    waterNowrun();
  }
  if (autoSch == 0) {
    auto_run1();

  } else {
    sch_run2();

  }

}
void setup()
{
  dht.begin();
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  pinMode(16, INPUT_PULLDOWN_16);

  Serial.begin(9600);
  //WiFi.begin(ssid, password);
  Blynk.begin(auth, ssid, pass);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  timeClient.begin();
}
```

body:
I am assuming after you start watering you want to set `V10` to `0` after 3 seconds.

First, you will have to set `waterNow` to `0` after you start watring. Otherwise `waterNowrun()` will keep executing.

Second, you need to keep track of the 'watering' state so that you know that you have to start tracking the time.

Third, save the time when the watering started so that you can compare with the current time to see if your '3 seconds' has been passed.

Here is a simple example:

    // Global variables
    const long int MAX_TIME_THRESHOLD_MS = 3000;
    bool WateringStarted = false;
    long int WateringStartTime = 0;

    ... ... ...

    void waterNowrun()
    {
      if (waterNow == 1)
      {
        digitalWrite(14, HIGH);
        Blynk.virtualWrite(V5, 255);
        lcdI2C.selectLine(2);
        lcdI2C.print("Watering Now     ");

        waterNow = 0;
        WateringStarted = true;
        WateringStartTime = millis();

      }
      else   // <------ Why do you even have else! You only call waterNowrun() when waterNow == 1
      {
        digitalWrite(14, LOW);
        Blynk.virtualWrite(V5, 0);
      }
    }

    ... ... ...

    void loop()
    {
      ... ... ...

      if(WateringStarted && (millis() - WateringStartTime) > MAX_TIME_THRESHOLD_MS)
      {
        WateringStarted = false;
        Blynk.virtualWrite(V10, 0);
        Blynk.syncAll();
      }

      ... ... ...

    }

I haven't run this code and don't have your setup to check it either. But it should give you some idea. Also, check the comments to your question for some more information about `millis()`.


message:
Not have to wait for if statement to run

I need some advice. I am trying to code a setup of 4 stepper motors that are connected to a keypad and 2 DC-motors that run a conveyor belt. My goal is to be able to push a key, the correspondning stepper motor starts and the DC-motors starts as well and run for a couple of seconds after the stepper. However, I want to be able to push multiple keys while the DC-motors are running. Right now I need to wait for the DC-motors to be done before I can push another key. How can I make this happen?

I think there will be issues if I code it with a timer since the keys are waiting for an input. I don't have any sensors.

This is my code:

    #include <Keypad.h>
    #include <Stepper.h>

    const int stepsPerRevolution = 1024;

    Stepper myStepper1(stepsPerRevolution, 22, 26, 24, 28);
    Stepper myStepper2(stepsPerRevolution, 32, 36, 34, 38);
    Stepper myStepper3(stepsPerRevolution, 23, 27, 25, 29);
    Stepper myStepper4(stepsPerRevolution, 33, 37, 35, 39);

    const int IN1 = 47;
    const int IN2 = 45;
    const int IN3 = 51;
    const int IN4 = 49;

    const int ENA = 43;
    const int ENB = 53;

    const byte ROWS = 4; //four rows
    const byte COLS = 4; //three columns
    char keys[ROWS][COLS] = {
      {'D','C','B','A'},
      {'H','G','F','E'},
      {'L','K','J','I'},
      {'P','O','N','M'}
    };

    byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
    byte colPins[COLS] = {6, 7, 8, 9}; //connect to the column pinouts of the keypad

    Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

    void setup(){
      Serial.begin(9600);
       myStepper1.setSpeed(10);
       myStepper2.setSpeed(10);
       myStepper3.setSpeed(10);
       myStepper4.setSpeed(10);

      pinMode (IN1, OUTPUT);
      pinMode (IN2, OUTPUT);
      pinMode (IN3, OUTPUT);
      pinMode (IN4, OUTPUT);
      pinMode (ENA, OUTPUT);
      pinMode (ENB, OUTPUT);

    }

    void loop(){
     // char key = keypad.getKey();
     char key = keypad.waitForKey();

       if (key){
        Serial.println(key);
    //control speed
      analogWrite(ENA, 200);
      analogWrite(ENB, 200);
    //control direction
    int onTime   = 5000;
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);

    // ----------------------------------Stepper1-----------------------------

            // just print the pressed key
       if (key == 'A' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper1.step(256);
      delay(100);
    }

      // just print the pressed key
       if (key == 'E' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper1.step(512);
      delay(100);
    }

      if (key == 'I' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper1.step(768);
      delay(100);
      }

      if (key == 'M' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper1.step(1024);
      delay(100);
      }

    //-----------------------Stepper2------------------------

    if (key == 'B' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper2.step(256);
      delay(100);
    }

      // just print the pressed key
       if (key == 'F' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper2.step(512);
      delay(100);
    }

      if (key == 'J' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper2.step(768);
      delay(100);
      }

      if (key == 'N' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper2.step(1024);
      delay(100);
      }

     //------------------------Stepper3--------------------

    if (key == 'C' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper3.step(256);
      delay(100);
    }

      // just print the pressed key
       if (key == 'G' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper3.step(512);
      delay(100);
    }

      if (key == 'K' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper3.step(768);
      delay(100);
      }

      if (key == 'O' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper3.step(1024);
      delay(100);
      }

     //------------------------Stepper4--------------------

    if (key == 'D' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper4.step(256);
      delay(100);
    }

      // just print the pressed key
       if (key == 'H' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper4.step(512);
      delay(100);
    }

      if (key == 'L' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper4.step(768);
      delay(100);
      }

      if (key == 'P' ){
        Serial.println(key);
         // step one revolution in one direction:
      Serial.println("clockwise");
      myStepper4.step(1024);
      delay(100);
      }

    //---------DC_Motor---------

       delay(onTime);
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
      digitalWrite(IN4, LOW);

     }
    }

body:
The `delay(onTime);` statement in the `//---------DC_Motor---------` section of your code is preventing anything else taking place until the end of the DC motor run. Instead of delaying, you need to test how long the motor has been running, and do nothing if that time has not been reached yet. As others have pointed out, the BlinkWithoutDelay example program demonstrates how to do this. But in short, the motor section needs to do:

    // Start motor here
    timeMotorStarted = millis();
       :
       :
       :
    if( millis() - timeMotorStarted > onTime ){  // has motor run long enough?
      // stop the motor
    }


message:
Add nRF24L01 to a project

I Have a Liquid Level Project that Currently uses an Oled display.  I have just discovered the existence of the nRF24L01 wireless communication module; and it is exactly what I need to make my project more user friendly.

Eventually I want to have a dashboard that brings all my info together in one place, but for now I just want to figure out how to get my Liquid Level Project transmitting, and receive the data on another Arduino and view it on the Serial monitor.  As is all it does is print out "?" in the Serial monitor.

I have this Sketch on the Liquid Level Project Arduino:

    #include <Wire.h>
    #include "SSD1306Ascii.h"
    #include "SSD1306AsciiAvrI2c.h"
    SSD1306AsciiAvrI2c oled;
    #define I2C_ADDRESS 0x3C
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>

    double SensorAnalogValue;
    uint8_t calculation=1;
    String Show_value;

    //create an RF24 object
    RF24 radio(9, 8);  // CE, CSN

    //address through which two modules communicate.
    const byte address[6] = "00001";

    void setup()
    {

      Serial.begin(9600);
      oled.begin(&Adafruit128x64, I2C_ADDRESS);
      oled.setFont(CalLite24);
      oled.clear();

      radio.begin();

      //set the address
      radio.openWritingPipe(address);

      //Set module as transmitter
      radio.stopListening();

    }

    void loop()
    {

      SensorAnalogValue = analogRead(A0) * 5.0 / 1023.0;
      if (SensorAnalogValue < 1.726) {
        calculation=0;
        Show_value="Low";
      }
      if (SensorAnalogValue > 4.04) {
        calculation=0;
        Show_value="High";
      }
      if(calculation!=0){
      //  Serial.println(SensorAnalogValue);
        Show_value=(String)Liquid_Volume(SensorAnalogValue);
      }
      Serial.println(SensorAnalogValue);

    oled.setCursor(20, 0);
      oled.print(Show_value);
      oled.print(" L");
      oled.println(" ");
      oled.print(Show_value);
      oled.print("L");
      oled.println(" ");
    delay(500);
       oled.clear();

      radio.write(&Show_value, sizeof(Show_value));
      delay(1000);

      calculation=1;
    }
    int Liquid_Volume(double Volt) {
      double A =   2.81842;
      double B = -11.00151 ;
      double C =  14.4765 ;
      double D =  28.73579 ;

      return A * Volt * Volt * Volt + B * Volt * Volt + C * Volt + D;
    }

And the Receiver has this:

    //Include Libraries
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>

    //create an RF24 object
    RF24 radio(9, 8);  // CE, CSN

    //address through which two modules communicate.
    const byte address[6] = "00001";

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

      radio.begin();

      //set the address
      radio.openReadingPipe(0, address);

      //Set module as receiver
      radio.startListening();
    }

    void loop()
    {
      //Read the data if available in buffer
      if (radio.available())
      {
        char Show_value[32] = {0};
        radio.read(&Show_value, sizeof(Show_value));
        Serial.println(Show_value);
      }
    }

I think the problem is in:

    radio.write(&Show_value, sizeof(Show_value));

I believe "radio.write" is used kinda like Serial.print, or oled.print,  But I don't really understand the "sizeof" part, maybe that is the problem?

body:
```c++
radio.write(&Show_value, sizeof(Show_value));
```

> I believe "radio.write" is used kinda like Serial.print, or
> oled.print, But I don't really understand the "sizeof" part, maybe
> that is the problem?

Sort of.  There's kind of two interrelated problems.  The major one is that the actual data of a `String` is not contained with the actual `String` type itself.  It's [allocated on the heap][1].  What the `String` class contains is [a pointer to it and some numbers][2] for tracking the allocated size and amount used.

So the first problem is you're not reading the memory that actually contains the text inside the string.

`sizeof(Show_value)` evaluates to the size in bytes of the `String` class itself, which is the size of a pointer and a couple of integers, about 6 bytes, and not the size of the content of the string.

So you're sending a pointer (a memory address) that the receiver wouldn't know what to do with, and some information about how much was allocated and used and nothing of the String content.

Try:

```c++
radio.write(Show_value.c_str(), Show_value.length());
```

`.c_str()` gets a pointer to the actual string content itself.  And `.length()` is the actual size of the used part of the `String`'s allocated area on the heap.

That said, it's better to avoid `String` where you reasonably can.

---

Regarding:

> Does this also mean I need to `replace radio.read(&Show_value, sizeof(Show_value));`

It would. Doing that is a bit more complicated since `.c_str()` yields `const char *`; `String` isn't designed to make write-access to its underlying data as easy.

Without hacking your way around `String`'s expectations, that would require using a temporary buffer. Something like:

```c++
char buffer[33] = "";  // Note: this will actually fill the entire buffer with '\0', which some find a surprise.
// The idea in the above is to accommodate the maximum RH24L01 packet size 32 bytes plus room for a null terminator.

radio.read(buffer, sizeof buffer - 1);  // We're only making the 32 byte chunk available to the .read() call, and leaving the last byte to it's '\0' value to force null termination in any case.

String s = buffer;
```

This assuming that you're either filling the packet with bytes, or including the null terminator in the packet, or both.  If you're using a dynamic payload size, rather than initializing the array with `= "";`, it could be left uninitialized and the received packet size could be used to place the null terminator at the location needed.

You could wrap this in a function if you plan on doing it a lot.  But again, it's probably better if you can just use the array and not work with `String`.

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores/arduino/WString.cpp#L157
  [2]: https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores/arduino/WString.h#L196


message:
StoreProhibited error while trying to read file to PROGMEM

I'm trying to read a file from micro SD on an ESP32-cam board and upload to an FTP server, but when I try to read data from the opened file to an unsigned char, it gives me the following error:

```
Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x4008c674  PS      : 0x00060030  A0      : 0x800ed1c7  A1      : 0x3ffb1e20
A2      : 0x00000000  A3      : 0x3ffd7c78  A4      : 0x00000080  A5      : 0x00000000
A6      : 0x474e5089  A7      : 0x0a1a0a0d  A8      : 0x00000000  A9      : 0x3ffb1df0
A10     : 0x00000080  A11     : 0x3ffb66e4  A12     : 0x3ffd7c78  A13     : 0x00000080
A14     : 0x00002494  A15     : 0xff000000  SAR     : 0x00000018  EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000  LBEG    : 0x4008c670  LEND    : 0x4008c68c  LCOUNT  : 0x00000007

ELF file SHA256: 0000000000000000

Backtrace: 0x4008c674:0x3ffb1e20 0x400ed1c4:0x3ffb1e30 0x400ed245:0x3ffb1e60 0x400d06e7:0x3ffb1e80 0x400d084f:0x3ffb1f20 0x400d2b5a:0x3ffb1fb0 0x4008efde:0x3ffb1fd0

Rebooting...
```

The code is the following:

```
// Wifi and FTP Client Lib
#include <WiFi.h>
#include <WiFiClient.h>
#include "ESP32_FTPClient.h"

// MicroSD
#include "driver/sdmmc_host.h"
#include "driver/sdmmc_defs.h"
#include "sdmmc_cmd.h"
#include "esp_vfs_fat.h"

// FTP Server credentials
char ftp_server[] = "192.168.1.50";
char ftp_user[]   = "username";
char ftp_pass[]   = "password";

// wifi access
const char* ssid = "ssid";
const char* password = "psk";

// file to be read and uploaded
FILE *fileUpload = NULL;

// ftp client object
ESP32_FTPClient ftp (ftp_server, ftp_user, ftp_pass);

// micro sd initialization
static esp_err_t init_sdcard()
{
  esp_err_t ret = ESP_FAIL;
  sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  esp_vfs_fat_sdmmc_mount_config_t mount_config = {
    .format_if_mount_failed = false,
    .max_files = 10,
  };
  sdmmc_card_t *card;
  ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
}

void FTP_upload( void );
void FTP_upload()
{

  // initialize file name
  char fileName[100];
  sprintf(fileName, "/sdcard/img.png");
  fileUpload = fopen(fileName, "r+");

  // notify reading of the file
  Serial.print("Reading file: ");
  Serial.println(fileName);
  if (fileUpload == NULL)
  {
    Serial.println("Cannot open file");
    return;
  }

  // retrieve file size
  fseek(fileUpload, 0, SEEK_END);
  long int size = ftell(fileUpload);
  fclose(fileUpload);

  // print file size to serial
  Serial.print("File size: ");
  Serial.println(size);

  // Reading data to array of unsigned chars
  fileUpload = fopen(fileName, "r+");
  unsigned char * in PROGMEM = (unsigned char *) malloc(size);

  // display allocated memory
  Serial.print("Allocated memory: ");
  Serial.println(sizeof(in));

  // read file to allocated memory
  int bytes_read = fread(in, sizeof(unsigned char), size, fileUpload); // <------- THIS ROW RISES THE ERROR

// close file
  fclose(fileUpload);

  // Open FTP connection
  Serial.println("Starting FTP upload...");
  ftp.OpenConnection();

  //Create a file and write the image data to it;
  ftp.InitFile("Type I");

  // change remote directory
  ftp.ChangeWorkDir("/Shared/");

  // specify remote file name
  String strNome = "img.png";

  // convert String to char
  const char *f_name = strNome.c_str();

  // create a new file with the given name inside the remote directory
  ftp.NewFile( f_name );

  // write data read above from local file to remote file
  ftp.WriteData(in, sizeof(in));

  // close remote file
  ftp.CloseFile();

  // notify completed upload
  Serial.println("File uploaded successfully");

  // wait
  delay(100);

}

void setup() {

  // begin serial communication
  Serial.begin(115200);

  // initialize micro sd
  esp_err_t errSD = init_sdcard();
  if (errSD != ESP_OK) {
    Serial.printf("Cannot initialize SD. Error code: 0x%x", errSD);
    return;
  }

  // begin wifi connection
  WiFi.begin(ssid, password);

  // wait for the connection to be estabilished
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // notify successful connection
  Serial.println("");
  Serial.println("WiFi connected");

  // show the assigned IP
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

  // call the FTP upload procedure
  FTP_upload();

}

void loop() {
  // empty
}
```

How can I solve this? Thank you

body:
Solved, I changed the method a little.

In a loop, I read a portion of the file and write it to the opened FTP remote file, then I close both at the end of the cycle

```
// open FTP connection
ftp.OpenConnection();

// open local file
fileUpload = fopen("/sdcard/img.png", "r+");

// initialize file type
ftp.InitFile("Type I");

// change remote directory
ftp.ChangeWorkDir("/Shared/");

// define remote file name
String strName = "img.png";

// convert to char
const char *f_name = strName.c_str();

// create remote file with given name
ftp.NewFile( f_name );

// read all file in a loop
unsigned char buff[64];
while(!feof(fileUpload)){

    // read a portion of the file
    fread(buff, sizeof(char), sizeof(buff), fileUpload);

    // write that portion to the remote file
    ftp.WriteData(buff, sizeof(buff));
}

// close both the local and the remote file
fclose(fileUpload);
ftp.CloseFile();
```


message:
Decode rf remote signals with ESP32 or node MCU?

I'm trying to decide my rf remote signals using ESP32 or node MCU. I have tried with Arduino and was successful but for some reason it is not working on either ESP32 or node MCU even using the same GPIO2 pin can anyone please tell me why both the boards are not able to decode the signal. I'm using the rc-switch library to decode and a 433Mhz transmitter reciever combo from amazon

```#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
}

void loop() {
  if (mySwitch.available()) {
    output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
    mySwitch.resetAvailable();
  }
}```

body:
For ESP32, you should provide real GPIO number.
For instance:
mySwitch.enableReceive(13);

And without deep explanation, believe that it properly works
with GPIO 13 and 27.
Details you can find by google...