title: ESP8266 shows garbage in serial monitor

text:
# Question
Title: ESP8266 shows garbage in serial monitor
I have my ESP8266 connected via serial to USB like the image shows:

It worked just fine, however, when I tried flashing Blynk code

```
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "YourAuthToken";

void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, "ssid", "pass");
}

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

```

It started outputting loads of garbage in the serial monitor, while Blynk app said ESP is not connected to network. I've tried since then flashing empty sketches or some other stuff, whatever I do, serial monitor shows loads of junk. I've tried changing modes, I've tried changing baud rates (57600 was default, and AT worked just fine).

Junk example:

```
  …ÕZªP‚,JHVYº—¡VÕ]J*ÉW¥¡Õ¥Õ-”ªUŠQd®”¡âJ%H
!HiZÊIIRPÖuUPÒ‚BñZT¥ *EUeZB\)*EVjU!\©Š_¥¢”ÅVªqYiUµP”¬ÕPQT°*uH)HZKB*ÕXªuH!HBHBH…µEIâHBH!H©ªqY+hZVB\BH!HÊ*Òµe�qHBHBHŠ*i±…Z¦-hUµPÔ¬ÔPQT°*uH)H-KB*ÕXªuH!HBHBH…µEB\!H!HBVªqY+iZVB\BH!HeVÒZ¢qHBHBHŠ*iQ…Z¦-hUµPÔ¬ÔPQTaYRB\    jHiBHªaYRB\BH!HBVªaYRB\BH!HBVªqY+iZVB\BH!HÊVÒZ¢qHBHBHŠ*i±Õ\V
iUµPÔ¬ÕPQT°*uH)H-JBVªaYRB\BH!H!VªaYR!\BHBH!Vªq©+hZW!\BHBHJ*iµE�âHBH!HŠ*i±…Z¦-hUµPÕ¬ÔPQTaYR!\    %Hi!HÕXªuH!HBHBH…µEIqHBHBH

```

# Answer
> 2 votes
Try stabilizing the power source.

I parallel connected two AA batteries with the Arduino's 3.3V output and the garbage disappeared and my ESP8266-01 got much more stable.

# Answer
> 2 votes
In this case, it looks like your Serial Monitor just isn't set to the right baud rate with Both NL & CR. Even if your monitor is set to the default 115200 baud rate, you'll still see some garbage characters which leads into the next issue.

Using 115200 has too many instructions for the Arduino Uno to reliably decode characters and that's where the garbage is coming from.

The ESP8266 default baud is 115200, so you need to connect at the default rate and issue an AT command to reduce the baud rate to 9600.

Each time you reset, the ESP8266 goes back to the default baud rate.

Here's an example script that connects at the default baud rate and then reduces it to 9600. You'll connect the Serial Monitor at 9600. At the lower baud rate, I'm not getting any garbage characters.

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

void setup()
{
  Serial.begin(9600);
  ESPserial.begin(115200);
  ESPserial.println("AT+IPR=9600");
  delay(1000);
  ESPserial.end();
  // Start the software serial for communication with the ESP8266
  ESPserial.begin(9600);

  Serial.println("Ready");
  ESPserial.println("AT+GMR");
}

void loop()
{
    // listen for communication from the ESP8266 and then write it to the serial monitor
    if ( ESPserial.available() )   {  Serial.write( ESPserial.read() );  }

    // listen for user input and send it to the ESP8266
    if ( Serial.available() )       {  ESPserial.write( Serial.read() );  }
}

```

An odd thing that happened to me is that I tried to use a baud rate of 4800 and I bricked one ESP8266 module. I don't know if that was a glitch or just a coincidence.

# Answer
> 1 votes
I had errors in printing sensor values to serial, normal output starts with "D:" and ends with "all".

```
D: 23 24 25 23 22 22 21 22 22 22 23 24 23 24 24 24 24 25 25 25 26 26 25 25 21 21 21 21 21 21 all
 36 36 37 45 44 43 41 41 41 40 39 39 38 38 37 38 38 38 37 40 all
&&B⸮⸮R⸮B &⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮
⸮⸮5
D: 29 45 29 28 27 26 25 27 29 26 22 23 24 22 21 21 20 20 22 22 149 26 25 24 27 26 23 21 21 22 all

```

I grounded, stabilized power source, change code not to use interrupts notthing had changed

How i solved: I had spare mcu, changed it, now serial works flawlessly.

# Answer
> 0 votes
Have you also pulled up the ESP8266's reset pin? I don't know what effect not doing so might have, but the recommended connections I have read and followed include that. The RST and CH\_PD pins are adjacent; they're easy to jumper together.

# Answer
> 0 votes
I had a similar problem with a NodeMCU ESP-12E (Amica v2) board... after pressing and releasing the RST button with Serial Monitor open & set to 115200 baud, it would display the boot message (starting with " ets Jan 8 2013, rst cause:2, boot mode(3,6)", and ending with "~ld"), then display gibberish when the program itself attempted to use Serial.print() or Serial.println().

It appears to be a strange bug related to NodeMCU itself, but the following work-around got Serial.print working for me:

1. Before using Serial.print() or Serial.println() for the first time in the program (setup() is probably a good place), do **Serial.begin(74880);**
2. Step 1 notwithstanding, set the baud rate in Serial Monitor to **115200**.

My guess is that somewhere between the Arduino library and CP2102, a register value is being miscalculated (or mangled), and calling Serial.begin(74880) results in setting a register to the value that calling Serial.begin(115200) *should* have set it to.

Here's the page where I read about the bug: https://github.com/esp8266/Arduino/issues/4005

# Answer
> 0 votes
This might be related to old ESP-01 firmware. I mean 2018-ish firmware in 01s I bought 3 years ago or so.

I had the same problem –- `write_flash` works but after the reset garbage is coming in. Try this \[installs micropython; change serial device to fit your setup\]:

```
esptool.py -p /dev/tty.usbserial-02022FD3 erase_flash
esptool.py -p /dev/tty.usbserial-02022FD3 write_flash 0xfc000 esp_init_data_default.bin
esptool.py -p /dev/tty.usbserial-02022FD3 write_flash -fs 1MB 0x00000 ../upython-esp8266-1m-20220117-v1.18.bin

```

Note: the location is flash size dependant – my ESP-01s have 1 MB of flash and you can check it using the `esptool.py flash_id` command. Use this reference:

* `0x7c000` for 512 KB, modules like most ESP-01, -03, -07 etc.
* `0xfc000` for 1 MB, modules like ESP8285, PSF-A85, some ESP-01, -03 etc.
* `0x1fc000` for 2 MB
* `0x3fc000` for 4 MB, modules like ESP-12E, NodeMCU devkit 1.0, WeMos D1 mini

The `esp_init_data_default.bin` file is taken from **Espressif SDK**, here's my SHA256 of it:

```
shasum -a 256 esp_init_data_default.bin
81e04e5ec0afef0aad3b52cca2a9bbccc205f4c57334c438e1d81e38ce94b932  esp_init_data_default.bin

```

But I guess the init file from Github should work OK as well \[didn't try though\].

https://github.com/espressif/ESP8266\_RTOS\_SDK

---
Tags: esp8266
---


# Question
Title: Arduino Nano BLE 33 default example sketch `USBHID>Keyboard` makes the Arduino unusable
## How the problem started

I was playing around with using the Arduino Nano BLE 33 as a keyboard, and stumbled upon the USBHID\>Keyboard sketch which I got via the default suggestion from the Board Manager to install `Arduino Mbed OS Nano Boards`:

See the source on github.com/arduino/ArduinoCore-mbed, or reproduced below:

```
#include "PluggableUSBHID.h"
#include "USBKeyboard.h"

USBKeyboard Keyboard;

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

}

void loop() {
  // put your main code here, to run repeatedly:
  delay(1000);
  Keyboard.printf("Hello world\n\r");
}

```

It seemed fairly innocent, so I uploaded it without a second thought thinking that I could trust anything provided from Arduino itself as an example script.

## What the problem is

But now, as soon as I plug in the Nano, it types `Hello world` followed by a newline every. single. second.

If I try to upload the blink sketch to clear it, I first need to select the Port, but the act of going through the menu to choose the correct port takes over a second, and typing in `Hello world` selects the library manager and ends up opening it when enter is pressed due to the `\n\r`. So my Arduino Nano has been rendered useless by code included as an example in the default sketches. That's not cool.

## Failed Solution Number 1

I tried creating a custom keyboard shortcut to select the port in less than a second, and then pressing `cmd-U` to upload, but I think there might also be a problem there because I get this error:

```
    ...
    Found upload port: /dev/cu.usbmodem11401
    /Users/<my username>/Library/Arduino15/packages/arduino/tools/bossac/1.9.1-arduino2/bossac -d --port=cu.usbmodem11401 -U -i -e -w /var/folders/y1/md9_k_td4rz1f0pq26d24crh0000gn/T/arduino_build_230227/<my script name>.ino.bin -R
->  No device found on cu.usbmodem11401
    An error occurred while uploading the sketch
    ....

```

I'm absolutely certain that `cu.usbmodem11401` is the correct port, because that's what shows up when I `ls /dev/cu*` while the Arduino is plugged in. So I think that the Arduino IDE is attempting to upload to `cu.usbmodem11401`, but sees that it's a keyboard, and decides that it can't upload code to a keyboard so aborts.

## Failed Solution Number 2

I tried uploading `blink.ino` from a different laptop (also macos) but nothing changed.

## Failed Solution Number 3

I tried looking for ways to 'distrust' a keyboard to prevent the Arduino from sending keyboard strokes, but couldn't anything.

## Failed Solution Number 4

Maybe attempting to short circuit whichever wire the Arduino uses to communicate with the laptop will work, but I don't know nearly enough to do that so I'd just be randomly connecting wires to ground which I don't really want to do...

## Fin

I'm at a loss for what to try. I've logged an issue with the github repo, but I can't think of other solutions.

# Answer
According to the datasheet...

> ## 3.6 Board Recover
>
> All Arduino boards have a built-in bootloader which allows flashing the board via USB. In case a sketch locks up the processor and the board is not reachable anymore via USB it is possible to enter bootloader mode by double- tapping the reset button right after power up.

So, plug it in, and press the RESET button twice. That should then load the bootloader and it will sit there waiting for you to reprogram it.
> 0 votes

---
Tags: arduino-nano, keyboard, hid, mbed
---


# Question
Title: Arduino writes only one time on SD card - Data log
I connected the SD card to Arduino as it's explained here. The problem is that the Arduino writes only once to the SD card and I don't understand the reason.

```
#include <SD.h>
#include <SPI.h>

int CS_PIN = 4;

File file;

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  Serial.print("Initializing SD card...");
  if (!SD.begin(CS_PIN)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("card initialized.");
}

void loop() {
  String dataString = "TEST";
  File dataFile = SD.open("datalog.txt");
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    Serial.println(dataString);
  } else {
    Serial.println("error opening datalog.txt");
  }
  delay(1000);
}

```

The output on Serial Monitor:

> Arduino write only one time on SD card error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt error opening datalog.txt

I also tried to use:

```
SD.open("file.txt", O_RDWR | O_APPEND);
SD.open("file.txt", O_RDWR | O_CREAT);

```

As I saw Adding data to an SD card file, but it doesn't work.

# Answer
> 2 votes
You are opening the file in read mode but should be opening it in write mode. Change `File dataFile = SD.open("datalog.txt");` to `File dataFile = SD.open("datalog.txt", FILE_WRITE);`.

You can remove this line of code: `digitalWrite(10, HIGH);`.

The arduino.cc website is also an excellent source of information regarding the SD library.

# Answer
> 1 votes
> File dataFile = SD.open("datalog.txt");

Repeatedly opening the same file is probably not a good practice, if you want to retain previously written contents.

# Answer
> -1 votes
For people having the same problem. I had the same problem where the SD Card would only run the if statement once and then not read it anymore. For some reason, after I ran the CardInfo, DumpFile, and ReadWrite example scripts in the SD Library (changing the title of the SD.open() command to the one that I was using), my code began to work and it started running the if statement each time. I would recommend trying this if you're experiencing the same problem.

---
Tags: sd-card
---


# Question
Title: My PN532 doesn't detect RFID card when connected with ESP32 in I2C mode while it works perectly with Arduino Uno
I have a Elechouse PN532 module (bought here - https://robu.in/product/pn532-nfc-rfid-read-write-module-v3-kit/). When I try to use to it with I2C and connect it to my ESP32 (DOIT ESP32 DEV KIT V1, 30 pin version), the PN532 gets detected but it doesn't detect when a card or token shown to it. When I try the exact same code with Arduino Uno with I2C, it works flawlessly. Below are the connections for both boards, the code, the output and actual connection picture (since some said wire position matters for PN532).

**Connections**

* ESP32

| ESP32 | PN532 |
| --- | --- |
| GPIO 22 | SCL |
| GPIO 21 | SDA |
| 3.3V | VCC |
| GND | GND |

* Arduino Uno

| Uno | PN532 |
| --- | --- |
| A5 | SCL |
| A4 | SDA |
| 3.3V | VCC |
| GND | GND |

**The code**

```
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

PN532_I2C pn532i2c(Wire);
PN532 nfc(pn532i2c);

void setup(void) {
  Serial.begin(115200);
  //Wire.begin(21, 22);        //used this line only when connected with ESP32
  Serial.println("Hello!");

  pn532i2c.wakeup();    //delays 500ms
  nfc.begin();

  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }

  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);

  // Set the max number of retry attempts to read from a card
  // This prevents us from waiting forever for a card, which is
  // the default behaviour of the PN532.
  nfc.setPassiveActivationRetries(0xFF);

  // configure board to read RFID tags
  nfc.SAMConfig();

  Serial.println("Waiting for an ISO14443A card");
}

void loop(void) {
  boolean success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)

  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);

  if (success) {
    Serial.println("Found a card!");
    Serial.print("UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("UID Value: ");
    for (uint8_t i=0; i < uidLength; i++)
    {
      Serial.print(" 0x");Serial.print(uid[i], HEX);
    }
    Serial.println("");
    // Wait 1 second before continuing
    delay(1000);
  }
  else
  {
    // PN532 probably timed out waiting for a card
    Serial.println("Timed out waiting for a card");
  }
}

```

**Output**

* For Arduino Uno
* For ESP32

**Connection Placements**

* For Arduino Uno
* For ESP32

Also, the configuration of ESP32 in Arduino IDE

# Answer
To use PN532, UART or SPI seems to be a good choice. Also, the little red board needs a strong power supply, and the power supply capacity from the ESP32 DEV KIT will be insufficient; I recommend adding a capacitor of about 47uF on the PN532.
> 1 votes

---
Tags: arduino-uno, i2c, esp32, rfid, espressif
---


# Question
Title: How to get 2 loop functions to cooperate?
I have a OLED SSD1306 & DS3231 RTC, 2 buttons to set the time & date. My project is to display a scrolling text at the top of the OLED, the RTC time in the middle, the day & date on the last line. My issue is I can't get the scrolling text & the time to run right when in the loop together, individually they work normal. When they are together, the scrolling text is fine, but the time is static, its not displaying the current RTC. Then after 1 loop cycle the time seconds text become jumbled, then after a 2nd cycle the minutes & seconds become jumbled. I have tried putting display.clearDisplay(); display.display(); at the end of the loop, doing this fixes the time from becoming jumbled by clearing the buffer before the next cycle, but does not fix the time from being static. How can I get the time to not be static anymore? Any help would be greatly appreciated. Here is my sketch:

```
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define button1    9                       // Button B1 is connected to Arduino pin 9
#define button2    8                       // Button B2 is connected to Arduino pin 8

void setup(void) {
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  delay(1000);

  // by default, the high voltage from the 3.3v line
  display.begin(SSD1306_SWITCHCAPVCC, 0x3c);  // initialize with the I2C address
  // init done

  // Clear the display buffer.
  display.clearDisplay();
  display.display();

  display.setTextColor(WHITE, BLACK);
}

char Time[]     = "  :  :  ";
char Calendar[] = "  /  /20  ";
byte i, second, minute, hour, day, month, date, year;

void display_day(){
  switch(day){
    case 1:  draw_text(0, 50, " SUNDAY  ", 1); break; //(Column,Row,Data to be displayed,Font size)
    case 2:  draw_text(0, 50, " MONDAY  ", 1); break; //(Column,Row,Data to be displayed,Font size)
    case 3:  draw_text(0, 50, " TUESDAY ", 1); break; //(Column,Row,Data to be displayed,Font size)
    case 4:  draw_text(0, 50, "WEDNESDAY", 1); break; //(Column,Row,Data to be displayed,Font size)
    case 5:  draw_text(0, 50, "THURSDAY ", 1); break; //(Column,Row,Data to be displayed,Font size)
    case 6:  draw_text(0, 50, " FRIDAY  ", 1); break; //(Column,Row,Data to be displayed,Font size)
    default: draw_text(0, 50, "SATURDAY ", 1); //(Column,Row,Data to be displayed,Font size)
  }
}

void DS3231_display(){
  // Convert BCD to decimal
  second = (second >> 4) * 10 + (second & 0x0F);
  minute = (minute >> 4) * 10 + (minute & 0x0F);
  hour   = (hour >> 4)   * 10 + (hour & 0x0F);
  month  = (month >> 4)  * 10 + (month & 0x0F);
  date   = (date >> 4)   * 10 + (date & 0x0F);
  year   = (year >> 4)   * 10 + (year & 0x0F);
  // End conversion

  Time[7]     = second % 10 + 48;
  Time[6]     = second / 10 + 48;
  Time[4]     = minute % 10 + 48;
  Time[3]     = minute / 10 + 48;
  Time[1]     = hour   % 10 + 48;
  Time[0]     = hour   / 10 + 48;
  Calendar[9] = year   % 10 + 48;
  Calendar[8] = year   / 10 + 48;
  Calendar[4] = date   % 10 + 48;
  Calendar[3] = date   / 10 + 48;
  Calendar[1] = month  % 10 + 48;
  Calendar[0] = month  / 10 + 48;

//Print text
  draw_text(60, 50, Calendar, 1); // Display the date (format: mm/dd/yyyy)
  draw_text(15, 25, Time, 2); // Display the time
}

void blink_parameter(){
  byte j = 0;
  while(j < 10 && digitalRead(button1) && digitalRead(button2)){
    j++;
    delay(25);
  }
}

byte edit(byte x_pos, byte y_pos, byte parameter){
  char text[3];
  sprintf(text,"%02u", parameter);
  while(!digitalRead(button1));                      // Wait until button B1 released
  while(true){
    while(!digitalRead(button2)){                    // If button B2 is pressed
      parameter++;
      if(i == 0 && parameter > 12)                   // If month > 12 ==> month = 1
        parameter = 1;
      if(i == 1 && parameter > 31)                   // If date > 31 ==> date = 1
        parameter = 1;
      if(i == 2 && parameter > 99)                   // If year > 99 ==> year = 0
        parameter = 0;
      if(i == 3 && parameter > 23)                   // If hours > 23 ==> hours = 0
        parameter = 0;
      if(i == 4 && parameter > 59)                   // If minutes > 59 ==> minutes = 0
        parameter = 0;
      sprintf(text,"%02u", parameter);
      draw_text(x_pos, y_pos, text, 1);
      delay(200);                                    // Wait 200ms
    }
    draw_text(x_pos, y_pos, "  ", 1);
    blink_parameter();
    draw_text(x_pos, y_pos, text, 1);
    blink_parameter();
    if(!digitalRead(button1)){                       // If button B1 is pressed
      i++;                                           // Increment 'i' for the next parameter
      return parameter;                              // Return parameter value and exit
    }
  }
}

void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

void scroll_text(){
  draw_text(0, 0, "The Pumpkin Express", 1);
  display.display();
  display.startscrollright(0x00, 0x00);
  delay(8500);
  display.stopscroll();
  delay(4000);
  }

void loop() {

  if(!digitalRead(button1)){                         // If button B1 is pressed
    i = 0;
    while(!digitalRead(button1));                    // Wait for button B1 release
    while(true){
      while(!digitalRead(button2)){                  // While button B2 pressed
        day++;                                       // Increment day
        if(day > 7) day = 1;
        display_day();                               // Call display_day function
        delay(200);                                  // Wait 200 ms
      }
      draw_text(0, 50, "         ", 1);
      blink_parameter();                             // Call blink_parameter function
      display_day();                                 // Call display_day function
      blink_parameter();                             // Call blink_parameter function
      if(!digitalRead(button1))                      // If button B1 is pressed
        break;
    }
    //set position of text when editing on button press
    month  = edit(60, 50, month);                    // Edit month
    date   = edit(80, 50, date);                      // Edit date
    year   = edit(110,50, year);                    // Edit year
    hour   = edit(14, 25, hour);                     // Edit hours
    minute = edit(50, 25, minute);                   // Edit minutes

    // Convert decimal to BCD
    minute = ((minute / 10) << 4) + (minute % 10);
    hour = ((hour / 10)  << 4) + (hour % 10);
    date = ((date / 10) <<  4) + (date % 10);
    month = ((month / 10)  << 4) + (month % 10);
    year = ((year / 10)  << 4) + (year % 10);
    // End conversion

    // Write data to DS3231 RTC
    Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address
    Wire.write(0);                              // Send register address
    Wire.write(0);                              // Reset seconds and start oscillator
    Wire.write(minute);                         // Write minute
    Wire.write(hour);                           // Write hour
    Wire.write(day);                            // Write day
    Wire.write(month);                          // Write month
    Wire.write(date);                           // Write date
    Wire.write(year);                           // Write year
    Wire.endTransmission();                     // Stop transmission and release the I2C bus
    delay(200);                                 // Wait 200ms
  }

  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0);                                // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading
  second = Wire.read();                         // Read seconds from register 0
  minute = Wire.read();                         // Read minutes from register 1
  hour   = Wire.read();                         // Read hour from register 2
  day    = Wire.read();                         // Read day from register 3
  month  = Wire.read();                         // Read month from register 4
  date   = Wire.read();                         // Read date from register 5
  year   = Wire.read();                         // Read year from register 6
  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0x11);                             // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 2);                    // Request 2 bytes from DS3231 and release I2C bus at end of reading

  DS3231_display();                             // Display time & calendar
  display_day();                                // Display date

  scroll_text();                                // Display scrolling text
              // If i dont use the clear buffers(next 2 line codes), on the
             //next loop cycle the seconds & minute text becomes jumbled
  //display.clearDisplay();
  //display.display();

  delay(50);                                    // Wait 50ms
}

```

# Answer
> 1 votes
The answer to your title question, "How to get 2 loop functions to cooperate?" is: You can't, because your program can't have two functions with the same name. What you'd need to do instead is redesign your program, keeping in mind the MCU can only *do one thing at a time*, although you could break up each of several jobs into pieces and interleave them fast enough that we slow humans won't notice.

My approach, when I have a question like this, is to temporarily put aside what I know about coding and about MCUs, and just focus on how to do the job. I list the sub-tasks my code needs to do but without thinking too much about *how* to do them. Write them down, in the order they required doing, in any note-taking style that suits you.

Now break down each one of those sub-tasks into *its* sub-tasks. Repeat, until you understand how to code each one. Then you'll know enough to start writing the code.

Update:

@NathanJiang is correct. The solution is not to make two loop() functions (because the language doesn't support that), but to decide how to interleave pieces of each job within 1 function, in such a way that they each appear to operate smoothly and don't interfere with each other. Especially, neither one must call delay(), which *stops your code doing anything* for the duration. If some piece isn't ready to be done yet, your code must move on to other pieces and do which ever of those *is* ready. This keeps it checking each piece over and over again, rapidly, doing what is ready and skipping what is not.

# Answer
> 0 votes
The way to get functions to cooperate with each other is to re-code them so they don't waste time and pass control back and forth as quickly as possible. You do this by using the BlinkWithoutDelay trick to re-write the "blocking" code to be non-blocking and trust in `loop()` to hand back control to your function in a reasonable amount of time.

For instance take this function that @jsotola identified as a performance killer:

```
void scroll_text(){
  draw_text(0, 0, "The Pumpkin Express", 1);
  display.display();
  display.startscrollright(0x00, 0x00);
  delay(8500);
  display.stopscroll();
  delay(4000);
  }

```

It really doesn't need to monopolize the processor for 12500 microseconds--Instead it could just check the time and turn scrolling on and off every so often, and quickly pass control back to the `loop()` for reading and updating the clock.

I don't have your hardware or setup, so here's some untested code:

```
void scroll_text(){
  // some local state variables to remember where we are
  static bool isInitialized = false; // maybe a global if re-initializing is needed.
  static bool isScrolling = false;
  static unsigned long interval = 1;
  static unsigned long last = -interval;
  unsigned long now = millis();
  if (now - last >= interval ) { // time to do something
    last = now;
    if( !isInitialized ){
      draw_text(0, 0, "The Pumpkin Express", 1);
      display.display();
      isIinitialized = true;
    }
    if ( !isScrolling ) {
        isScrolling = true;
        display.startscrollright(0x00, 0x00);
        // delay(8500);  // use BWOD trick instead
        interval = 8500;
     } else { // isScrolling
       isScrolling = false;
       display.stopscroll();
       //delay(4000);
       interval = 4000;
     }
  }

```

This drop-in `scroll_text()` function can be called many time times per millisecond and will mostly do nothing and return control immediately. But when it realizes the time is right, it will update its own state variables and the output states.

By replacing the `scroll_text()` function with a non-blocking form, it speeds up `loop()` by 12.5 seconds per loop. Doing similar replacement of processor-sapping `delay()`s could further improve responsiveness. However it is a big mind shift to stop using serial, blocking code and shift to events. Every time you see a `delay()`, a `while(...)`, or a `for()` loop, think about whether you really need to trap the processor inside of that loop, or what data you would need in order to skip it for now and come back to it next time through the main event `loop()`.

I think the next step would be to wrap the reading of the reading the the DS3231 with the BWOD trick -- you only need to read the clock once per 1000ms and you could save hundreds of instructions per `loop()`.

---
Tags: code-review
---


# Question
Title: Reading & writing a configuration file on an Adafruit Circuit Playground Express
I would like to store an application's configuration in a file stored on the Circuit Playground Express (CPX) flash. The application itself needs to be able to update the configuration file. Things I need to store are basic, for example:

* NeoPixel brightness (eg. brightness = 0.9)
* NeoPixels on/off (eg. NP\_enable = \[0,0,1,0,1,0,1,1,1,1\]

ArduinoJason seems appropriate, but I cannot even get to the point of writing files to the CPX. The TinyUSB libraries are supposed to give the ability to write to the CPX SPI Flash, but I cannot get any of the examples included with this library to compile. I am trying to compile the msc\_external\_flash example provided with the TinyUSB library. I get the following 2 errors:

```
In file included from /home/pi/Arduino/libraries/Adafruit_TinyUSB_Library/examples/MassStorage/msc_external_flash/msc_external_flash.ino:28:0:
/home/pi/Arduino/libraries/Adafruit_TinyUSB_Library/src/Adafruit_TinyUSB.h:31:2: error: #error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
#error TinyUSB is not selected, please select it in "Tools->Menu->USB Stack"
^~~~~
msc_external_flash:65:6: error: #error No QSPI/SPI flash are defined on your board variant.h !
#error No QSPI/SPI flash are defined on your board variant.h !
^~~~~

```

The board selected is SAMD--\>Circuit Playground Express. There is no Tools menu item for selecting the USB stack.

Regarding the second error, From msc\_external\_flash.ino:

```
  #if defined(EXTERNAL_FLASH_USE_QSPI)
    Adafruit_FlashTransport_QSPI flashTransport;
  #elif defined(EXTERNAL_FLASH_USE_SPI)
    Adafruit_FlashTransport_SPI flashTransport(EXTERNAL_FLASH_USE_CS, EXTERNAL_FLASH_USE_SPI);
  #else
    #error No QSPI/SPI flash are defined on your board variant.h !
  #endif

```

of the files named variant.h, this looks like the best candidate: /home/pi/.arduino15/packages/arduino/hardware/samd/1.8.12/variants/circuitplay/variant.h

but the file does not contain the string "EXTERNAL\_FLASH", nor anything I see that is CPX specific.

Arduino version is 1.8.19, which I am running on a Raspberry Pi 3 B+ running Buster.

Thanks, Scott

# Answer
> 3 votes
The problem was using the Arduino SAMD board core instead of the Adafruit SAMD board core. The Adafruit SAMD board core is not visible unless you add: https://adafruit.github.io/arduino-board-index/package\_adafruit\_index.json

to the "Additional Boards Manager URLs:" field of the Arduino IDE preferences panel.

Once you do that... Then install the "Adafruit SAMD Boards" from the Arduino IDE Boards Manager. Then select the menu item: Tools --\> Board: --\> Adafruit SAMD (32-bits ARM Cortext-M0+ and Cortext-M4) boards --\> Adafruit Circuit Playground Express (SAMD21)

I have not seen this procedure in any Adafruit documentation.

---
Tags: adafruit, flash, json
---


title: Can you write c code in arduino ide?

text:
# Question
Title: Can you write c code in arduino ide?
So i know that the native arduino language is written in c/c++, but does that mean that i can write pure c code in the arduino ide, or that i have to use the arduino specified language? I’m new to this and very confused, please bear with me here :’)

# Answer
> 2 votes
Yes, you can write in pure C. Some parts of the Arduino core API are actually defined in C, e.g. `pinMode()` and `digitalWrite()` (at least in the AVR core). So you can use them. Other parts, like `Serial`, are C++ objects, and you will not be able to use them from plain C.

The Arduino IDE, however, will insist on you writing a file with the .ino extension, that it will compile as preprocessed C++. You do not need to put anything in that file though. If you want to write your whole program in pure C, you can create an empty .ino file, and in the same folder a .c file with your whole program. In that file you can define your own `main()`. If you want to use the Arduino core API though, you should instead define `setup()` and `loop()`, and rely on the core-provided `main()`.

---
Tags: arduino-ide, arduino-nano
---


title: What size diode should I use?

text:
# Question
Title: What size diode should I use?
I'm building a project with an ESP8266 which requires multiple analog inputs - but the ESP8266 only has one. I know of ways to multiplex with dedicated modules, but since I have lots of diodes lying around I've decided to multiplex with them. I've found lots of tutorials on how to multiplex (e.g. this one) but none of them say what size diode to use. So which size shall I use? Does it even matter? I have `1N4148`s, `1N4007`s, `1N5819`s, `1N5399`s, `1N5408`s, `1N5822`s, `FR107`s and `FR207`s.

# Answer
By the time you finish mucking around powering different devices from I/O pins (which have a limit to how much current they can source) and then install different diodes for each one, you are probably better off (and more simply) to use a multiplexer like the 74HC4051 which I describe here.

As Gil mentioned in his reply, the 0.7V drop (or thereabouts) that the diodes will incur are going to affect the accuracy of the readings, plus you have the issue that the devices might take a few milliseconds to stablise if you keep turning them on and off.

To answer your question, though, any signal diode should do the trick as there will be very little current drawn, as the analog input is high impedance. For example the 1N4148.

You can connect 8 devices to the 74HC4051 with only 4 connections between it and the microprocessor. Three "selector" pins which therefore give you 8 possible combinations, and the signal pin which would go to your analog input.

You could even get a 74HC4067 and have 16 inputs, for the cost of only one more selector pin.
> 2 votes

# Answer
I do not think it is possible to truly multiplex analog signals with simply using diodes in an 'or' configuration. Your demo shows powering only one sensor at a time and isolating the sensors (pots) output with the diode "or". This demo works as long as only one sensor is powered and or the rest output voltage is below the one you are measuring. You also have a voltage drop across the diode and nothing to keep the signal stable, it will bounce around by the forward voltage of the diode or more. The diode will add about a 10% error and reduce your measurement range. To stabilize it you need to add some resistance between the analog input of the microprocessor and ground (load sensor output). This will introduce some error in your reading but you can compensate for that. Any diode will work, use one that you're comfortable with or you can check their characteristics and make a choice.
> 1 votes

---
Tags: esp8266, multiplexer
---


# Question
Title: How do I send a string from an Arduino Slave using SPI?
I have an Arduino Uno acting as a master with 3 Arduino Nano's acting as a slaves.

Looking at this example: http://www.gammon.com.au/forum/?id=10892, it tells me how to send a string from the master to the slave, but I didn't see any examples sending a string from the slave to the master device. I was able to successfully send and receive digits to/from the master and slave, but I couldn't figure out how to send strings from the slave to the master based on the example.

My understanding is that SPI communications can only send information byte by byte, so am I supposed to convert my string into a byte format before putting that into the SPDR variable so that it can be sent back to the master?

In any case, would I be able to get some pointers on how to send strings from the slave to the master?

Thanks in advance.

# Answer
Remember the master controls the transmission (provides the clock), however it *can* be done. For example:

---

## Master

```
// master

#include <SPI.h>

void setup (void)
{
  Serial.begin (115200);
  Serial.println ("Starting");

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // end of setup

void loop (void)
{
  char buf [20];

  // enable Slave Select
  digitalWrite(SS, LOW);
  SPI.transfer (1);   // initiate transmission
  for (int pos = 0; pos < sizeof (buf) - 1; pos++)
    {
    delayMicroseconds (15);
    buf [pos] = SPI.transfer (0);
    if (buf [pos] == 0)
      {
      break;
      }
    }

  buf [sizeof (buf) - 1] = 0;  // ensure terminating null

  // disable Slave Select
  digitalWrite(SS, HIGH);

  Serial.print ("We received: ");
  Serial.println (buf);

  delay (1000);  // 1 second delay
}  // end of loop

```

In this example the master initiates a transmission by sending 0x01 to the slave. Then it gets bytes back until a 0x00 byte (signifying the end of the string). The `delayMicroseconds` is there to give the slave time to respond.

---

## Slave

```
// Slave

void setup (void)
{

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= bit(SPE);

  // turn on interrupts
  SPCR |= bit(SPIE);
}  // end of setup

volatile char buf [20] = "Hello, world!";
volatile int pos;
volatile bool active;

// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;

  if (c == 1)  // starting new sequence?
    {
    active = true;
    pos = 0;
    SPDR = buf [pos++];   // send first byte
    return;
    }

  if (!active)
    {
    SPDR = 0;
    return;
    }

  SPDR = buf [pos];
  if (buf [pos] == 0 || ++pos >= sizeof (buf))
    active = false;
}  // end of interrupt service routine (ISR) SPI_STC_vect

void loop (void)
{

}  // end of loop

```

The slave does everything inside the ISR. The arrival of the 0x01 byte makes it reset its "pointer" to the start of the buffer. After that it responds with another byte from the buffer until it has reached the terminating 0x00 byte.
> 3 votes

# Answer
In part of sender I'm use the convert String to char array method before sending to the receiver.

**Master**

```
#include <SPI.h>
const int size_arr = 50;  // define array size (must be less than size of slave)
char buf[size_arr]; // define char array, use for convert from string for send to slave
String main_dat = "jack,12,47,123,8888"; // real String data

void setup() {

pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);

}
void loop() {
main_dat.toCharArray(buf, size_arr); // convert String data to char array
Spi_tranmis(buf); // send char array
delay(500);

}

void send_spi(byte pram) {

  digitalWrite(SS, LOW);
  SPI.transfer(pram);
  digitalWrite(SS, HIGH);
  delayMicroseconds(50);

}

void Spi_tranmis(char buf[]) {
for (int i = 0 ; i < size_arr ; i ++) {
  send_spi(buf[i]);
}

send_spi('\n');
}

```

And in part of receiver i'm use char array receive from master and convert to String leter.

**Slave**

```
#include <SPI.h>

const int size_arr = 51; // define array size (must be more than size of master)
char buf[size_arr]; // char array , use for recive from master

volatile byte pos = 0;
volatile boolean process = false;

String msg; // real data

void setup() {
   Serial.begin(9600);
   Serial.println("test");
   pinMode(MISO, OUTPUT);
   digitalWrite(MISO, LOW);
   SPCR |= _BV(SPE);
   SPCR |= _BV(SPIE);

 }

 ISR(SPI_STC_vect) {
  char c = SPDR;

  if (pos < sizeof buf) {
    if (c == '\n') {
      process = true;
    }
     else {
      buf[pos++] = c;
     }
   }
 }

void loop() {
  recvHandle();

}

void recvHandle() {
  if (process) {  // when SPI available
    msg = String(buf);   // convert char array to String
    Serial.println(msg);
    process = false;
    pos = 0;
  }

```

}

* You must define size of char array in receiver more than sender *
> 1 votes

# Answer
String is only array of char ended by char \0. But you can also access it as array of bytes ended with 0. And send them by one byte until it reaches the 0 (send it too). On master you save it to long enough array of char (work with it as with bytes) including the final zero and bingo, you have char string transmitted :)
> 0 votes

# Answer
> How do I send a string from the an Arduino Slave using SPI?

Depending on your definition of string it would look something like this (for master):

```
String message = "....";
SPI.transfer(message.c_str(), message.length() + 1);

```

or

```
char message[MESSAGE_MAX];
strcpy(message, ....);
SPI.transfer(message, strlen(message) + 1);

```

For the SPI slave this will need to be transformed to either an SPI ISR or busy-wait for chip-select and then the transfer.

Cheers!
> 0 votes

---
Tags: arduino-uno, spi, string
---


# Question
Title: How to expand this code for more than four 74hc165 shift registers? It works well with maximum four 74hc165 shift registers at a time
```
#define NUMBER_OF_SHIFT_CHIPS   4
#define DATA_WIDTH   NUMBER_OF_SHIFT_CHIPS * 8

int LoadPin    = 9;
int EnablePin  = 8;
int DataPin    = 11;
int ClockPin   = 12;

unsigned long pinValues;
unsigned long oldPinValues;

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

  pinMode(LoadPin, OUTPUT);
  pinMode(EnablePin, OUTPUT);
  pinMode(ClockPin, OUTPUT);
  pinMode(DataPin, INPUT);

  digitalWrite(ClockPin, LOW);
  digitalWrite(LoadPin, HIGH);

  pinValues = read_shift_regs();
  print_byte();
  oldPinValues = pinValues;
}

void loop()
{
  pinValues = read_shift_regs();
  if (pinValues != oldPinValues)
  {
    print_byte();
    oldPinValues = pinValues;
  }
}

unsigned long read_shift_regs()
{
  long bitVal;
  unsigned long bytesVal = 0;

  digitalWrite(EnablePin, HIGH);
  digitalWrite(LoadPin, LOW);
  delayMicroseconds(5);
  digitalWrite(LoadPin, HIGH);
  digitalWrite(EnablePin, LOW);

  for (int i = 0; i < DATA_WIDTH; i++)
  {
    bitVal = digitalRead(DataPin);
    bytesVal |= (bitVal << ((DATA_WIDTH - 1) - i));

    digitalWrite(ClockPin, HIGH);
    delayMicroseconds(5);
    digitalWrite(ClockPin, LOW);
  }

  return (bytesVal);
}

void print_byte() {
  byte i;
  Serial.println("*Shift Register Values:*\r\n");

  for (byte i = 0; i <= DATA_WIDTH - 1; i++)
  {
    Serial.print(pinValues >> i & 1, BIN);

    Serial.print("  ");

  }
  Serial.print("\n");
  Serial.println(); Serial.println();
}

```

# Answer
As StarCat mentioned in the comments, you return the read value as an `unsigned long`, which can hold exactly 4 bytes. When trying to write more into it with your current code you will loose the previous data. So you need a data structure that is able to hold all the data that you want to read.

I suggest that you do it like the `shiftIn()` function of the Arduino framework: Use a `DATA_WIDTH` of 8 bits (1 byte) and enclose the reading loop into another for loop, where you iterate over `NUMBER_OF_SHIFT_CHIPS`, getting exactly one byte from each chip and putting it into an array of `byte` (aka `uint8_t`). There are multiple ways to do this, but I will describe only one, not necessarily the best one for your situation.

First declare an array of `byte` on global scope. It needs to be `NUMBER_OF_SHIFT_CHIPS` bytes big. We initialize the data to zero:

```
byte shift_data[NUMBER_OF_SHIFT_CHIPS] = {0};

```

Set `DATA_WIDTH` to 8 bits:

```
#define DATA_WIDTH   8

```

Now look into `read_shift_regs()`. Enclose the for loop into another for loop iterating over `NUMBER_OF_SHIFT_CHIPS` and use that index to write the data into the corresponding byte in `shift_data` (by using `shift_data[j]` with the corresponding index `j`). As we write a global array we don't need to return anything, so you can make the function `void` (unless you want to return some other information).

```
void read_shift_regs()
{
  long bitVal;

  digitalWrite(EnablePin, HIGH);
  digitalWrite(LoadPin, LOW);
  delayMicroseconds(5);
  digitalWrite(LoadPin, HIGH);
  digitalWrite(EnablePin, LOW);
  for(int j = 0; j < NUMBER_OF_SHIFT_CHIPS; j++){
    for (int i = 0; i < DATA_WIDTH; i++)
    {
      bitVal = digitalRead(DataPin);
      shift_data[j] |= (bitVal << ((DATA_WIDTH - 1) - i));

      digitalWrite(ClockPin, HIGH);
      delayMicroseconds(5);
      digitalWrite(ClockPin, LOW);
    }
  }
}

```

Then change all lines with

```
pinValues = read_shift_regs();

```

to read\_shift\_regs();

And finally - to actually use the read values - you now need to access a complete array instead of a single variable. I will leave that to you. Basically its again just iterating over all elements of the array.

Note:

* I have not tested the above code in any way. Its more about explaining the principle.
* One can also handle the array with parameters, but if you don't know how to use arrays as parameters, then this can give you a lot of other errors. So I didn't suggest that.
> 3 votes

---
Tags: arduino-uno
---


title: printf %s gives gibberish

text:
# Question
Title: printf %s gives gibberish
This Code:

```
String S0 = "";
String S1 = "1";
String S2 = "12";
String S3 = "123";
String S4 = "1234";
String S5 = "12345";
String S6 = "123456";
String S7 = "1234567";
String S8 = "12345678";
String S9 = "123456789";
String S10 = "1234567890";
String S11 = "1234567890a";
String S12 = "1234567890ab";
String S13 = "1234567890abc";
String S14 = "1234567890abcd";
String S15 = "1234567890abcde";
String S16 = "1234567890abcdef";
String S17 = "1234567890abcdefg";
String S18 = "1234567890abcdefgh";
String S19 = "1234567890abcdefghi";
String S20 = "1234567890abcdefghij";
Serial.printf("(0):%s\n", S0);
Serial.printf("(1):%s\n", S1);
Serial.printf("(2):%s\n", S2);
Serial.printf("(3):%s\n", S3);
Serial.printf("(4):%s\n", S4);
Serial.printf("(5):%s\n", S5);
Serial.printf("(6):%s\n", S6);
Serial.printf("(7):%s\n", S7);
Serial.printf("(8):%s\n", S8);
Serial.printf("(9):%s\n", S9);
Serial.printf("(10):%s\n", S10);
Serial.printf("(11):%s\n", S11);
Serial.printf("(12):%s\n", S12);
Serial.printf("(13):%s\n", S13);
Serial.printf("(14):%s\n", S14);
Serial.printf("(15):%s\n", S15);
Serial.printf("(16):%s\n", S16);
Serial.printf("(17):%s\n", S17);
Serial.printf("(18):%s\n", S18);
Serial.printf("(19):%s\n", S19);
Serial.printf("(20):%s\n", S20);

```

Gives This Result:

```
(0):
(1):1
(2):12
(3):123
(4):1234
(5):12345
(6):123456
(7):1234567
(8):12345678
(9):123456789
(10):�H�?
(11):�^�?
(12):_�?
(13):�_�?
(14):`�?
(15):0`�?
(16):�`�?
(17):a�?
(18):@a�?
(19):pa�?
(20):�a�?

```

Any ideas?? PS: IT IS OBVIOUS that for whatever platform it is being used, it is working for short strings and not for longer strings! And it has been answered in the comments after you have closed it! So if you do not know the answer instead of closing, maybe it is better to leave it for others to answer it...

# Answer
> 4 votes
(Community Wiki answer assembled from the comments)

Noting that the standard Arduino core doesn't have a `Serial.printf()` function. The ESP32 core does.

You need `.c_str()` in your calls. `.printf()` is a variadic function which doesn't really have access to any sort of destination type to do conversions; it relies entirely on your passing the correct format specifiers. It is just supplying the bytes to the `String` object, which is not simply a `const char *` (specified `%s`). If you're curious, the behaviour difference you're seeing is down to whether "small string optimization" is being used.

Short string optimization is where shorter strings are stored directly in the object and for longer strings it's used as pointers.

The suggested solution is to use: `Serial.printf("%s",Sxx.c_str());`

---
Tags: printf
---


# Question
Title: Code got stuck after initialization with RFM69
I'm working on RFM69 connected to an Arduino Uno. Currently, I was able to initialize the RFM69 using the a code I modified from the internet. However, my Receiver part always encounters error. It doesn't sometimes proceed and sometimes got stuck in the initialization loop. Yesterday, my Transmitter managed to work properly but today, sometimes I also observed same problem with my Receiver.

Here's my wiring.

The code I'm using for both Transmitter and Receiver

```
#include <SPI.h>
#include <RH_RF69.h>

/************ Radio Setup ***************/

// Change to 434.0 or other frequency, must match RX's freq!
#define RF69_FREQ 434.0

#define RFM69_CS 10
#define RFM69_INT 2
#define RFM69_RST 9
#define LED 13

// Singleton instance of the radio driver
RH_RF69 rf69(RFM69_CS, RFM69_INT);

int16_t packetnum = 0;  // packet counter, we increment per xmission

void setup()
{
  Serial.begin(9600);
  //while (!Serial) { delay(1); } // wait until serial console is open, remove if not tethered to computer

  pinMode(LED, OUTPUT);
  pinMode(RFM69_RST, OUTPUT);
  //digitalWrite(RFM69_RST, LOW);
  //from this point I added it
  digitalWrite (RFM69_RST, HIGH);
  delay (100);
  digitalWrite (RFM69_RST, LOW);
  delay (100);

  Serial.println("LoRa Daughter Board (RFM69) - Transmitter");
  Serial.println();

  // manual reset
  digitalWrite(RFM69_RST, HIGH);
  delay(10);
  digitalWrite(RFM69_RST, LOW);
  delay(10);

  if (!rf69.init()) {
    Serial.println("RFM69 Initialization Failed!");
    while (1);
  }
  Serial.println("RFM69 Initialization Success!");
  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM (for low power module)
  // No encryption
  if (!rf69.setFrequency(RF69_FREQ)) {
    Serial.println("setFrequency failed");
  }

  // If you are using a high power RF69 eg RFM69HW, you *must* set a Tx power with the
  // ishighpowermodule flag set like this:
  //rf69.setTxPower(20, true);  // range from 14-20 for power, 2nd arg must be true for 69HCW

  // The encryption key has to be the same as the one in the server
  uint8_t key[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
  rf69.setEncryptionKey(key);

  pinMode(LED, OUTPUT);

  Serial.print("RFM69 Frequency: ");  Serial.print((int)RF69_FREQ);  Serial.println(" MHz");
}

void loop() {
  delay(1000);  // Wait 1 second between transmits, could also 'sleep' here!

  char radiopacket[20] = "Hello World #";
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);

  // Send a message!
  rf69.send((uint8_t *)radiopacket, strlen(radiopacket));
  rf69.waitPacketSent();

  // Now wait for a reply
  uint8_t buf[RH_RF69_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf69.waitAvailableTimeout(500))  {
    // Should be a reply message for us now
    if (rf69.recv(buf, &len)) {
      Serial.print("Got a reply: ");
      Serial.println((char*)buf);
      Blink(LED, 50, 3); //blink LED 3 times, 50ms between blinks
    } else {
      Serial.println("Receive failed");
    }
  } else {
    Serial.println("No reply, is another RFM69 listening?");
  }
}

void Blink(byte PIN, byte DELAY_MS, byte loops) {
  for (byte i=0; i<loops; i++)  {
    digitalWrite(PIN,HIGH);
    delay(DELAY_MS);
    digitalWrite(PIN,LOW);
    delay(DELAY_MS);
  }
}

```

Here are screenshots of the results Taken yesterday: Mar 16

Taken today: Mar 17

# Answer
It may be your environment, I have lots of problems here with RF transmission interference, a nearby radio amateur and proliferation of WiFi seem to exacerbate the problem. I've had some success building an RFM69 relay but have mostly gone over to WiFi using ESP8266 modules as they're much more reliable for communication.
> -1 votes

---
Tags: arduino-uno, lora
---


# Question
Title: Toggle button switches through case statements with button debouncing
The overview of my code is that I want a toggle button to be pushed and each button push will move the code to the next case statement. In each case statement, there will be different LED functions. I need help with a few things

1. I need help with blinking 4 of the LEDs continuously with 100ms pause in case 1. Because it is not in the main loop, I am having trouble getting the 4 LEDs to switch on and off. Normally, I could just have a simple code that turns it on, then compares previous to last and if different, turns it off, and this continues.
2. I need the code to go back to case 0 once the button has been held for 2 seconds.
3. I cannot get my button debounce code to work from case 0 to case 1. If I add the debounce code in case 0 how I have it in the rest of the cases, it wont run through the rest of the cases. Below is the code:

```

//LED variables for left turn signal OUT
int LED_1 = 2;
int LED_2 = 3;
int LED_3 = 4;
int LED_4 = 5;

//LED variables for right turn signal OUT
int LED_5 = 6;
int LED_6 = 7;
int LED_7 = 8;
int LED_8 = 9;

//break signal OUT
int BS_OUT = A5;

//reverse signal OUT
int RS_OUT = 10;

//toggle switch button between different modes
int toggle_IN = A4;

//switch case statement variable for togglemodes
int toggleState = 0;

//variables to see if the toggle button has been pressed or not
boolean oldSwitchStateToggle = LOW;
boolean newSwitchStateToggle = LOW;

//true or false to save whether button has been pressed for switching case statements
bool enabledToggle;

//debounce time to take care of button bouncing
const int debounce = 100; //ms

//time for holding a current time of millis()
unsigned long t = 0;

void setup()
{
  Serial.begin(9600);
  //toggle button input
  pinMode(toggle_IN, INPUT);

  //led outputs
  pinMode(LED_4, OUTPUT);
  pinMode(LED_3, OUTPUT);
  pinMode(LED_2, OUTPUT);
  pinMode(LED_1, OUTPUT);
  pinMode(LED_5, OUTPUT);
  pinMode(LED_6, OUTPUT);
  pinMode(LED_7, OUTPUT);
  pinMode(LED_8, OUTPUT);

}

void loop()
{
   //checking to see if toggle button has been pushed
   newSwitchStateToggle = digitalRead(toggle_IN);
   if(newSwitchStateToggle != oldSwitchStateToggle)
  {
    if(newSwitchStateToggle == HIGH)
    {
      //enabling toggle for if statements
      enabledToggle = true;
      //case switch for flow through 4 different LED output options
      toggleButtonState();

    }
    else
    enabledToggle = false;
    oldSwitchStateToggle = newSwitchStateToggle;
  }
}

void toggleButtonState()
{
  unsigned long nowToggle = millis();
  switch (toggleState)
  {

    case 0:
    Serial.println("0000");
          if(enabledToggle)
          {
            digitalWrite(LED_1, HIGH);
            t = nowToggle;
            toggleState = 1;
          }

          break;

    case 1:
    Serial.println("1111");
          if(enabledToggle)
          {
            digitalWrite(LED_1, LOW);
            digitalWrite(LED_2, HIGH);
            //alows going to next state after 100ms for button debounce
            if(nowToggle - t > debounce)
            {
              toggleState = 2;
              t = nowToggle;
            }
          }

          break;

     case 2:
     Serial.println("2222");
          if(enabledToggle)
          {
            digitalWrite(LED_2, LOW);
            digitalWrite(LED_3, HIGH);
            if(nowToggle - t > debounce)
            {
              toggleState = 3;
              t = nowToggle;
            }
          }

          break;

     case 3:
     Serial.println("3333");
         if(enabledToggle)
          {
            digitalWrite(LED_3, LOW);
            digitalWrite(LED_4, HIGH);
            if(nowToggle - t > debounce)
            {
              toggleState = 4;
              t = nowToggle;
            }
          }
          break;

     case 4:
     Serial.println("44444");
          if(enabledToggle)
          {
            turnOffLeds();
            if(nowToggle - t > debounce)
            {
              toggleState = 0;
              t = nowToggle;
            }
          }
          break;

  }
}

void turnOffLeds()
{
  digitalWrite(LED_1, LOW);
  digitalWrite(LED_2, LOW);
  digitalWrite(LED_3, LOW);
  digitalWrite(LED_4, LOW);
}

```

updated code: trying to add in debounce but it will not work

```

int LED_1 = 2;
int LED_2 = 3;
int LED_3 = 4;
int LED_4 = 5;

int LED_5 = 6;
int LED_6 = 7;
int LED_7 = 8;
int LED_8 = 9;

//toggle switch button between different modes
int toggle_IN = A4;

//switch case statement variable for togglemodes
int toggleState = 0;

//variables to see if the toggle button has been pressed or not
boolean oldSwitchStateToggle = LOW;
boolean newSwitchStateToggle = LOW;

//true or false to save whether button has been pressed for switching case statements
bool enabledToggle;

//debounce time to take care of button bouncing
const int debounce = 100; //ms

//time for holding a current time of millis()
unsigned long t = 0;

int ledBlinkState = LOW;

unsigned long prevBlinkMillis = 0;

const int blinkInterval = 150;

bool state1 = false;
bool state2 = false;
bool state3 = false;
bool state4 = false;
bool state0 = false;

void setup()
{
  Serial.begin(9600);
  //toggle button input
  pinMode(toggle_IN, INPUT);

  //led outputs
  pinMode(LED_4, OUTPUT);
  pinMode(LED_3, OUTPUT);
  pinMode(LED_2, OUTPUT);
  pinMode(LED_1, OUTPUT);
  pinMode(LED_5, OUTPUT);
  pinMode(LED_6, OUTPUT);
  pinMode(LED_7, OUTPUT);
  pinMode(LED_8, OUTPUT);

}

void loop()
{
  unsigned long nowToggle = millis();
  Serial.print("NOWWWWWW");
  Serial.println(nowToggle);
   //checking to see if toggle button has been pushed
   newSwitchStateToggle = digitalRead(toggle_IN);
   if(newSwitchStateToggle != oldSwitchStateToggle)
   {
    t = nowToggle;
    Serial.print("TIMEEEEE");
    Serial.println(t);
    if(newSwitchStateToggle == HIGH)
    {
      if(nowToggle - t > debounce)
      {
        //enabling toggle for if statements
        enabledToggle = true;
        //case switch for flow through 4 different LED output options
        toggleButtonState();
      }

    }
    else
    enabledToggle = false;
    oldSwitchStateToggle = newSwitchStateToggle;
  }

  unsigned long currentBlinkMillis = millis();

  if(state0 == true)
  {
    digitalWrite(LED_5, HIGH);
    digitalWrite(LED_6, HIGH);
    digitalWrite(LED_7, HIGH);
    digitalWrite(LED_8, HIGH);

    if(currentBlinkMillis - prevBlinkMillis >= blinkInterval)
    {
      prevBlinkMillis = currentBlinkMillis;
      if(ledBlinkState == LOW)
      {
        ledBlinkState = HIGH;
      }
      else
      {
        ledBlinkState = LOW;
      }
      digitalWrite(LED_1, ledBlinkState);
      digitalWrite(LED_2, ledBlinkState);
      digitalWrite(LED_3, ledBlinkState);
      digitalWrite(LED_4, ledBlinkState);
    }
  }

  if(state1 == true)
  {
    digitalWrite(LED_1, HIGH);
    digitalWrite(LED_2, HIGH);
    digitalWrite(LED_3, HIGH);
    digitalWrite(LED_4, HIGH);

    if(currentBlinkMillis - prevBlinkMillis >= blinkInterval)
    {
      prevBlinkMillis = currentBlinkMillis;
      if(ledBlinkState == LOW)
      {
        ledBlinkState = HIGH;
      }
      else
      {
        ledBlinkState = LOW;
      }
      digitalWrite(LED_5, ledBlinkState);
      digitalWrite(LED_6, ledBlinkState);
      digitalWrite(LED_7, ledBlinkState);
      digitalWrite(LED_8, ledBlinkState);
    }
  }

  if(state2 == true)
  {
    if(currentBlinkMillis - prevBlinkMillis >= blinkInterval)
    {
      prevBlinkMillis = currentBlinkMillis;
      if(ledBlinkState == LOW)
      {
        ledBlinkState = HIGH;
      }
      else
      {
        ledBlinkState = LOW;
      }
      digitalWrite(LED_1, ledBlinkState);
      digitalWrite(LED_2, ledBlinkState);
      digitalWrite(LED_3, ledBlinkState);
      digitalWrite(LED_4, ledBlinkState);
      digitalWrite(LED_5, ledBlinkState);
      digitalWrite(LED_6, ledBlinkState);
      digitalWrite(LED_7, ledBlinkState);
      digitalWrite(LED_8, ledBlinkState);
    }
  }

  if(state3 == true)
  {
    digitalWrite(LED_1, HIGH);
    digitalWrite(LED_2, HIGH);
    digitalWrite(LED_3, HIGH);
    digitalWrite(LED_4, HIGH);
    digitalWrite(LED_5, HIGH);
    digitalWrite(LED_6, HIGH);
    digitalWrite(LED_7, HIGH);
    digitalWrite(LED_8, HIGH);
  }

  if(state4 == true)
  {
    turnOffLeds();
  }

}

void toggleButtonState()
{
  switch (toggleState)
  {

    case 0:
    Serial.println("0000");
          if(enabledToggle)
          {
            turnOffLeds();
            state4 = false;
            state0 = true;
            toggleState = 1;
          }

          break;

    case 1:
    Serial.println("1111");
          if(enabledToggle)
          {
            turnOffLeds();
            state0 = false;
            state1 = true;
            toggleState = 2;
          }

          break;

     case 2:
     Serial.println("2222");
          if(enabledToggle)
          {
            turnOffLeds();
            state1 = false;
            state2 = true;
            toggleState = 3;
          }

          break;

     case 3:
     Serial.println("3333");
         if(enabledToggle)
          {
            turnOffLeds();
            state2 = false;
            state3 = true;
            toggleState = 4;
          }
          break;

     case 4:
     Serial.println("44444");
          if(enabledToggle)
          {
            turnOffLeds();
            state3 = false;
            state4 = true;
            toggleState = 0;
          }
          break;

  }
}

void turnOffLeds()
{
  digitalWrite(LED_1, LOW);
  digitalWrite(LED_2, LOW);
  digitalWrite(LED_3, LOW);
  digitalWrite(LED_4, LOW);
  digitalWrite(LED_5, LOW);
  digitalWrite(LED_6, LOW);
  digitalWrite(LED_7, LOW);
  digitalWrite(LED_8, LOW);
}

```

# Answer
> 1 votes
I would recommend you start with an existing library to do the "button debouncing" and "long button press" detection.

The EasyButton library on github and via the Arduino IDE library manager has potential.

Here is a test sketch which shows the "button detection" part of your requirement.

If you were to add a variable to represent "state", this code could be adapted to control a `case` statement bases on state.

```
// Sketch uses 3286 bytes (10%) of program storage space.
// Global variables use 357 bytes (17%) of dynamic memory.
#include <EasyButton.h>

// EasyButton(uint8_t pin,
//            uint32_t debounce_time = 35,
//            bool pullup_enable = true,
//            bool active_low = true)
EasyButton button(2);

void onPressed(){
  // Your code here to INCREMENT a "state counter".
  Serial.println("Button pressed");
}

void onPressedForDuration(){
  // Your code here to SET the "state counter" to 0.
  Serial.println("Button pressed for duration");
}

void setup(){

  // Test output to serial monitor.
  Serial.begin(9600);

  // Initialize the button.
  button.begin();

  // Add the callback function to be called when the button is pressed.
  button.onPressed(onPressed);

  // Add the callback function to be called when the button is pressed
  // for at least the given time.
  button.onPressedFor(2000, onPressedForDuration);

}

void loop(){

  // Continuously read the status of the button.
  button.read();

}

```

# Answer
> 0 votes
I answered how to do a mode switch with just one button many many years ago. Make use of it what you will... it's just a sample skeleton. Here is the code I used:

```
/*
 Using a single switch to select between 3 modes
*/
// Schematic: http://www.pwillard.com/files/mode4.jpg
//===============================================================
// Global Variables & Constants
//===============================================================

const int ledPinOne = 2; // LED1 ANODE
const int ledPinTwo = 4; // LED2 ANODE
const int ledPinThree = 7; // LED3 ANODE
const int modePin = 13; // Active HIGH, held low by 4.7K

int mode = 0; // Selector State (Initial state = ALL OFF)
int val = 0; // Pin 13 HIGH/LOW Status
int butState = 0; // Last Button State
int modeState = 0; // Last Mode State
boolean debug = 1; // 1 = Print Serial Enabled / 0 = disabled

//===============================================================
// SETUP
//===============================================================
void setup () {
 pinMode(ledPinOne, OUTPUT);
 pinMode(ledPinTwo, OUTPUT);
 pinMode(ledPinThree, OUTPUT);
 pinMode(modePin, INPUT);
 if (debug){
 Serial.begin(9600);
 Serial.print("Initial Mode: ");
 Serial.println(mode);
 Serial.print("Setup Complete\n");
 }
}

//===============================================================
// Main Loop
//===============================================================
void loop() {

 val = digitalRead(modePin);

 // If we see a change in button state, increment mode value
 if (val != butState && val == HIGH){
 mode++;
 }

 butState = val; // Keep track of most recent button state

 // No need to keep setting pins *every* loop
 if (modeState != mode){

 // If no keys have been pressed yet don't execute
 // the switch code below
 // if (mode != 0) {

 switch ( mode ) {
 //case 1 is actually handled below as default

case 2:
 digitalWrite(ledPinOne, LOW);
 digitalWrite(ledPinTwo, HIGH);
 showState();
 break;
 case 3:
 digitalWrite(ledPinTwo, LOW);
 digitalWrite(ledPinThree, HIGH);
 showState();
 break;
 default:
 mode = 1;
 // loop back to 1 by default, seems redundant but
 // it also handles the "mode is > 3" problem
 digitalWrite(ledPinThree, LOW);
 digitalWrite(ledPinOne, HIGH);
 showState();
 break;
 } // end switch
// } // end of "if mode = 0" check
 } // end of ModeState check
 modeState = mode; // Keep track of mode recent mode value
 delay(10); // slow the loop just a bit for debounce
}

//===============================================================
// Subroutine
//===============================================================
void showState() {
 if (debug){
 Serial.print("Mode: ");
 Serial.println(mode);
 }
}

```

---
Tags: arduino-uno, led, button, millis, debounce
---


# Question
Title: Using 1 ms delay() in a for loop to check inputs.. Bad?
So first off, I know millis() exists. Just asking out of curiosity. Say you have a button you wanna check for during a delay.. Maybe a 10 second delay. So you make a for loop that checks for input and delays 1 ms... 10,000 times. What's bad about this?

```
 int pin = 13;
    bool button = false;

    void setup()
    {
      pinMode(pin, INPUT);
    }

    void loop()
    {

     while(button == false) {
     for(int i = 0; i<10000; i++) {
     if(digitalRead(pin,HIGH){
     button = true;
}
     delay(1);

    }
  }
}

```

# Answer
> 3 votes
You can do this, for quite simple sketches. It starts to become ugly if you add more features and conditions.

Therefore, the "correctTM" (read: *professional*) way is to implement a state machine. See in the IDE the non-delay blink example.

```
const unsigned long DELAY_MS = 1000;

int pin = 13;

enum State {
    WAITING, WORKING,
};

State state;

unsigned long startTime;

void setup()
{
    pinMode(pin, INPUT);
    state = WAITING;
    startTime = millis();
}

void loop()
{
    switch (state) {
    case WAITING:
        // You can put both conditions in one "if" with an "||" operator.
        // But it will look less clear.
        if (millis() - startTime > DELAY_MS) {
            state = WORKING;
        } else if (digitalRead(pin)) {
            state = WORKING;
        }
        break;
    case WORKING:
        // anything to do after the delay or the button
        break;
    default:
        // any error handling you see fit
        break;
    }
}

```

The function `loop()` is designed to be called endlessly in repetition. Use this to your advantage.

# Answer
> 1 votes
> What's bad about this?

It looks a bit clunky but I suppose there is nothing particularly bad about it (apart from your typo of digitalWrite rather than digitalRead).

I would do it more like:

```
unsigned long now = millis ();
button = LOW;

while ((millis () - now < 10000) && (button == LOW))
  button = digitalRead (pin);

```

# Answer
> 0 votes
> I know millis() exists

Ok, millis is always the best way...

> Say you have a button you wanna check for during a delay.. So you make a for loop that checks for input and delays 1 ms... 10,000 times.

Your code is not really doing what you want. Your while loop never ends until button is pressed so 10s delay has no sense. I suppose your code should exit after 10 seconds or if button is pressed.

> Just asking out of curiosity

You're code, without millis(), should be

```
bool button = false;
...
...
void loop() {
  uint16_t ms2wait = 10000;
  while (button == false && --ms2wait > 0) {
    if(digitalRead(pin,HIGH)
      button = true;
    delay(1);
  }
}

```

---
Tags: millis, input, delay
---


# Question
Title: How to get started with writing code for a Hall Effect sensor?
One of my biggest questions concerns coding a Hall effect sensor to find wheel speed with an arduino mega.

I’ve got an lcd in digital pins(7,8,9,10,11,12) and a Hall effect sensor in digital pin 2.

I just have no idea how to code the actual rpm measuring process. Does anyone have any ideas or experience that can help me? My form of measurement is to spin something with a mounted magnet near it. The end game is to measure a car wheel rpm. Pointers? Tips?

# Answer
> 1 votes
You can measure this in either RPM (revolutions per minute) or frequency (cycles per second).

Whether it be a minute or a second, you count the number of times you get a pulse and at the end of the minute/second you copy the total to your variable and reset the counter variable. If you need a fasster update rate, you can count for fractions of minute/second and do the calculation to show it in terms of RPM/frequency.

My first concern when solving this issue is how fast the magnet is going past the sensor (ie how many pulses per second).

If it is slow, you can do it in your main loop as long as you don't have any blocking instructions (such as `delay()`).

If it is fast you will probably have to look into an interrupt. When the pin goes high, it jumps to the interrupt function and increments a counter. Check the input section for libraires that make the interrupt process easy (or do it the old fashioned way, your choice). Some of the button libraries have interrupt specific functions.

---
Tags: programming, sketch, frequency, hall-effect
---


title: String to unsigned 16-bit integer

text:
# Question
Title: String to unsigned 16-bit integer
I'm currently working on a project with a 4DSystems Display. Im talking to the Display over SoftwareSerial with an ESP32. As soon as I want to use a Unicode character it requires me to convert my whole String to a uint16\_t. Can somebody help me I have no idea how I should go on with this?

```
  #include <genieArduino.h>
  void loop() {
    uint16_t tn[] = { 0x2126,0 }; // Ω
    genie.WriteStrU(0, tn);
  }

```

This works but how could I inset a variable into the uint16\_t?

# Answer
As mentioned by chrisl in a comment, your best option is to to use the regular `WriteStr()` method to print variables, and use `WriteStrU()` to print Unicode string constants. For example:

```
float R = 12.34;  // dummy resistance value.
genie.WriteStr(0, "R = ");
genie.WriteStr(0, R);
genie.WriteStrU(0, (uint16_t *) u" Ω");

```

should print:

```
R = 12.34 Ω

```

Note the use of the `u` string prefix to write UTF-16-encoded strings in the source code.

---

**Edit**: You wrote

> the `WriteStr` always replaces the text inside a String object instead of adding on.

This makes things more complicated. The only option I see is to format the whole message as UTF-16 beforehand, then send it with `WriteStrU()`. Here is a class that does simple UTF-16 formatting. It inherits from the `Print` class, meaning you can `print()` to it anything you could print to `Serial`. In addition, it can print UTF-16 strings:

```
template <size_t max_length>
class UTF16Writer : public Print {
public:
    // Convert ASCII to UTF-16.
    size_t write(uint8_t c) {
        if (length >= max_length)
            return 0;  // buffer full
        buffer[length++] = c;
        buffer[length] = 0;  // terminate string
        return 1;
    }
    // Record UTF-16 data.
    size_t print(const char16_t *s) {
        size_t chars_written = 0;
        while (*s && length < max_length) {
            buffer[length++] = *s++;
            chars_written++;
        }
        buffer[length] = 0;  // terminate string
        return chars_written;
    }
    using Print::print;
    uint16_t buffer[max_length + 1];
private:
    size_t length = 0;
};

```

The template parameter is the capacity of the buffer. Once you have written the whole message as UTF-16 using this class, you can pass its `buffer` member to `WriteStrU()`. For example:

```
float R = 12.34;  // dummy resistance value.
UTF16Writer<16> writer;
writer.print("R = ");
writer.print(R);
writer.print(u" Ω");
genie.WriteStrU(0, writer.buffer);

```

**Note**: Do not forget the `u` prefix in the Unicode string, otherwise the bytes of the string (UTF-8 in the source) would be interpreted as latin1 by `UTF16Writer::print(const char*)`. A message such as `"martine écrit en UTF-8"` would then be displayed as “martine Ã©crit en UTF-8”.
> 1 votes

---
Tags: esp32, convert
---


# Question
Title: Simulating a button press using the Serial Monitor to run a Servo
I'm kind of new to Arduino and C, and I was having trouble with this sketch. I'm working on a project to control 6 servos using virtual buttons. When I hold down the button, the servo moves forward smoothly to a certain fixed point, and when I release it, it comes back to a fixed point. I initially tested this with a single servo and an actual button on my breadboard using the following sketch.

```
#include<Servo.h>
int switch1;
float switch1Smoothed;
float switch1Prev;
Servo myservo1;
float a=1200.0; //lower angle limit

void setup() {

  Serial.begin(115200);
  pinMode(A1,INPUT_PULLUP);
  myservo1.attach(9);
  myservo1.writeMicroseconds(a);
  switch1Prev=a;
}

void loop() {
//Motor 1
  switch1 = digitalRead(A1);// read switch | will return 1 or 0 continuously
  //Serial.println(switch1);
  switch1 = switch1 * 2400;        // multiply by angle limit

  // *** smoothing ***

  switch1Smoothed = (switch1 * 0.05) + (switch1Prev * 0.95);
  if(switch1Smoothed>=a){
  switch1Prev = switch1Smoothed;
  }
  else{
    switch1Prev = a;
  }
  // *** end of smoothing ***

//  Serial.print(switch1);                  // print to serial terminal/plotter
//  Serial.print(" , ");
//  Serial.println(switch1Smoothed);
    myservo1.writeMicroseconds(switch1Smoothed) ;
    delay(10);                               // repeat loop 100 times per second
}

```

This works out just fine. Now, I'm working with NodeRed, a low code JavaScript flow creator, which is where my virtual button is, and I've set it up to send 0s or 1s as strings based on whether the button is pressed or not via serial communication. This is the config of the Serial Node on NodeRed:

And I wrote a short function on Arduino to parse the incoming string from the serial connection, convert it back to an integer, and then use that as my "button" input. However, it seems that either my logic is flawed, or my code is because my servo does not behave the same way it does with the physical button.

Here's the modified sketch:

```
#include <Servo.h>
int switch1;
float switch1Smoothed;
float switch1Prev;
Servo myservo1;
float a=1200.0;
String readString, mot1, mot2;

void setup() {
  Serial.begin(9600);
  myservo1.attach(9);
  myservo1.writeMicroseconds(a);
  switch1Prev=a;
}

void captureChar(int& n1){ //using reference to pass the value

  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    }
  }

  if (readString.length() >0) {

      mot1 = readString.substring(0,1);
      mot2 = readString.substring(1,2);
      n1 = mot1.toInt();
      //n2 = mot2.toInt();
    readString="";

  }
}

void loop(){
  captureChar(switch1);
  switch1 = switch1 * 2400;        // multiply by maximum angle limit

  // *** smoothing ***

  switch1Smoothed = (switch1 * 0.05) + (switch1Prev * 0.95);
  if(switch1Smoothed>=a){
  switch1Prev = switch1Smoothed;
  }
  else{
    switch1Prev = a;
  }
  // *** end of smoothing ***

//  Serial.print(switch1);                  // print to serial terminal/plotter
//  Serial.print(" , ");
//  Serial.println(switch1Smoothed);
  myservo1.writeMicroseconds(switch1Smoothed);
  delay(15);
}

```

When I load this sketch and hold down the virtual button, i.e., send a continuous stream of string "1", the motor simply goes back and forth really fast, rather than slowly moving to the set maximum position and stopping there while the button is held.

# Answer
> 3 votes
There may be a problem with your smoothing logic, which is quite convoluted. However, if the first code works fine, you can keep it *almost* as-is, and only replace `digitalRead()` with a version that reads the virtual button. It looks like that is what `captureChar()` attempts to achieve. This function, however, has a couple of problems:

* it has a loop and a delay, thus breaking the timing of the original code
* its interface is very different from the one of `digitalRead()`, and thus cannot be used as a drop-in replacement.

Here is what I would propose as a `digitalRead()` replacement. It has the same signature as the original `digitalRead()`, and can be used as a drop-in replacement:

```
int virtual_switch_reading = LOW;

int virtualDigitalRead(uint8_t /* pin number ignored */) {
    int c = Serial.read();
    if (c == '0')
        virtual_switch_reading = LOW;
    else if (c == '1')
        virtual_switch_reading = HIGH;
    return virtual_switch_reading;
}

```

Note that calling `Serial.available()` is not useful: if no data is available, `Serial.read()` returns `-1`, which is neither equal to `'0'` nor equal to `'1'`.

---

**Edit**: addressing the requirement to have six virtual switches.

As stated in a comment, I suggest you encode the states of all the switches, within NodeRed, as a single byte, with one bit per switch. You would then send this byte to the Arduino, either periodically or whenever any switch changes state.

On the Arduino, in order to simulate `digitalRead()` on a virtual switch, you first have to map the pin numbers to the virtual switches:

```
// Map a pin number to a virtual switch.
const uint8_t virtual_switch_masks[NUM_DIGITAL_PINS] = {
    0,     // pin 0: not virtual
    0,     // pin 1: not virtual
    1<<0,  // pin 2: virtual switch 0
    1<<1,  // pin 3: virtual switch 1
    // etc...
};

```

Note that this table doesn't store switch numbers. It instead stores *bit masks*. For example, virtual switch 1 is stored as `1<<1` = `0b00000010`, i.e. all bits are clear except for bit number 1 (rightmost being zero), which is set.

You can then simulate `digitalRead()` by extracting the relevant bit from the byte you last received from NodeRed, which is done by a *bitwise and* with the relevant mask:

```
// States of all virtual switches, one bit per switch.
uint8_t virtual_switch_states = 0;

int virtualDigitalRead(uint8_t pin) {
    uint8_t mask = virtual_switch_masks[pin];

    // If this is not a virtual switch, do a regular digitalRead().
    if (!mask)
        return digitalRead(pin);

    // For a virtual switch, extract the relevant bit
    // from virtual_switch_states.
    if (virtual_switch_states & mask)
        return HIGH;
    else
        return LOW;
}

```

In order to update the states of the virtual switches from the data received, you just have to add this somewhere within `loop()`:

```
if (Serial.available())
    virtual_switch_states = Serial.read();

```

---
Tags: servo, button, debugging
---


# Question
Title: Why is EEPROM commit not registering int values?
```
       if(jsonDoc["delayOn"].as<int>() <= 255 && jsonDoc["delayOff"].as<int>() <= 255 && jsonDoc["delayUnitOn"].as<int>() <= 2 && jsonDoc["delayUnitOff"].as<int>() <= 2 &&
         jsonDoc["mode"].as<int>() <= 1 && jsonDoc["blink"].as<int>() <= 1 &&
         jsonDoc["timeOnHour"].as<int>() <= 23 && jsonDoc["timeOnMinute"].as<int>() <= 59 &&
         jsonDoc["timeOffHour"].as<int>() <= 23 && jsonDoc["timeOffMinute"].as<int>() <= 59) {

        int val;
        int addr_init = (relay*eepromSlotsPerRelayPin)*sizeof(int);

        val = jsonDoc["blink"].as<int>();
        EEPROM.put(addr_init,val);
        if(jsonDoc["blink"].as<int>()==1){ //0=off,1=on

          val = jsonDoc["mode"].as<int>();
          EEPROM.put(addr_init+(5*sizeof(int)),val);

          if (jsonDoc["mode"].as<int>()==0){ //blink mode

            val = jsonDoc["delayOn"].as<int>();
            EEPROM.put(addr_init+(1*sizeof(int)),val);
            val = jsonDoc["delayOff"].as<int>();
            EEPROM.put(addr_init+(3*sizeof(int)),val);
            //1=minute,0=second,2=hour
            val = jsonDoc["delayUnitOn"].as<int>();
            EEPROM.put(addr_init+(2*sizeof(int)),val);
            val = jsonDoc["delayUnitOff"].as<int>();
            EEPROM.put(addr_init+(4*sizeof(int)),val);
            EEPROM.end();

          }else if(jsonDoc["mode"].as<int>()==1){ //time switch mode

            val = jsonDoc["timeOnHour"].as<int>();
            EEPROM.put(addr_init+(6*sizeof(int)),val);
            val = jsonDoc["timeOnMinute"].as<int>();
            EEPROM.put(addr_init+(7*sizeof(int)),val);
            val = jsonDoc["timeOffHour"].as<int>();
            EEPROM.put(addr_init+(8*sizeof(int)),val);
            val = jsonDoc["timeOffMinute"].as<int>();
            EEPROM.put(addr_init+(9*sizeof(int)),val);
            EEPROM.end();
          }
          else {
            request->send(412, "text/plain", "unknown mode");
            return;
          }
        }
      }
      else {
        request->send(412, "text/plain", "a parameter is not within limits");
        return;
      }

      //initBlinkPinObjs
      int addr_init;
      int val,uom;
      for(int i = 0; i<maxRelayPins; i++) {
        bPinObjs[i].pin = relayPins[i];
        //EEPROM Slot per Relay dataStruct
        //0=>enable, 1=>durationOn, 2=>durationOnTimeMeasure,
        //3=>durationOff, 4=>durationOffTimeMeasure
        //5=>mode, 6=>timeOnHour, 7=>timeOnMinute,
        //8=>timeOffHour, 9=>timeOffMinute

        addr_init = (i*eepromSlotsPerRelayPin)*sizeof(int);

        val = 0;
        EEPROM.get(addr_init,val);
       bPinObjs[i].enable = val;

        val = 0;
        EEPROM.get(addr_init+(5*sizeof(int)),val);
        bPinObjs[i].mode = val;

        val = 0;
        EEPROM.get(addr_init+(6*sizeof(int)),val);
        bPinObjs[i].timeOnHour=val;

        val = 0;
        EEPROM.get(addr_init+(7*sizeof(int)),val);
        bPinObjs[i].timeOnMinute=val;

        val = 0;
        EEPROM.get(addr_init+(8*sizeof(int)),val);
        bPinObjs[i].timeOffHour = val;

        val = 0;
        EEPROM.get(addr_init+(9*sizeof(int)),val);
        bPinObjs[i].timeOffMinute = val;

        //delayOn
        //convert to millisec
        uom = 0;
        EEPROM.get(addr_init+(2*sizeof(int)),uom);
        switch(uom){
          case 0:
            bPinObjs[i].durationOn=0;
            val = 0;
            EEPROM.get(addr_init+(1*sizeof(int)),val);
            bPinObjs[i].durationOn = val*1000;
          break;
          case 1:
            bPinObjs[i].durationOn=0;
            val = 0;
            EEPROM.get(addr_init+(1*sizeof(int)),val);
            bPinObjs[i].durationOn = val*60000;
          break;
          case 2:
            bPinObjs[i].durationOn=0;
            val = 0;
            EEPROM.get(addr_init+(1*sizeof(int)),val);
            bPinObjs[i].durationOn = val*3600000;
          break;
          default:
          break;
        }
        //delayOff
        //convert to millisec
        uom = 0;
        EEPROM.get(addr_init+(4*sizeof(int)),uom);
        switch(uom){
          case 0:
            bPinObjs[i].durationOff = 0;
            val = 0;
            EEPROM.get(addr_init+(3*sizeof(int)),val);
            bPinObjs[i].durationOff = val*1000;
          break;
          case 1:
            bPinObjs[i].durationOff = 0;
            val = 0;
            EEPROM.get(addr_init+(3*sizeof(int)),val);
            bPinObjs[i].durationOff = val*60000;
          break;
          case 2:
            bPinObjs[i].durationOff = 0;
            val = 0;
            EEPROM.get(addr_init+(3*sizeof(int)),val);
            bPinObjs[i].durationOff = val*3600000;
          break;
          default:
          break;
        }
      }

```

```
--JSON INPUT printed from server--

relay:0
blink:1
mode:1
delayOn:56
delayOff:2
delayUnitOn:0
delayUnitOff:0
timeOnHour:5
timeOnMinute:56
timeOffHour:7
timeOffMinute:48

```

```
OUTPUT printed from server:
--Objects content--
Size of INT:4
---------0--------- init addr: 0
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------1--------- init addr: 40
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------2--------- init addr: 80
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------3--------- init addr: 120
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------4--------- init addr: 160
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------5--------- init addr: 200
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------6--------- init addr: 240
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------7--------- init addr: 280
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0
---------8--------- init addr: 320
[0]enable: 0
[1]durationOn: 0
[2]durationOnUom: 0
[3]durationOff: 0
[4]durationOffUom: 0
[5]mode: 0
[6]onHr: 0
[7]onMin: 0
[8]offHr: 0
[9]offMin: 0

```

This is inside an esp8266 async webserver `server.on` method. My `EEPROM.begin` is in `setup` function. Initially, only the first `put` within a block becomes committed . Now, nothing is registering after I implemented the `sizeof(int)` inside addresses.

The intention is to store `int` data passed thru `http post` per relay pin \[total of 9 pins\]. The program then uses the data to perform on a relay:

* blink
* switch on/off based on time (hour,minute) ...

I've tried all sorts to fix:

* `commit`,`end` after every `put`
* `EEPROM.begin(512)` then `commit` & `end` on every `put`
* add `delay`s
* use `end` only instead of `commit`
* add address range for `sizeof(int)`

# Answer
> 0 votes
Weird, i commented out the `val=0;` before `EEPROM.get`s also replaced `EEPROM.end` with `EEPROM.commit`.

This is the output now:

```
--Objects content--
Size of INT:4
---------0--------- init addr: 0
[0]enable: 1
[4]durationOn: 3000
[8]durationOnUom: 0
[12]durationOff: 2000
[16]durationOffUom: 0
[20]mode: 1
[24]onHr: 9
[28]onMin: 11
[32]offHr: 9
[36]offMin: 12
---------1--------- init addr: 40
[40]enable: 1
[44]durationOn: 0
[48]durationOnUom: -1
[52]durationOff: 0
[56]durationOffUom: -1
[60]mode: -1
[64]onHr: -1
[68]onMin: -1
[72]offHr: -1
[76]offMin: -1
---------2--------- init addr: 80
[80]enable: 1
[84]durationOn: 0
[88]durationOnUom: -1
[92]durationOff: 0
[96]durationOffUom: -1
[100]mode: -1
[104]onHr: -1
[108]onMin: -1
[112]offHr: -1
[116]offMin: -1
---------3--------- init addr: 120
[120]enable: 1
[124]durationOn: 0
[128]durationOnUom: -1
[132]durationOff: 0
[136]durationOffUom: -1
[140]mode: 1
[144]onHr: 5
[148]onMin: 56
[152]offHr: 7
[156]offMin: 48
---------4--------- init addr: 160
[160]enable: 1
[164]durationOn: 0
[168]durationOnUom: -1
[172]durationOff: 0
[176]durationOffUom: -1
[180]mode: -1
[184]onHr: -1
[188]onMin: -1
[192]offHr: -1
[196]offMin: -1
---------5--------- init addr: 200
[200]enable: 1
[204]durationOn: 0
[208]durationOnUom: -1
[212]durationOff: 0
[216]durationOffUom: -1
[220]mode: -1
[224]onHr: -1
[228]onMin: -1
[232]offHr: -1
[236]offMin: -1
---------6--------- init addr: 240
[240]enable: 1
[244]durationOn: 0
[248]durationOnUom: -1
[252]durationOff: 0
[256]durationOffUom: -1
[260]mode: -1
[264]onHr: -1
[268]onMin: -1
[272]offHr: -1
[276]offMin: -1
---------7--------- init addr: 280
[280]enable: 1
[284]durationOn: 0
[288]durationOnUom: -1
[292]durationOff: 0
[296]durationOffUom: -1
[300]mode: -1
[304]onHr: -1
[308]onMin: -1
[312]offHr: -1
[316]offMin: -1
---------8--------- init addr: 320
[320]enable: 1
[324]durationOn: 0
[328]durationOnUom: -1
[332]durationOff: 0
[336]durationOffUom: -1
[340]mode: -1
[344]onHr: -1
[348]onMin: -1
[352]offHr: -1
[356]offMin: -1

--JSON inputs--

relay:0
blink:1
mode:1
delayOn:3
delayOff:2
delayUnitOn:0
delayUnitOff:0
timeOnHour:9
timeOnMinute:11
timeOffHour:9
timeOffMinute:12

```

---
Tags: esp8266, eeprom, esp8266webserver
---


# Question
Title: Pan and tilt bracket move to sound, control servo motors using microphone sound sensors
I'm trying to code the pan and tilt bracket to turn based on where I speak, I know how to move the servo motors, but I really need help with the sound sensing. This is the code I've got currently:

```
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
     Servo myservo2;           // a maximum of eight servo objects can be created
int sound1;
int sound2;
int pos = 0;    // variable to store the servo position

void setup()
{
  Serial.begin(9600);
  myservo.attach(5);  // attaches the servo on pin 9 to the servo object
  myservo2.attach(6);
}

void loop()
{
  sound1 = analogRead(A0);
  sound2 = digitalRead(7);

  if (sound1 > 50)
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }

   if (sound2 > 50)
   for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

```

I've been working on this for some time, but for some reason, whenever I try to code the sound sensor, it always ends up being ignored, so for example, If my code says, if sound sensor number 1 detects sound, move 90 degrees vertically or horizontally, it always ignores that if statement and just continuously moves 90 degrees to wherever. I need it to follow my voice, or if that's too advanced, it's fine if it just follows any sound. So if I more 30 degree to the right on the pan and tilt bracket, and speak, I need it to turn and face me. Also, the kind of sound sensor I'm using is KY-037, the red variation with 4 pins. Any advice would be really helpful, thanks.

# Answer
> 4 votes
What you are trying to achieve is not easy. Expect to spend a lot of time developing, testing and tuning it.

The first step would be to work the acoustics of your device. The sound sensors are not sensitive to the direction of the incoming sound, so you will to have to use two of them facing different directions, like the ears on your head face different sides. It would help to have the polar plot of your microphones: if they are not directional enough, you may have to build some kind of sound obstacle between them (the “head” between the ears, or maybe even a pair of “auricles”) to improve the angular selectivity. With cardioid microphones, you may get away with just facing them 180° apart.

Getting this right can take significant effort. A two-channel oscilloscope and a sinusoidal sound source would help a lot: watch the signals coming out of both mikes, and see how their amplitudes change as you turn the head. You want them to be sensitive enough to that orientation. Then, adjust the potentiometers within the sound modules in order to have the same amplitudes when the head is facing the sound source.

Next you will have to sample these signals with your Arduino. The default Arduino sampling rate (`analogRead()` in a tight loop) is about 8.93 kHz for a single channel, or 4.46 kHz per channel if alternating between two channels. This may be enough for getting a rough estimate of the intensity of voice, but it is kind of borderline too low. You may want to increase the sampling rate: the way to do so has been discussed here, and is only a search away.

With `analogRead()`, the sampling rate is also inconsistent and dependent on what the sketch is doing: the more the CPU works, the slower the sampling rate. I would strongly recommend letting the ADC work in free running mode, and retrieve the samples from an interrupt service routine. For this, you will have to first read and understand the chapter on the ADC from the datasheet of the microcontroller.

Next, you have to estimate the intensities from the samples you read. In principle, this means low-pass filtering the square of the AC part of the signal. If that is too much work, you may get away with a simple peak-detection.

You may want to take a look at this sound-meter sketch for inspiration. It uses the free-running ADC technique and estimates a sound amplitude using the proper “low-pass filtering the square of the AC part of the signal”. It is single channel though, and you will have to adapt it for tracking two channels. This would involve changing the multiplexer setting within the ISR.

Lastly, you will have to make the pan servo respond to the difference in intensities between the two ears. That is the easy part, it could roughly go like this:

```
void loop() {
    float intensity_right = get_sound_intensity(RIGHT_MIKE);
    float intensity_left = get_sound_intensity(LEFT_MIKE);

    // Only move the head if we actually hear sound.
    if (intensity_right >= intensity_threshold
            || intensity_left >= intensity_threshold) {

        float difference = intensity_right - intensity_left;

        // Only move the head if the intensity difference is
        // significant.
        if (fabs(difference) >= difference_threshold) {
            if (difference > 0 && servo_position < 180) {
                servo_position += 1;
                servo.move(servo_position);
            } else if (difference < 0 && servo_position > 0) {
                servo_position -= 1;
                servo.move(servo_position);
            }
        }
    }
}

```

---
Tags: arduino-uno, python
---