# Question
Title: "Done uploading" but Uno still running old sketch
So, this is my first experience, I bought new original Uno, trying write some code there and it stuck in running only one sketch.

Tools-\>Boards is ok, Tools-\>Ports is ok.

I try created new sketch from File-\>Examples-\>01. Basics-\>Blink and it uploaded successfully, but Uno still running old code and sending to Serial Monitor data (from empty A0, where was potentiometer)

I tried reinstall Arduino App, trying on Windows, tried with only power (just 12v round port, without USB) and it still launch old sketch. When I plug Uno to Mac or Windows it immediately start spaming to Serial Monitor same data.

Clicking, pressing, holding "reset" button with plug or unplug on smth else doesn't work.

==============

Here is my last code, which "stuck" on Uno right now:

```
const int myPin = A0;

void setup() {
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  int sensorValue = analogRead(myPin);
  // Serial.print("Sensor value: ");
  Serial.println(sensorValue);

}

```

And proof that upload success:

Here is code of Blink from examples:

```
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}

```

And proof that upload success:

Here is my Uno without anything but with lighted TX port when I plug it into Mac/Windows (you can see that L/13 bulb light darker than should and I don't know why):

And here is unstoppable spaming in Serial Monitor by sketch from first code:

```
01:57:24.874 -> 430
01:57:24.874 -> 420
01:57:24.874 -> 425
01:57:24.874 -> 435
01:57:24.874 -> 424
01:57:24.874 -> 425
01:57:24.907 -> 425
01:57:24.907 -> 434
01:57:24.907 -> 422
01:57:24.907 -> 425
01:57:24.907 -> 425
01:57:24.907 -> 433
01:57:24.940 -> 420
01:57:24.940 -> 424
01:57:24.940 -> 423
01:57:24.940 -> 431
01:57:24.940 -> 417
01:57:24.940 -> 423
01:57:24.940 -> 422
01:57:24.973 -> 429
01:57:24.973 -> 415
01:57:24.973 -> 421
01:57:24.973 -> 422
01:57:24.973 -> 424
01:57:24.973 -> 416
01:57:25.005 -> 421
01:57:25.005 -> 428
01:57:25.005 -> 421
01:57:25.005 -> 419
01:57:25.005 -> 418
01:57:25.005 -> 426
01:57:25.036 -> 415
01:57:25.036 -> 417
01:57:25.036 -> 417
01:57:25.036 -> 424
01:57:25.036 -> 411
01:57:25.036 -> 416
01:57:25.036 -> 416
01:57:25.069 -> 424
01:57:25.069 -> 410
01:57:25.069 -> 416
01:57:25.069 -> 416
01:57:25.069 -> 423
01:57:25.069 -> 407
01:57:25.101 -> 415

```

=========== UPD: On IDE v. 1.8.19 I got this

```
Arduino: 1.8.19 (Mac OS X), Board: "Arduino Uno"

Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
An error occurred while uploading the sketch
avrdude: verification error, first mismatch at byte 0x0002
         0x5d != 0x5c
avrdude: verification error; content mismatch

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

```

With checked show verbose during compilation and upload I got more:

```
Arduino: 1.8.19 (Mac OS X), Board: "Arduino Uno"

/private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/arduino-builder -dump-prefs -logger=machine -hardware /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/hardware -hardware /Users/mr_belogub/Library/Arduino15/packages -tools /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/tools-builder -tools /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/mr_belogub/Library/Arduino15/packages -built-in-libraries /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/libraries -libraries /Users/mr_belogub/Documents/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=2341_0043 -ide-version=10819 -build-path /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559 -warnings=none -build-cache /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_cache_275921 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -verbose /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/examples/01.Basics/Blink/Blink.ino
/private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/arduino-builder -compile -logger=machine -hardware /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/hardware -hardware /Users/mr_belogub/Library/Arduino15/packages -tools /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/tools-builder -tools /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/mr_belogub/Library/Arduino15/packages -built-in-libraries /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/libraries -libraries /Users/mr_belogub/Documents/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=2341_0043 -ide-version=10819 -build-path /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559 -warnings=none -build-cache /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_cache_275921 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -verbose /private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/examples/01.Basics/Blink/Blink.ino
Using board 'uno' from platform in folder: /Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6
Using core 'arduino' from platform in folder: /Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6
Detecting libraries used...
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/standard /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/sketch/Blink.ino.cpp -o /dev/null
Generating function prototypes...
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/standard /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/sketch/Blink.ino.cpp -o /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/preproc/ctags_target_for_gcc_minus_e.cpp
/private/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/AppTranslocation/9AA61328-BD81-4800-BA6D-7F5DD6005876/d/Arduino.app/Contents/Java/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/preproc/ctags_target_for_gcc_minus_e.cpp
Compiling sketch...
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino -I/Users/mr_belogub/Library/Arduino15/packages/arduino/hardware/avr/1.8.6/variants/standard /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/sketch/Blink.ino.cpp -o /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/sketch/Blink.ino.cpp.o
Compiling libraries...
Compiling core...
Using precompiled core: /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_cache_275921/core/core_arduino_avr_uno_7dc84736bec69d7a3f526b3465643c6f.a
Linking everything together...
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.elf /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/sketch/Blink.ino.cpp.o /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/../arduino_cache_275921/core/core_arduino_avr_uno_7dc84736bec69d7a3f526b3465643c6f.a -L/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559 -lm
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.elf /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.eep
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy -O ihex -R .eeprom /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.elf /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-size -A /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.elf
Sketch uses 924 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -carduino -P/dev/cu.usbmodem1101 -b115200 -D -Uflash:w:/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/Users/mr_belogub/Library/Arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/Users/mr_belogub/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/cu.usbmodem1101
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "/var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex"
avrdude: writing flash (924 bytes):

Writing | ################################################## | 100% 0.13s

avrdude: 924 bytes of flash written
avrdude: verifying flash memory against /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex:
avrdude: load data flash data from input file /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex:
avrdude: input file /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex contains 924 bytes
avrdude: reading on-chip flash data:

An error occurred while uploading the sketch
Reading | ################################################## | 100% 0.13s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0002
         0x5d != 0x5c
avrdude: verification error; content mismatch

avrdude done.  Thank you.

```

# Answer
So, my solution is: **burn new bootloader**

I bought: USBASP ISP-AVR V2 (Programmer) - 139 UAH / 3.65 USD
10pin to 6pin connector - 22 UAH / 0.58 USD
(cable was with programmer)

I connect programmer to cable with 10pin female, other 10pin female to 10pin/6pin connector, connector to 6 alone pins on Arduino, Arduino to PC

Install drivers, via IDE choose Tools-\>Burn Bootloader

And voilà!
> 1 votes

# Answer
It looks like your upload failed:

```
avrdude: verifying flash memory against /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex:
avrdude: load data flash data from input file /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex:
avrdude: input file /var/folders/g4/0ddwtmhx3y97b4nm8m2ns88c0000gn/T/arduino_build_275559/Blink.ino.hex contains 924 bytes
avrdude: reading on-chip flash data:

An error occurred while uploading the sketch
Reading | ################################################## | 100% 0.13s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0002
         0x5d != 0x5c
avrdude: verification error; content mismatch

```

This was possibly related to your first sketch outputting to serial constantly. In future I suggest building in a delay before sending data constantly to serial (eg. `delay(500)`).

Burning a new bootloader removed the problem sketch.

Instead you could have held down the Reset button until the uploading started, and then released it. That would stop the original sketch from running.
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Shared memory space for locally defined buffers?
Within a class I have a method that is using a basic char buffer to print some data, something like

```
char buffer[64];
sprintf(buffer, "%s: some text: %u, %u, %u %u", string_var, u_var1, u_var2, u_var3, u_var4);
Serial.println(buffer);

```

All variables are defined locally to that method within the class.

For the moment I have commented out the Serial.println(buffer), as it is part of precompiler debugging section. I know that this buffer is not being printed from this location. The buffer is still being loaded with data but is NOT being printed.

In my main code I have another function using a similar format, but the buffer has a different name.

```
char json_buffer[256];
Serial.println(json_buffer);

```

again all defined locally, NOT globally.

Now this serial print line is printing the contents of the first char buffer\[64\], UNLESS I create it with a null termination from the off, like:

```
char json_buffer[256] ={"\n"};

```

Why is this happening? is it a memory leak? buffer overflow? I have tried increasing the size of each buffer, for example the first buffer I have tried with 512 characters size, and the 2nd with 512 also, but no matter what I try the contents of the first buffer are being printed when I print the 2nd one.

Just looking for an explanation and a robust way of preventing this. Thanks!

Full code is at: https://github.com/practable/refrigeration/tree/dev/fw/refrigerationFirmware But is a fairly extensive program

# Answer
> 3 votes
From your linked code this doesn't look valid to me:

```
sprintf(json_buffer, "%s%s", json_buffer, json_footer);

```

It looks like you are trying to append json\_footer to json\_buffer, however the sprintf will start writing to the start of json\_buffer, discarding what is already there. I suggest you use `strcat` instead.

You are doing that a lot, and there is a possibility of a race condition, where, in the process of writing to json\_buffer in that invalid way, the sprintf gets out of control and writes much more than it should.

# Answer
> 1 votes
Just as a complement to Nick Gammon's answer: if you want to build the JSON string using `sprintf()`, you should keep track of the current position of the end of the string (the `\0` that terminates it): that's where you should write the next bit, thus that's the pointer you will provide to `sprintf()`.

Also, you may want to use `snprintf()` instead, just to make sure you never overflow your buffer.

Here is an example of building a string by multiple calls to `snprintf()`, while keeping track of the current writing position:

```
char *build_json() {
    static char buffer[620];
    char *end = buffer + sizeof buffer;  // end of buffer
    char *p = buffer;                    // current writing position

    p += snprintf(p, end-p, "{\n");
    p += snprintf(p, end-p, "  \"timestamp\": %d,\n", 1704391201);
    p += snprintf(p, end-p, "  \"valves\": {\n");
    p += snprintf(p, end-p, "    \"V1\": %d,\n", rand() % 2);
    p += snprintf(p, end-p, "    \"V2\": %d\n", rand() % 2);
    p += snprintf(p, end-p, "  },\n");
    p += snprintf(p, end-p, "  \"relays\": {\n");
    p += snprintf(p, end-p, "    \"foo\": %d,\n", rand() % 2);
    p += snprintf(p, end-p, "    \"bar\": %d\n", rand() % 2);
    p += snprintf(p, end-p, "  }\n");
    p += snprintf(p, end-p, "}\n");
    return buffer;
}

```

# Answer
> 0 votes
Automatic variables live on the stack for the duration of the block in which they were created - probably the whole of each of those functions. They are not automatically initialized, but merely considered to be in use for the durations of execution of each function.

So the likely answer is that `buffer` and `json_buffer` overlap, at least to some degree. In that case, since you didn't initialize 'json\_buffer', whatever will be printed from it is **whatever data was previously left in the memory area** it now occupies. We can't see your code, to say definitively, but since this scenario can describe exactly what your are seeing, I'd say it is highly likely the right explanation.

> Just looking for an explanation and a robust way of preventing this.

Easy, peasy: Don't use the contents of uninitialized variables; always initialize them before use.

---

For the not-yet-initiated the terms might be not that clear.

* "To initialize" generally means **to write** a value into a variable by some means.
* "To use" generally means **to read** from the variable.

The programming language here is C++, which roughly works like this:

* A non-`static` (dynamic) variable local to a function or method is not initialized without an explicit initialization or assignment:
```
/* ... */ {
    int not_initialized;
    int initialized = 23;
    int written_to; // here uninitialized
    written_to = 42; // now "initialized"
}

```
* A `static` variable without explicit initialization is default-initialized:
```
static int default_initialized; // = 0; by the standard's specification

```
This is independent of the scope of the variable. It can live inside any function or method, or outside at unit level.
* A global variable without explicit initialization is default-initialized:
```
// outside any function or method
int default_initialized; // = 0; by the standard's specification

```

With this in mind, it makes no sense to initialize dynamic variables *and to write into them* (what some consider as "to use") without an intermediate usage (reading it). Some compilers can even warn about that code smell:

```
/* ... */ {
    int initialized = 0;
    // other code without access to "initialized"
    initialized = 2024; // second write
                        // Strange, why not initialize it directly?
                        // Or did the programmer forget something in between?
}

```

If your compiler optimizes well, it might remove the initialization.

---
Tags: serial
---


title: LED control with a string variable

text:
# Question
Title: LED control with a string variable
I would like to control three LEDs with a string variable using an Arduino Mega.

I have connected the three LEDs to pins 10, 11 and 12 of the Arduino.

If my string equals Red, the red LED should turn on. If my string equals Yellow, the yellow LED should turn on. If my string equals Green, the green LED should turn on.

I wrote the following program, and I expect the following: When I type Red, I expect the Red LED to turn on, and so on for the others. But no LED turns on.

You can check the following video: https://www.youtube.com/watch?v=MAnAc\_t0OrM&t=1583s

```
int redPin=10, yellowPin=11, greenPin=12;

String my_Color;
String msg1="Which LED do you want to turn ON?";
String msg2="Red, Yellow or Green?";
String msg3="You chose LED:";

void setup() {
  pinMode(redPin, OUTPUT);
  pinMode(yellowPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(msg1);
  Serial.println(msg2);
  while(Serial.available()==0) {}
  my_Color=Serial.readString();
  Serial.print(msg3 );
  Serial.println(my_Color);
  Serial.println('Red', BIN);
  Serial.println('my_Color',BIN);
  if(my_Color == "Red") {
    Serial.print("Red True");
    digitalWrite(redPin,HIGH);
    digitalWrite(yellowPin,LOW);
    digitalWrite(greenPin,LOW);
  }
  if(my_Color=="Yellow") {
    digitalWrite(redPin,LOW);
    digitalWrite(yellowPin,HIGH);
    digitalWrite(greenPin,LOW);
  }
  if(my_Color=="Green") {
    digitalWrite(redPin,LOW);
    digitalWrite(yellowPin,LOW);
    digitalWrite(greenPin,HIGH);
  }
}

```

Could anyone check the sketch and correct me?

# Answer
This question originated on electronics.stackexchange.com, copying my answer from there:

There are three main areas where your system may be failing: the LEDs, the string input, and the logic evaluations. Right now it's a black box - you enter some input, and you don't see an output. But you have no idea where the system is failing between those two points. You should first narrow down to find which one the problem is. This is very good practice for learning how to debug systems in general.

Start with the string input. After you read in the string from Serial, print it back out. Verify that it matches what you entered. (I expect this to be the problem. Like I said in my comment, your string is probably being read in as "Red\r \n ". Print the string twice, and if it prints "Red" twice with a line break in between, than that is your problem. You need to run my\_Color.trim() to fix that.)

Then, check the logic evaluations. Add a Serial.print() command with some string in it after each **if** evaluation. If your program prints out the string after you enter a valid LED color, than you know that your code is executing correctly. If not, there is some difference between the my\_color String and the String you are checking it against.

Thereafter, if it is still not working then the problem is with the LEDs. I don't have your circuit so I can't tell you what to debug there.
> 3 votes

---
Tags: arduino-uno, arduino-mega
---


title: ESP32 - DeepSleep loop or not?

text:
# Question
Title: ESP32 - DeepSleep loop or not?
I'm trying to create a battery & solar-powered ESP32 for future use with sensors. It connects to Wifi, MQTT, publishes some readings and status messages and goes back to sleep. From time to time (it can happen after a few sleep cycles and sometimes after a few hundred cycles), I get 2 unexplained behaviours: 1) fails to connect to MQTT at boot, 2) fails to sleep.

Sometimes those behaviours happen simultaneously.

Is there a known issue with `deepsleep` and MQTT (using `PubSubClient`)? Most deepsleep examples I see online, all code is outside the `loop()` section - is it mandatory to be like that?

I don't share code, since it is more a general question.

Guy

**EDIT1**

1. most of `callback` was commented out, leaving only printing the incoming message.
2. LED was attached to a GPIO, generating a blink on `loop()` \- when sleep succeeds - it goes off, when it fails, it stays on. This test shows that when this "error" happens, code actually stop running, but does not enter deep sleep (power-wise).

# Answer
> Is there a known issue with deepsleep and MQTT ?

No. There may be a specific problem with the specific library you are using, but the concept of there being an issue with MQTT in general is nonsense.

> Most deepsleep example I see online, all code is outside loop()section - is it mandatory to be like that ?

No, that's just being structured and tidy with your code. Whether code is in loop or in functions that are called by loop makes no difference. It can be a lot easier to manage your code if you structure it in functions rather than dumping it all in loop.
> 1 votes

# Answer
The problem with calling `ESP.deepSleep(xx)` inside `loop()` is that watchdog is already activated there, and then a reset occurs during the sleep state.

To fix this, I used the software's own `ESP.restart()` reset technique after having written a signature to a "not init" variable, as follows:

Variable area:

```
uint16_t SleepSign __attribute__((section(".noinit"))); // Hot reset / deep sleep signature.

```

Then, at the beginning of `setup()` we write the code that tests the content of that uninitialized variable, and if it contains the signature, `ESP.deepSleep(xx)` is called. In my case I use `ESP.deepSleep(0)` because I intend for the device to reboot only on a new boot:

```
void setup()
{
     if (SleepSign == 0xdd11) ESP.deepSleep(0);
     Rest of the initialization:
     ...

Inside loop():
     ...
     if ((millis() - timeconnect) > 300*1000) {
       SleepSign = 0xdd11; // deep sleep at restart
       ESP.restart();
     }
     ...

```

This system is tested and works correctly, reducing consumption to the minimum specified by espressif. I previously tried to block watch before exiting `setup()`, but it didn't work, of course:

```
*((volatile uint32_t*) 0x60000900) &= ~(1); // Hardware WDT OFF

```

Obviously, if we are interested in using a timed deepSleep, and have the device do anything before going back to sleep, we can assign several values to the SleepSign variable to control the restart, also resetting its value before calling ESP.deepSleep(0):

```
 void setup()
 {
 if (SleepSign == 0xdd11) {
    SleepSign = 0xffff;
    ESP.deepSleep(xx);
  }
  Rest of the initialization:
  ...

```

The only drawback I find is that the esp will perform a reset before going to sleep, but I don't think that matters much.
> 2 votes

---
Tags: esp32, sleep
---


# Question
Title: Construct Strings with UTF-8 characters from data
I am printing some ASCII art to the Serial monitor from Arduino UNO, with some success. However, using string literals uses more memory than I would like. I wanted to try constructing the strings/chars from other data types so that I can manipulate the data and print the ascii art without storing it in string literals.

However, I have found that there seems to be no way to print UTF-8 characters other than from a string literal. Is this the case? Is there no way to construct a string containing characters that have numeric values that are too big for `char`?

As an example, to print "▓" works fine as a String literal but, it seams, no other way.

```
Serial.println("▓");                         // works fine
Serial.println('▓');                         // char can't store value
Serial.println(String('▓'));                 // char can't store value
Serial.println(0x2593);                      // just prints the numeric value
Serial.println((char)0x2593);                // char can't store value
Serial.println((wchar_t)0x2593);             // doesn't work
Serial.println(String(0x2593));              // doesn't work
Serial.println(String((wchar_t)0x2593));     // doesn't work

```

Similarily with write() instead of print():

```
Serial.write("▓");                  // Works fine
Serial.write('▓');                  // char can't store value
Serial.write(0x2593);               // just prints the numeric value
Serial.write((char)0x2593);         // char can't store value
Serial.write((wchar_t)0x2593);      // doesn't work

```

I also tried deriving new component strings from a string literal using `substring()` and `charAt()`. Neither works. Both produce � in the output.

`String((char)65)` constructs the string "A" from the numeric value 65. Neither `String((char)0x2593)` nor `String((wchar_t)0x2593)` produce the desired results. Is there a way to construct a string from numeric values that are too big to store in 'char'?

# Answer
> 3 votes
As you have noticed, `Serial` doesn't know how to deal with `wchar_t`. If you are building your strings algorithmically from Unicode code points, you need to convert those code points to UTF-8 for printing. I am not aware of any built-in function that does that. You may want to search the library manager for a library providing this functionality.

Alternatively, you could write the conversion yourself: it is not that complicated. For example, here is a function that converts any code point from the BMP (i.e. \< 216) to an UTF-8 string:

```
// A BMP multi-byte character, with terminating NUL byte.
struct Mbchar {
    char utf8[4];
};

// Convert a wide character to UTF-8. Only works within the BMP.
Mbchar wchar_to_utf8(wchar_t c) {
    Mbchar result;
    if (c < 128) {               // 0xxx.xxxx
        result.utf8[0] = c;
        result.utf8[1] = 0;
    } else if (c < 2048) {       // 110x.xxxx 10xx.xxxx
        result.utf8[0] = 0xc0 | (c >> 6);
        result.utf8[1] = 0x80 | (c & 0x3f);
        result.utf8[2] = 0;
    } else {                     // 1110.xxxx 10xx.xxxx 10xx.xxxx
        result.utf8[0] = 0xe0 | (c >> 12);
        result.utf8[1] = 0x80 | (c >> 6 & 0x3f);
        result.utf8[2] = 0x80 | (c & 0x3f);
        result.utf8[3] = 0;
    }
    return result;
}

```

Keep in mind that, depending on the Arduino you are using, `wchar_t` may not support characters outside the BMP. The AVR-based Arduinos definitively don't.

This function can be used like this:

```
Serial.println(wchar_to_utf8(0x2593).utf8);  // prints “▓”

```

---
Tags: serial, string, data-type, print, char
---


# Question
Title: Arduino interrupt for serial data on digital pin, that is too large for the serial buffer
I am using an Arduino Nano in combination with a NEO 6m GPS module. The GPS module is sending data, consisting of a few hundred chars, every second. Since I am communicating with my PC over the integrated serial RX and TX pins of the Arduino, I cannot use them for the sensor without being able to display anything sent from the Arduino on my PC. I am using the SoftwareSerial library to mark two digital pins as my new RX and TX to communicate with the GPS sensor.

The problem is that I have to actively listen to the RX pin at the moment the data is incoming, because otherwise data will be lost, since it's too much to be placed into the serial buffer completely. But on the other hand: I don't want to actively wait for the digital pin to receive data, so I would be in time to read it. It would be best handled with an interrupt every time the digital RX pin starts to receive data. But I read that SoftwareSerial is not compatible with this kind of interrupt, since it has a built-in interrupt itself everytime new data arrives to save it onto the buffer.

This is what I have tried:

```
#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);
String serialString;

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

  //Interrupts when a transmission begin in the RX-Pin is recognized
  attachInterrupt(digitalPinToInterrupt(4), readGpsSerialData, CHANGE);
}

void loop() {
  //processing data that takes too long to check frequently enough if data is being transmitted at the moment
  Serial.println("In Loop");
  delay(1000);
}

//Read all the incomming data once transmission started
void readGpsSerialData() {
  String serialString = "";
  while (ss.available() > 0) {
    char serialChar = ss.read();
    serialString += serialChar;
  }
  lastGpsString = serialString;
  Serial.print("Data from Interrupt: ");Serial.println(lastGpsString);
}

```

I think the problem is that my interrupt activates, not just once when the transmission starts, but every time the RX digital value changes (so a lot of times in the transmission). A data RDY value would be nice for this interrupt trigger but the GPS module does not have one.

# Answer
GPS is a really slow communication, it communicates in 9600bps and data only available once in every second. Any MCU running at much slower than an Arduino Uno running at 16MHz should be able to handle it, with a small rx buffer. If there is a problem, it is because of the user code implementation.

You didn't mention which Arduino board you are using. Arduino's implementation of `attachInterrupt()` function has quite limited *digital* pins that you could attach an interrupt to it. See the documentation. Even it can handle interrupt on pin4, the `CHANGE` means that it would be triggered in every single bit change, which is really unnecessary.

Secondly, there are a few "do and don't" for setting up an interrupt callback function, it all come down to "keep it short and simple", to have a while..loop and Serial print within an interrupt callback is one of those things that should be avoid, for that I suggest to read Nick Gammon's Interrupts.

There is a misunderstanding of "actively listen" of RX. The `Serial.available()` is a function that behave like an `onEvent()` callback internally, so it is non-block by simply doing a checking with `if(Serial.available()`, it will only blocking by putting it in a `while` loop. Furthermore, `Serial.available()` only turn from 0 to 1 when a full byte is received.

I'd suggest to not using interrupt, and make the following changes. This should provide plenty of time for handling other communication while receive GPS data stream.

```
#include <SoftwareSerial.h>

// The serial connection to the GPS module
SoftwareSerial ss(4, 3);

void setup() {
  Serial.begin(9600);   // change baudrate to 115200 to improve performance
  ss.begin(9600);
}

void loop() {
  String serialString = "";

  // this code block only execute when a character is fully received
  if (ss.available() > 0) {
    char serialChar = ss.read();
    serialString += serialChar;
    // only print the string when the `\n` is received (i.e. full GPS string)
    if (serialChar == '\n') {
      Serial.println(serialString);
    }
  }

  // there are plenty of time to handle the rest of the communication with the PC here
}

```
> 2 votes

# Answer
There are 2 aspects here.

The first is that the continuous flow of NMEA data is not THAT important. When you are ready to read, you can discard any pending input, ie flush the buffer, and start reading from the next `$` onwards.

You can also limit the number of NMEA verbs displayed (there are commands to do that), so that less information is sent to Serial.

The second aspect is that most GPS modules send data at 9,600 bauds, which is quite slow, and every second (that's what the PPS pin is for). So you read data, store the lines in a buffer, and parse the buffer. Rinse and repeat. Even an Arduino Uno should be good enough. And as I said, if there's too much data, discard and start reading again.
> 0 votes

# Answer
To avoid a buffer overflow, I would recommend increasing the communication speed on the PC side. You can easily set `Serial.begin(115200);` or even higher, as the comment in your code suggests. The PC and also the Arduino work just fine with that. That will make sure you can send out all the input from the GPS receiver much faster than new data comes in, so you shouldn't loose anything. Just make sure that you use the same value on the Arduino and the PC.
> 0 votes

---
Tags: serial, arduino-nano, interrupt, buffer
---


# Question
Title: Why does the ADC report 0 in this sketch?
This sketch always reports 0 for the ADC reading.

I think this is going to turn out to be something silly, but I cannot find the source. I've reviewed the sketch ADC lines carefully and they *seem* right, so maybe the problem with the physical connections or how I'm trying to report the ADC output or the order in which tasks are executed. The `capture_FID()` etc functions are based on the example in Section 9.2.4 of Norman Dunbar's book, *Arduino Software Internals*. The only difference is the position of `ADCSRA |= (1 << ADEN);` which I moved to right after the power up based on this answer. That did not make a difference.

```

void init();
void setup() {
  Serial.begin(115200);
  capture_FID();
}
void loop() {
}

void capture_FID() {

  volatile uint16_t ADC_output = 0;  // max value 65536

  config_ADC();
  start_ADC();
  for (int i = 1; i <= 5; i++) {
    Serial.print("\ti = ");
    Serial.print(i);
    Serial.print(" value = ");
    Serial.println(ADC_output);
  }
  stop_ADC();
}

// ADC Configuration
void config_ADC() {
  Serial.println("Configuring the ADC...");
  PRR &= ~(1 << PRADC);                                            // power up the ADC
  ADCSRA |= (1 << ADEN);                                           // enable ADC
  ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);             // slow the clock
  ADMUX = (0 << REFS1) | (1 << REFS0);                             // use 5 V internal reference
  ADMUX &= ~(1 << ADLAR);                                          // right-align the 10 bit output in 2 byte/16 bit space
  ADMUX |= (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0);  // multiplexer input; use A0
  DIDR0 |= (1 << ADC0D);                                           // disable digital input to pin A0
  ADCSRA |= (1 << ADIE);                                           // set interupt to notify data is available for further use
  ADCSRA |= (1 << ADATE);                                          // auto-trigger on
  ADCSRB = 0;                                                      // free-running mode
  delay(20);                                                       // wait for voltage to settle
}

// Start the ADC = start acquiring data
void start_ADC() {
  Serial.println("Starting the ADC...");
  ADCSRA |= (1 << ADSC);
}

// Stop the ADC = stop acquiring data
void stop_ADC() {
  Serial.println("Stopping the ADC...");
  ADCSRA |= (0 << ADSC);
}

ISR(ADC_vect) {
  volatile uint16_t ADC_output;  // max value 32767
  ADC_output = ADCW;
}

```

Hardware:

* Arduino R3
* 0.1 uF cap across GND and AREF
* PicoScope function generator is supplying a 500 Hz, 500 mV, 1 V offset signal; the negative output is wired to GND on the Arduino, the positive output is wired to A0.
* A sketch that doesn't involve free-running and auto-triggering that I found on Nick Gammon's site works fine, so the board appears to be fine. This also implies the hardware connections and scope settings are fine.

# Answer
You have *two* different variables named `ADC_output`:

* one which is local to `capture_FID()`, and is always zero (it is never assigned another value)
* one local to `ISR(ADC_vect)`, which is set but never used.

You should use only one such variable.

There are also a handful more problems in this code:

* `capture_FID()` prints multiple times the same result, without checking that new data has arrived
* access to `ADC_output` outside the ISR is not protected in a critical section
* the ADC register is called `ADC`, not `ADCW`.
* `ADCSRA |= (0 << ADSC)` is a no-op
* there is no point in declaring `init()`
* probably more, I did not read it thoroughly…
> 3 votes

---
Tags: arduino-uno, avr, adc
---


# Question
Title: Serial read multiple digits and always reading 10 at the end?
So I'm trying to make a program that allows you to enter a number in decimal and it displays it in binary, and it's going fairly well after some initial struggles (for some reason it read integers as 48 more than they are (5 read as 53)) but there's something I still don't understand, and I'm scared that it may be a hardware issue.

For some reason, I can't display two-digit numbers. For example, if I input 12, it displays 1, and THEN it displays 2. Also, to make things worse, it ALWAYS outputs 10 after I input ANY number. For example, if I input 5, it displays 5, and then ALWAYS 10.

```
    void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
  int number;
  if (Serial.available() > 0) {

    number = Serial.read();
    Serial.print("Number to display: ");
    Serial.println(number);

    if (number <= 15){
      int LEDPin = 2;
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
        for (int n = 0; n <= 4; n++){
          int binval = bitRead(number, n);
          Serial.println(binval);
          digitalWrite(LEDPin, binval);
          LEDPin++;
      }
    }
    else{
    Serial.println("Number must be less than 16!");
    }

    delay(1000);
  }
}

```

EDIT: And of course, after asking the question I re-ran the code and its AGAIN showing ints as 48 bigger than they are (5 as 53).

At this point, I'm extremely confused. Am I doing something wrong? Is this a hardware issue? What can I do?

# Answer
> 1 votes
I would suggest getting the user input with `Serial.readBytesUntil()`, store it in a `char` array, then use `itoa()` to get the integer value. Here is a modified version of your sketch.

```
char inputBuffer[5];
byte number = 0;

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {

  if (Serial.available() > 0) {

    Serial.readBytesUntil('\n', inputBuffer, 4);
    number = atoi(inputBuffer);
    Serial.print("Number to display: ");
    Serial.println(inputBuffer);

    if (number <= 15){
      int LEDPin = 2;
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      digitalWrite(5, LOW);
        for (int n = 0; n <= 4; n++){
          int binval = bitRead(number, n);
          Serial.println(binval);
          digitalWrite(LEDPin, binval);
          LEDPin++;
      }
    }
    else{
      Serial.println("Number must be less than 16!");
    }
    delay(1000);
  }
}

```

# Answer
> 1 votes
> for some reason it read integers as 48 more than they are (5 read as 53)

That's because you're not entering numbers, you're entering ASCII characters that represent numbers.

Everything you see on a computer or similar device is not really what is there. It is all translated into a form that we mere humans can see. Every number is translated into readable characters, and readable characters have to be converted into numbers.

For example, the number 165 is the characters 1 (49), 6 (54) and 5(53). When you enter that number you are sending those three individual characters.

You see the entire ASCII table here.

Another effect of sending individual characters is that you also send a marker to say "This is the end of the line". That can either be character 13 (Carriage Return), character 10 (Line Feed), or a combination of the two. You can select which is sent in the Serial Monitor.

You should really use that line ending character or combination of characters to work out how many characters there are in your number so you can convert them into a proper integer value.

Some further reading:

# Answer
> 0 votes
Regarding your "it ALWAYS outputs 10 after I input ANY number", I had the same problem using ASCII, and I think I finally figured it out. When you use Serial.println anywhere, it will output a line feed. In ASCII that is called newline and its value is 10. I have not yet figured a way to get around that.

```

byte ASCII_Number;

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

void loop() {
  Serial.println("Enter any single ASCII character:");
  while (Serial.available()==0) {}
  char ASCII_Character = Serial.read();
  ASCII_Number = (int)ASCII_Character;
  Serial.print("For your ASCII Character: ");
  Serial.print(ASCII_Character);
  Serial.print(" the ASCII Number is: [");
  Serial.print(ASCII_Number);
  Serial.println("] "); // print line always generates ASCII 10 (newline).
  //This runs the loop again with a newline for the character.
  delay (5000);
  ASCII_Number = 0;
}

```

---
Tags: arduino-uno
---


# Question
Title: DHT22 sensor reading code interprets negative values weirdly
The following code reads the DHT22 temperature and humidity values, assuming the `pin` value as the sensor's host pin.

When the temperature drops below 0°C, this code returns inadequate values in the range from -3200 to -3300 (most often the values range around -3275). When using a popular Adafruit library, the values are also incorrect. The code was not written by me, it originates from here, but the comments in the source are in Russian.

> The problem is quite common, but there was no adequate solution provided in any case. It was mentioned in the Adafruit library issues quite a few times (here, here and here (related)), and on other websites. People even reported this issue on DHT11 and DHT21 sensors.

```
// "DHTLif.h"

#pragma once
#include <Arduino.h>
#include <Firmata.h>

uint64_t readingTime;

void DHTt(const uint8_t pin) {
  if ((millis() - readingTime) > 2000) {
    unsigned char receivedDHTData[5];
    float temperature, humidity;

    #define DHT_PORT PORTD
    #define DHT_DDR DDRD
    #define DHT_PIN PIND
    #define DHT_BIT pin
    int count = 32;
    unsigned char i, j;

    ReLoad: // Restarting point for error handling
    //=============MCU send START
    DHT_DDR |= (1 << DHT_BIT); // exit
    DHT_PORT &= ~(1 << DHT_BIT); // the pin's level is low, set it to high and wake up the sensor
    delay(18); // 18 ms delay from the docs
    DHT_PORT |= (1 << DHT_BIT); // set the pin's level to low
    DHT_DDR &= ~(1 << DHT_BIT); // the pin as exit

    //=============Initialize DHT
    delayMicroseconds(50); // delay from the docs
    if (DHT_PIN & (1 << DHT_BIT)) { // DHT must return 0
      if (count != 0) {
        goto ReLoad;
        count--;
      } else {
        // send initialization error message
        Firmata.sendString("ERR;DHTt;INIT");
        return;
      }
    }

    delayMicroseconds(80);
    if (!(DHT_PIN & (1 << DHT_BIT))) { // the bus must be set to 0 after 80 ms
      if (count != 0) {
        goto ReLoad;
        count--;
      } else {
        // send weird behaviour error message
        Firmata.sendString("ERR;DHTt;BHVR");
        return;
      }
    }

    //===============Receive 40 bits of data
    while (DHT_PIN & (1 << DHT_BIT)); // wait until the bus is set to 1
    for (j = 0; j < 5; j++) { // loop for 0-4 bytes
      receivedDHTData[j] = 0;
      for (i = 0; i < 8; i++) { // receive bits and pack them into bytes
        while (!(DHT_PIN & (1 << DHT_BIT))); // wait until the bus is set to 0
        delayMicroseconds(30); // 30 ms delay from the docs
        if (DHT_PIN & (1 << DHT_BIT)) // if the pin is 1 after the delay,
          receivedDHTData[j] |= 1 << (7 - i); //set the i'th bit to 1
        while (DHT_PIN & (1 << DHT_BIT)); // wait until the bus is set to 0
      }
    }

    if ((unsigned char)(receivedDHTData[0] + receivedDHTData[1] + receivedDHTData[2] + receivedDHTData[3]) != receivedDHTData[4]) { // checksum
      Firmata.sendString("ERR;DHTt;CHSM");
      return;
    }

    temperature = (receivedDHTData[3] * 0.1) + ((receivedDHTData[2] & 0b01111111) * 25.6); // calculating temperature for DHT22
    if (receivedDHTData[2] & 0b10000000) temperature *= -1; // if the temperature is negative
    humidity = (receivedDHTData[1] * 0.1) + (receivedDHTData[0] * 25.6); //calculating humidity for DHT22

    // form the final message
    char result[32], catres[8];
    readingTime = millis();
    strcpy(result, "OK;DHTt;");

    dtostrf(temperature, 5, 2, catres);
    strcat(result, catres);
    strcat(result, ";");
    dtostrf(humidity, 5, 2, catres);
    strcat(result, catres);
    Firmata.sendString(result);
    return;
  }
}

```

The only fix I found looks really silly and it does not work, the values don't drop below zero.

```
// The temperature is a 16 bit signed integer, 10 times the actual value in degrees Celsius
int16_t temperatureTimesTen = (int16_t)((receivedDHTData[2] << 8) | receivedDHTData[3]);
float temperature = (float)(temperatureTimesTen) * 0.1f;

// The maximum possible temperature for an DHT22 is 80 degrees Celsius
if (temperature > 80) temperature = temperature - 3276.7f;

```

# Answer
Looking at the data sheet (Page 3), the DHT22 uses, unlike the DHT11 and unlike the implementation in many libraries, a standard Base-2 format for the temperature. So converting the temperature should be as easy as:

```
// The temperature is a 16 bit signed integer, 10 times the actual value in degrees Celsius
int16_t temperatureTimesTen = (int16_t)((receivedDHTData[2] << 8) | receivedDHTData[3]);
float temperature = (float)(temperatureTimesTen) * 0.1;

```

I was not able to confirm this yet (couldn't get my sensor cold enough), but your observation that the wrong values report as being in the order of -3300 point to the same conclusion.

**EDIT**

I need to correct myself. The documentation is misleading, therefore my understanding of it was incorrect. After I finally got the possibility to really test my DHT22 in negative temperatures (it's snowing outside now), I found the correct formula to be:

```
int temp = ((receivedDHTData[2] & 0x7F) << 8 | receivedDHTData[3]) * 0.1;
// if MSB = 1 we have negative temperature
temp = ((receivedDHTData[2] & 0x80) == 0 ? temp : -temp);

return temp; // in degrees celsius

```

**EDIT 2**

For this particular sensor, decoding seems to be as follows. It appears that on negative temperatures, the resolution is only 1 degree, not 0.1 degrees.

```
float temperature = 0;
int32_t temp = ((receivedDHTData[2]) << 8 | receivedDHTData[3]);
// if MSB = 1 we have negative temperature
if (temp & 0x8000)
{
    temp = temp | 0xFFFF0000; // sign-extend
    temperature = temp; // Convert to negative whole-degrees
}
else
{
    temperature = (float)temp / 10.0f;
}

```
> 0 votes

# Answer
I ran into this issue of getting -3200 values. I swapped the sensor with another one from the same vendor (tenstar robot on ali express) and the values for the 2nd sensor were normal. I put a regular thermometer next to the sensor and the reading are within a couple of degree of each other at -15c. I am supplying my sensors with 3.3 volts which in some cases can also cause issues. Might be worth trying 5 volts to see it that makes any difference.
> 0 votes

---
Tags: programming, temperature-sensor, mathematics, dht22, dht11
---


# Question
Title: How does the serial monitor know where a string terminates when we use Serial.print instead of Serial.println?
EDIT: I thought I had to parse the things coming into the program but the speed it is running at makes it indistinguishable to the eye that the word is being printed piecewise.

I am trying to create a serial monitor in rust using the serialport crate. I am using the following modification of blink code on the uno to test it:

```
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.print("HIGH");
  delay(700);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.print("LOW");
  delay(700);
}

```

with println, I am thinking of just concatenating the received buffers and printing on receiving nl or cr. The serial monitor is doing a pretty good job with how it is able to discern a string if a has ended without NL or CR on running the code. How is it doing that? Here is my code right now:

```
use std::time::Duration;
use serialport;

fn main() {
    let open_port_config = serialport::new("/dev/cu.usbmodem1201", 9600).timeout(Duration::from_secs(10));
    let open_port_result = open_port_config.open();

    let mut port = match open_port_result {
                    Ok(res) => res,
                    Err(_) => panic!("Couldn't open the port")
                };

    println!("Data bits: {}", port.data_bits().unwrap());
    println!("Flow control: {}", port.flow_control().unwrap());
    println!("Parity: {}", port.parity().unwrap());
    println!("Stop bits: {}", port.stop_bits().unwrap());

    loop {
        let mut serial_buf: [u8; 8] = [0; 8];
        port.read(&mut serial_buf[..]).expect("Found No data");
        let output = String::from_utf8(serial_buf.to_vec()).unwrap();
        println!("{:?},{:?}: {}", serial_buf, output.trim_matches('\0'), output);
    }
}

```

# Answer
The answer is: It does not know. Or, if you want to look at it in a different way: Timing and chance.

You simply never stumbled upon the case that you read the serial buffer on the PC side *in the exact moment when the Arduino is in the middle of writing to it*. That special case would be where you read and empty the buffer and output "HI" (followed by newline, because you add it in your code) on your serial monitor; then, during the next loop in your rust code, the remaining characters would be read, outputting "GH".

I'd say that you've been lucky that it always worked so far.

The better way would be to always use `println` on the Arduinos side; and on the PCs side: the rust function to "read until newline" from a serial connection (I'm guessing it exists because it does exist in other standard libraries; I never worked with rust before). This way, you'll have in-band signalling for "the next data block begins HERE".
> 0 votes

---
Tags: arduino-uno, serial
---


title: ESP32: nRF24L01 receives no data

text:
# Question
Title: ESP32: nRF24L01 receives no data
Using two, nRF24L01 with two, ESP32 DEVKIT V1. Trying to setup RF24 Library example, "Getting Started". Able to transmit on both nodes, however, there is no payload received when switching to receive while transmitting on both nodes.

**SPI pins used:**
MOSI = GPIO23,
MISO = GPIO19,
SCK = GPIO18,
CE = GPIO21,
CSN = GPIO5,
IRQ = No connection,
Vcc = 5.0 V using piggyback adapter with 3.3 V regulator,
GND = Ground.

Are the SPI pins used correctly for the ESP32 DEVKIT V1?

```
<script src="https://gist.github.com/Tech500/b57d4d356baaec48adc41196117c02aa.js"></script>
nRF24L01 Project for use with ESP32 DEVKIT V1
Details.txt
//Getting Started exammple:  Details Radio_0 and Radio_1.

RF24/examples/GettingStarted
Which radio is this? Enter '0' or '1'. Defaults to '0'
radioNumber = 0
*** PRESS 'T' to begin transmitting to the other node
SPI Frequency       = 10 Mhz
Channel         = 76 (~ 2476 MHz)
Model           = nRF24L01+
RF Data Rate        = 1 MBPS
RF Power Amplifier  = PA_LOW
RF Low Noise Amplifier  = Enabled
CRC Length      = 16 bits
Address Length      = 5 bytes
Static Payload Length   = 4 bytes
Auto Retry Delay    = 1500 microseconds
Auto Retry Attempts = 15 maximum
Packets lost on
    current channel = 0
Retry attempts made for
    last transmission   = 0
Multicast       = Disabled
Custom ACK Payload  = Disabled
Dynamic Payloads    = Disabled
Auto Acknowledgment = Disabled
Primary Mode        = TX
TX address      = 0x65646f4e31
pipe 0 ( open ) bound   = 0x65646f4e31
pipe 1 ( open ) bound   = 0x65646f4e32
pipe 2 (closed) bound   = 0xc3
pipe 3 (closed) bound   = 0xc4
pipe 4 (closed) bound   = 0xc5
pipe 5 (closed) bound   = 0xc6

-------------------------------------

radioNumber = 1
*** PRESS 'T' to begin transmitting to the other node
SPI Frequency       = 10 Mhz
Channel         = 76 (~ 2476 MHz)
Model           = nRF24L01+
RF Data Rate        = 1 MBPS
RF Power Amplifier  = PA_LOW
RF Low Noise Amplifier  = Enabled
CRC Length      = 16 bits
Address Length      = 5 bytes
Static Payload Length   = 4 bytes
Auto Retry Delay    = 1500 microseconds
Auto Retry Attempts = 15 maximum
Packets lost on
    current channel = 0
Retry attempts made for
    last transmission   = 0
Multicast       = Disabled
Custom ACK Payload  = Disabled
Dynamic Payloads    = Disabled
Auto Acknowledgment = Disabled
Primary Mode        = RX
TX address      = 0x65646f4e32
pipe 0 (closed) bound   = 0x65646f4e32
pipe 1 ( open ) bound   = 0x65646f4e31
pipe 2 (closed) bound   = 0xc3
pipe 3 (closed) bound   = 0xc4
pipe 4 (closed) bound   = 0xc5
pipe 5 (closed) bound   = 0xc6
Radio_0.ino

```

RF24 Library example "Getting Started":

```
/*
 * See documentation at https://nRF24.github.io/RF24
 * See License information at root directory of this library
 * Author: Brendan Doherty (2bndy5)
 */

/**
 * A simple example of sending data from 1 nRF24L01 transceiver to another.
 *
 * This example was written to be used on 2 devices acting as "nodes".
 * Use the Serial Monitor to change each node's behavior.
 *
 *  TX Code --Radio 0
 */

/*
  Coded for a ESP32 DEVKIT V1 board type to make use of a pair of
  nRF24L01+ 2.4 GHz. Transceivers
  SPI Pins used MOSI = 23, CE = 21, MSIO = 19, SCK = 18, CSN = 4
  This code is for Radio 0.
  William Lucid
*/

#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define CE_PIN 21
#define CSN_PIN 5

// instantiate an object for the nRF24L01 transceiver
RF24 radio(CE_PIN, CSN_PIN);

// Let these addresses be used for the pair
uint8_t address[][6] = { "1Node", "2Node" };
// It is very helpful to think of an address as a path instead of as
// an identifying device destination

// to use different addresses on a pair of radios, we need a variable to
// uniquely identify which address this radio will use to transmit
bool radioNumber = 0;  // 0 uses address[0] to transmit, 1 uses address[1] to transmit

// Used to control whether this node is sending or receiving
bool role = true;  // true = TX role, false = RX role

// For this example, we'll be using a payload containing
// a single float number that will be incremented
// on every successful transmission
float payload = 0.0;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // some boards need to wait to ensure access to serial over USB
  }

  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);

  // initialize the transceiver on the SPI bus
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {}  // hold in infinite loop
  }

  //radio.setAutoAck(false);

  // print example's introductory prompt
  Serial.println(F("RF24/examples/GettingStarted"));

  // To set the radioNumber via the Serial monitor on startup
  Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
  while (!Serial.available()) {
    // wait for user input
  }
  char input = Serial.parseInt();
  radioNumber = input == 1;
  Serial.print(F("radioNumber = "));
  Serial.println((int)radioNumber);

  // role variable is hardcoded to RX behavior, inform the user of this
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  // Set the PA Level low to try preventing power supply related problems
  // because these examples are likely run with nodes in close proximity to
  // each other.
  radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX is default.

  // save on transmission time by setting the radio to only transmit the
  // number of bytes we need to transmit a float
  radio.setPayloadSize(sizeof(payload));  // float datatype occupies 4 bytes

  // set the TX address of the RX node into the TX pipe
  radio.openWritingPipe(address[radioNumber]);  // always uses pipe 0

  // set the RX address of the TX node into a RX pipe
  radio.openReadingPipe(1, address[!radioNumber]);  // using pipe 1

  // additional setup specific to the node's role
  if (role) {
    radio.stopListening();  // put radio in TX mode
  } else {
    radio.startListening();  // put radio in RX mode
  }

  // For debugging info
  printf_begin();  // needed only once for printing details
  // radio.printDetails();       // (smaller) function that prints raw register values
  radio.printPrettyDetails();  // (larger) function that prints human readable data

}  // setup

void loop() {
  if (role) {
    // This device is a TX node

    unsigned long start_timer = micros();               // start the timer
    bool report = radio.write(&payload, sizeof(float)); // transmit & save the report
    unsigned long end_timer = micros();                 // end the timer

    if (report) {
      Serial.print(F("Transmission successful! "));  // payload was delivered
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // print the timer result
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);  // print payload sent
      payload += 0.01;          // increment float payload
    } else {
      Serial.println(F("Transmission failed or timed out"));  // payload was not delivered
    }

    // to make this example readable in the serial monitor
    delay(1000);  // slow transmissions down by 1 second

  } else {
    // This device is a RX node

    uint8_t pipe;
    if (radio.available(&pipe)) {              // is there a payload? get the pipe number that recieved it
      uint8_t bytes = radio.getPayloadSize();  // get the size of the payload
      radio.read(&payload, bytes);             // fetch payload from FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);  // print the size of the payload
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);  // print the pipe number
      Serial.print(F(": "));
      Serial.println(payload);  // print the payload's value
    }
  }  // role

  if (Serial.available()) {
    // change the role via the serial monitor

    char c = toupper(Serial.read());
    if (c == 'T' && !role) {
      // Become the TX node

      role = true;
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      radio.stopListening();

    } else if (c == 'R' && role) {
      // Become the RX node

      role = false;
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
      radio.startListening();
    }
  }

}  // loop

```

Radio\_1.ino:

```
/*
 * See documentation at https://nRF24.github.io/RF24
 * See License information at root directory of this library
 * Author: Brendan Doherty (2bndy5)
 */

/**
 * A simple example of sending data from 1 nRF24L01 transceiver to another.
 *
 * This example was written to be used on 2 devices acting as "nodes".
 * Use the Serial Monitor to change each node's behavior.
 */

 /*
  Coded for a ESP32 DEVKIT V1 board type to make use of a pair of
  nRF24L01+ 2.4 GHz. Transceivers
  SPI Pins used MOSI = 23, CE = 21, MSIO = 19, SCK = 18, CSN = 4
  This code is for Radio 1.

*/

#include <SPI.h>
#include "printf.h"
#include "RF24.h"

#define CE_PIN  21
#define CSN_PIN  5

// instantiate an object for the nRF24L01 transceiver
RF24 radio(CE_PIN, CSN_PIN);

// Let these addresses be used for the pair
uint8_t address[][6] = { "1Node", "2Node" };
// It is very helpful to think of an address as a path instead of as
// an identifying device destination

// to use different addresses on a pair of radios, we need a variable to
// uniquely identify which address this radio will use to transmit
bool radioNumber = 1;  // 0 uses address[0] to transmit, 1 uses address[1] to transmit

// Used to control whether this node is sending or receiving
bool role = false;  // true = TX role, false = RX role

// For this example, we'll be using a payload containing
// a single float number that will be incremented
// on every successful transmission
float payload = 0.0;

void setup() {

  Serial.begin(115200);
  while (!Serial) {
    // some boards need to wait to ensure access to serial over USB
  }

  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);

  // initialize the transceiver on the SPI bus
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {}  // hold in infinite loop
  }

  radio.setAutoAck(false);

  // print example's introductory prompt
  Serial.println(F("RF24/examples/GettingStarted"));

  // To set the radioNumber via the Serial monitor on startup
  Serial.println(F("Which radio is this? Enter '0' or '1'. Defaults to '0'"));
  while (!Serial.available()) {
    // wait for user input
  }
  char input = Serial.parseInt();
  radioNumber = input == 1;
  Serial.print(F("radioNumber = "));
  Serial.println((int)radioNumber);

  // role variable is hardcoded to RX behavior, inform the user of this
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  // Set the PA Level low to try preventing power supply related problems
  // because these examples are likely run with nodes in close proximity to
  // each other.
  radio.setPALevel(RF24_PA_LOW);  // RF24_PA_MAX is default.

  // save on transmission time by setting the radio to only transmit the
  // number of bytes we need to transmit a float
  radio.setPayloadSize(sizeof(payload));  // float datatype occupies 4 bytes

  // set the TX address of the RX node into the TX pipe
  radio.openWritingPipe(address[radioNumber]);  // always uses pipe 0

  // set the RX address of the TX node into a RX pipe
  radio.openReadingPipe(1, address[!radioNumber]);  // using pipe 1

  // additional setup specific to the node's role
  if (role) {
    radio.stopListening();  // put radio in TX mode
  } else {
    radio.startListening();  // put radio in RX mode
  }

  // For debugging info
  printf_begin();             // needed only once for printing details
  // radio.printDetails();       // (smaller) function that prints raw register values
  radio.printPrettyDetails(); // (larger) function that prints human readable data

}  // setup

void loop() {

  if (role) {
    // This device is a TX node

    unsigned long start_timer = micros();                // start the timer
    bool report = radio.write(&payload, sizeof(float));  // transmit & save the report
    unsigned long end_timer = micros();                  // end the timer

    if (report) {
      Serial.print(F("Transmission successful! "));  // payload was delivered
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);  // print the timer result
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);  // print payload sent
      payload += 0.01;          // increment float payload
    } else {
      Serial.println(F("Transmission failed or timed out"));  // payload was not delivered
    }

    // to make this example readable in the serial monitor
    delay(1000);  // slow transmissions down by 1 second

  } else {
    // This device is a RX node

    uint8_t pipe;
    if (radio.available(&pipe)) {              // is there a payload? get the pipe number that recieved it
      uint8_t bytes = radio.getPayloadSize();  // get the size of the payload
      radio.read(&payload, bytes);             // fetch payload from FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);  // print the size of the payload
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);  // print the pipe number
      Serial.print(F(": "));
      Serial.println(payload);  // print the payload's value
    }
  }  // role

  if (Serial.available()) {
    // change the role via the serial monitor

    char c = toupper(Serial.read());
    if (c == 'T' && !role) {
      // Become the TX node

      role = true;
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      radio.stopListening();

    } else if (c == 'R' && role) {
      // Become the RX node

      role = false;
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));
      radio.startListening();
    }
  }

}  // loop

```

Video confirming transmission; both radios

# Answer
SPI pins are correct for ESP32 DEVKIT V1; I have it both transmitting and receiving now.

I swapped out all Dupont wiring longer than 10 cm, changed the channel with the `radio.setChannel` function to 125 on both transmitter and receiver, and added a 100 μF, 16 V electrolytic capacitor between the 5 V rail and ground.

```
Transmission successful! Time to transmit = 403 us. Sent: 5.96
Transmission successful! Time to transmit = 403 us. Sent: 5.97
Transmission successful! Time to transmit = 403 us. Sent: 5.98
Transmission successful! Time to transmit = 403 us. Sent: 5.99
Transmission successful! Time to transmit = 403 us. Sent: 6.00
Transmission successful! Time to transmit = 403 us. Sent: 6.01
Transmission successful! Time to transmit = 403 us. Sent: 6.02
Transmission successful! Time to transmit = 403 us. Sent: 6.03
Transmission successful! Time to transmit = 403 us. Sent: 6.04

Received 4 bytes on pipe 1: 6.25
Received 4 bytes on pipe 1: 6.26
Received 4 bytes on pipe 1: 6.27
Received 4 bytes on pipe 1: 6.28
Received 4 bytes on pipe 1: 6.29
Received 4 bytes on pipe 1: 6.30

```

Code Gists for nRF24L01, transmit and receive radios
> 1 votes

---
Tags: esp32, nrf24l01+
---


# Question
Title: Can Vin of ESP handle many voltage sensors and relays?
My project is Charging Battery via Solar and Piezoelectric sensor while also getting the Realtime Voltage of the Battery, Capacitor, and Solar.

I want to use Vin as the source to get 5V because ESP8266 NodeMCU only has 3.3V output.

As the diagram shows, can it power 3 Voltage sensors and 2 Relays? or should i use an external power source?

Ps: The solar is the 'normally closed'

# Answer
> 1 votes
Vin is for powering the ESP via the onboard voltage regulator which converts Vin to 3.3V for the ESP. It's not a source of 5V unless connected via USB.

---
Tags: esp8266, sensors, nodemcu, relay, solar
---


# Question
Title: How do I use RFID-RC522 with an Arduino?
I am working on a project for my local Makerspace, we have limited budget so I was hoping to use the RFID-RC522 el'cheap'o RFID/NFC readers on eBay, I received a couple of SPI based boards, they work, however the code examples for them are limited.

I have found several different libraries and settled on this one: https://github.com/ljos/MFRC522

The trouble is that all the code available online seem to spawn from some Chinese guys Python code that people have translated, and hacked into an Arduino library.

The code works, but Mifare cards are meant to have 4, 7 or 10 byte UIDs and the example/library is returning a 5 byte serial number.

There is no documentation and the NXP datasheet is incomprehensible... Additionally it seems to work with most cards, but it doesn't work with Mastercard PayWave cards which conform to the ISO 14443 standard. The more expensive RDM880 reader which is based on the MFRC500 works fine and has a nice library but the cost makes the implementation impossible.

So, can someone help me to get this NXP MFRC522 based unit reading the UID from all ISO 14443 cards.

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

#define RFID_SS  10
#define RFID_RST 5

MFRC522 rfid( RFID_SS, RFID_RST );

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

void loop() {
  byte data[MAX_LEN];
  byte uid[5];

  if ( rfid.requestTag( MF1_REQIDL, data ) == MI_OK ) {
    if ( rfid.antiCollision( data ) == MI_OK ) {
      memcpy( uid, data, 5 );
      for ( int i = 0; i < 5; i++ ) {
        Serial.print( uid[i], HEX );
        Serial.print( ' ' );
      }
      Serial.println();
    }
  }
}

```

# Answer
> 6 votes
Sorry, but I must disagree with your *'NXP datasheet is incomprehensible'*. From the FIRST PAGE of the MFRC522 datasheet:

***'Remark: The MFRC522 supports all variants of the MIFARE Mini, MIFARE 1K, MIFARE 4K, MIFARE Ultralight, MIFARE DESFire EV1 and MIFARE Plus RF identification protocols'***

**Here** it says the MFRC522 covers just a part of ISO/IEC 14443. The following are missing fron the NXP RC522:

**\*MIFARE DESFire EV1** (includes AES encryption)

**MIFARE DESFire EV2** (includes MIsmartApp, Transaction MAC, Unlimited Applications MIFARE Plus drop-in replacement for MIFARE Classic with certified security level (AES 128 based))

***MIFARE SAM AV2*** (secure access module that provides the secure storage of cryptographic keys and cryptographic functions)\*

These are probably the ones used in bank cards. Again, from the FIRST PAGE of the MFRC500 datasheet:

***'All protocol layers of the ISO/IEC 14443 A are supported.'***

You'll have to plow through all the different MIFARE / ISO/IEC 14443 specs to find out how many ID bytes there are for the different types (I suspect diferent types return a different quantity of bytes).

So, basically, you're screwed. Spring for the expensive MFRC500-based reader. I assume that with the higher cost you also get a high-class API, documentation and examples or even (gasp!) tech support.

Cheers

# Answer
> 1 votes
The MFRC522::requestTag() returns the card type in the first two bytes of the 2nd parameter (*data* in your example above). You will need to look at this value to determine which sort of card it is. Use this information to print out the required *N* bytes of ID.

At a pinch, you could dump out the full 16 bytes (MAX\_LEN), and test them with your various card types to see which bytes are changing in a deterministic manner, thus allowing you to determine the correct length of the ID.

And in case it saves you some time, if you call that library's self-test functions - getFirmwareVersion() and digitalSelfTestPass(); it's necessary to call MFRC522::begin() again, otherwise it's not possible to read RFID IDs (at the time of writing of course.)

# Answer
> 1 votes
Try using the most popular one.

https://github.com/miguelbalboa/rfid

This is working for me. It returns the uID as what you desire. Just remove the other functions just the getting of the uid from its example.

# Answer
> 0 votes
The fifth byte from the RC522 is just a checksum.

For instance, a possible return value (taken from https://github.com/miguelbalboa/rfid/issues/604#issuecomment-1885042556 ) is:

8B 65 66 B9 31

and if you do the binary xor of the first four numbers, you get precisely the fifth:

```
In [1]: hex(int("8B", 16)^int("65", 16)^int("66", 16)^int("B9", 16))[2:]
Out[1]: '31'

```

(Indeed, if you compare the first four bytes from the RC522 with the four bytes from the other reader, they should coincide)

---
Tags: rfid
---


title: Send data through SPI with DMA

text:
# Question
Title: Send data through SPI with DMA
I need to send data as fast as possible from an Arduino DUE to an extern DAC. To do so I use DMA & SPI and I want DMA to fetch data from the memory and send it to the SPI which will just relay it via its Master Output Slave input. So far I did a DMA transfer from a variable to another, woked perfectly. I'm using the same code but change the address as SPI\_TDR (Transmit Data Register), unfortunatly it's not working. I guess the address is not good but if so what should I do ?

Here is my code :

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

#define DMA_CH 0         //N° Canal du DMA
#define DMA_BUF_SIZE 32  //Taille mémoire DMA

uint32_t g_dma_buf2[DMA_BUF_SIZE];

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

  SPI0->SPI_WPMR = 0x53504900;             //Protection key
  SPI0->SPI_IDR = 0x0000070F;              //Desactivation interrupts
  SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS;  //SPI master
}

void loop() {
  Serial.println("+++++");
  pmc_enable_periph_clk(ID_DMAC);

  uint32_t i;
  uint32_t cfg;
  dma_transfer_descriptor_t desc;

  for (i = 0; i < DMA_BUF_SIZE; i++) {
    g_dma_buf2[i] = i;
    Serial.print(g_dma_buf2[i]);
  }
   Serial.println();

  dmac_init(DMAC);
  dmac_set_priority_mode(DMAC, DMAC_PRIORITY_ROUND_ROBIN);
  dmac_enable(DMAC);
  cfg = DMAC_CFG_SOD_ENABLE | DMAC_CFG_AHB_PROT(1) | DMAC_CFG_FIFOCFG_ALAP_CFG;  //Config registre CFG
  dmac_channel_set_configuration(DMAC, DMA_CH, cfg);

  desc.ul_source_addr = (uint32_t)g_dma_buf2;
  desc.ul_destination_addr = SPI0->SPI_TDR;
  desc.ul_ctrlA = DMAC_CTRLA_BTSIZE(DMA_BUF_SIZE) | DMAC_CTRLA_SRC_WIDTH_WORD | DMAC_CTRLA_DST_WIDTH_WORD;
  desc.ul_ctrlB = DMAC_CTRLB_SRC_DSCR_FETCH_DISABLE | DMAC_CTRLB_DST_DSCR_FETCH_DISABLE | DMAC_CTRLB_FC_MEM2MEM_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_DST_INCR_FIXED;
  desc.ul_descriptor_addr = 0;

  SPI_Enable(SPI0);
  dmac_channel_multi_buf_transfer_init(DMAC, DMA_CH, &desc);
  dmac_channel_enable(DMAC, DMA_CH);
  Serial.println("*****");

  while (!dmac_channel_is_transfer_done(DMAC, DMA_CH)) { Serial.print('X'); }
Se
  Serial.print("SR : "); Serial.println(SPI0->SPI_SR, HEX);
  Serial.print("TDR : "); Serial.println(SPI0->SPI_TDR, HEX);
  Serial.print("PSR : "); Serial.println(PIOA->PIO_PSR, HEX);   //PIO_SODR
  Serial.print("OSR : "); Serial.println(PIOA->PIO_OSR, HEX);
  Serial.println(DMAC->DMAC_CH_NUM[0].DMAC_SADDR , HEX);
  Serial.println(DMAC->DMAC_CH_NUM[0].DMAC_DADDR, HEX);
  Serial.println("-----");
}

```

I use mainly this example : https://ww1.microchip.com/downloads/en/Appnotes/Atmel-42291-SAM3A-3U-3X-4E-DMA-Controller-DMAC\_ApplicationNote\_AT07892.pdf#\_OPENTOPIC\_TOC\_PROCESSING\_d91e3076 And here is the datasheet of the µc : https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A\_Datasheet.pdf

You can see at the bottom of my code sevral prints, from them I had many idea : does the PIO could block the data ? Does the address PIO\_PA26A\_SPI0\_MOSI could work ? Could the SPI block the data because conditions are not met ?

Any idea is welcomed, I'm on this for some time now.

Edit : SPI is not an necessity, the idea is to send data without length limit (unlike UART). I'm considering using SSC.

# Answer
I managed to solve it but not with SPI, I use the SSC of the µcontroller (which does I²S and uses DMA automatically) :

```
uint32_t liste[] PROGMEM = { 0x8F66F1, 0x0, 0xAAAAAB };  //Data to send
#define DMA_BUF_SIZE (sizeof(liste) / sizeof(liste[0]))  //Size DMA buffer

uint32_t i;

void setup() {
  uint clk_div = 0x90;  //Clock divider wanted
  clk_div = (clk_div / 24) / DMA_BUF_SIZE;
  clk_div = floor(clk_div + 0.5);
  clk_div = clk_div * 24 * DMA_BUF_SIZE;  //Clock divider adjusted -> MCK/2*clk_div

  PMC->PMC_WPMR = 0x504D4300;                                    //Desactivation protection PMC
  PMC->PMC_PCER0 = (1 << ID_SSC);                                //Activation SSC clock
  PMC->PMC_SCER |= 0x100;                                        //Activation clock
  PIOA->PIO_WPMR = 0x50494F00;                                   //Desactivation protection Port I/O A
  PIOA->PIO_PDR = PIO_PDR_P14 | PIO_PDR_P15 | PIO_PDR_P16;       //I/O controlled by the peripheral
  PIOA->PIO_ABSR |= PIO_PA14B_TK | PIO_PA15B_TF | PIO_PA16B_TD;  //Assignation of I/O to SSC

  SSC->SSC_CR = SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST;                                                     //Desactivation and reset SSC
  SSC->SSC_WPMR = 0x53534300;                                                                                //Desactivation protection SSC
  SSC->SSC_IDR = 0xFFFFFFFF;                                                                                //Desactivation Interrupts
  SSC->SSC_IER = 0x00000000;                                                                                //Desactivation Interrupts bis
  SSC->SSC_CMR = clk_div;                                                                                //Clock management
  SSC->SSC_TFMR = SSC_TFMR_DATLEN(0x18) | SSC_TFMR_MSBF | SSC_TFMR_DATNB(0);                                    //Data transfert management
  SSC->SSC_TCMR = SSC_TCMR_CKS_MCK | SSC_TCMR_CKO_CONTINUOUS | SSC_TCMR_START_CONTINUOUS | SSC_TCMR_STTDLY(0);  //Clock during transfert management
  SSC->SSC_CR = SSC_CR_TXEN;                                                                                //Activation transmission SSC
}

void loop() {
  for (i = 0; i < DMA_BUF_SIZE; i++) {
    ssc_write((Ssc*)SSC, (uint32_t)liste[i]);  //Transmission SSC
  }
}

```

In case someone try the same thing.
> 2 votes

# Answer
I believe I have gotten this to work the way you intended, without SSI. Bits of this code have been borrowed from an SD Card library (https://github.com/openbci-archive/OpenBCI\_8bit/blob/master/OpenBCI\_8bit\_SDfat\_Library/SdFat/SdSpiSAM3X.cpp, around line 110). I am trying to run a TFT using a "framebuffer," but in order to do so I need DMA working with SPI.

In your original source, it appears you are missing a few things in `cfg`. According to the aforementioned code listing, `cfg` should look something like `DMAC_CFG_DST_PER(1) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD_ENABLE | DMAC_CFG_AHB_PROT(1) | DMAC_CFG_FIFOCFG_ALAP_CFG`. Per the datasheet, `DST_PER` must be set to one of the DMA channels seen on page 339, table 22-2. In this case, Channel 1 is used, as it corresponds to SPI0\_TX. Likewise, you appear to be missing DMAC\_CFG\_DST\_H2SEL for hardware handshaking. There's likely a few other things I'm not pointing out, as I had a fair amount of trouble with this too.

TL;DR The following code should do the trick for a basic DMA transfer from a buffer:

```
#include "sam.h"

#define CLOCK_SPEED 84000000

void setup_spi()
{
    PMC->PMC_PCER0 |= (1 << ID_PIOA); // Enable PIOA

    PIOA->PIO_ODR |= PIO_PA25;      // MISO Pin - Input
    PIOA->PIO_PDR |= PIO_PA25;
    PIOA->PIO_ABSR &= ~(PIO_PA25);  // MISO Pin - (A) Peripheral

    PIOA->PIO_OER |= PIO_PA26;      // MOSI Pin - Output
    PIOA->PIO_PDR |= PIO_PA26;
    PIOA->PIO_ABSR &= ~(PIO_PA26);  // MOSI Pin - (A) Peripheral

    PIOA->PIO_OER |= PIO_PA27;      // SCLK Pin - Output
    PIOA->PIO_PDR |= PIO_PA27;
    PIOA->PIO_ABSR &= ~(PIO_PA27);  // SCLK Pin - (A) Peripheral

    PIOA->PIO_OER |= PIO_PA28;      // CS Pin 0 - Output
    PIOA->PIO_PDR |= PIO_PA28;
    PIOA->PIO_ABSR &= ~(PIO_PA28);  // CS Pin 0 - (A) Peripheral
    PIOA->PIO_PUER |= PIO_PA28;

    // Disable the SPI to configure it
    SPI0->SPI_CR |= SPI_CR_SPIDIS;

    // SPI0 Setup --------------
    PMC->PMC_PCER0 = (1 << ID_SPI0);        // Enable SPI0 Clock

    // Master Mode, Fixed Peripheral Mode, Mode fault detection disabled, Fixed peripheral modes
    SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_MODFDIS;

    // Mode and Clock           Clock Freq Calculation
    SPI0->SPI_CSR[0] |= SPI_CSR_NCPHA | (((int8_t)(CLOCK_SPEED / 1000000)) << 8);       // Need to stick clock calculation in byte 2

    // 8 bits per transfer
    SPI0->SPI_CSR[0] |= SPI_CSR_BITS_8_BIT;

    SPI0->SPI_CR |= SPI_CR_SPIEN;           // Enable SPI0

}

uint8_t pixbuf[] = "This is a test!"; // Buffer to be transmitted

void setup_dma()
{
    PMC->PMC_PCER1 |= (1 << (ID_DMAC - 32)); // Turn on DMA Controller Clock (?)

    DMAC->DMAC_EN = 0; // Disable DMA Controller

    DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_ROUND_ROBIN; // Set arbitration method

    DMAC->DMAC_EN = 1; // Enable DMA Controller

    DMAC->DMAC_CHDR = DMAC_CHDR_DIS0; // Disable DMA Channel 0

    DMAC->DMAC_CH_NUM[0].DMAC_SADDR = (uint32_t)pixbuf; // Set src buffer
    DMAC->DMAC_CH_NUM[0].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR; // Set dst buffer
    DMAC->DMAC_CH_NUM[0].DMAC_DSCR = 0x0;

    DMAC->DMAC_CH_NUM[0].DMAC_CTRLA = DMAC_CTRLA_DST_WIDTH_BYTE | DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_BTSIZE(0x10); // Set src/dest bit width (8 bits) and set buffer size to 16
    DMAC->DMAC_CH_NUM[0].DMAC_CTRLB = DMAC_CTRLB_DST_INCR_FIXED | DMAC_CTRLB_SRC_INCR_INCREMENTING | DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_SRC_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC;

    DMAC->DMAC_CH_NUM[0].DMAC_CFG = DMAC_CFG_DST_PER(1) | DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD_ENABLE | DMAC_CFG_AHB_PROT(1) | DMAC_CFG_FIFOCFG_ALAP_CFG; // Configure DMA Controller

    DMAC->DMAC_EBCISR; // Read interrupt register to clear interrupt flags

    DMAC->DMAC_CHER = DMAC_CHER_ENA0; // Enable DMA Channel 0
}

int main(void)
{
    /* Initialize the SAM system */
    SystemInit();

    setup_dma();
    setup_spi();
    while (!(DMAC->DMAC_CHSR & DMAC_CHSR_ENA0 << 0));
    uint32_t dma_status;

    dma_status = DMAC->DMAC_EBCISR;
    //SPI0->SPI_TDR = 'a'; // Write dummy out

    /* Replace with your application code */
    while (1)
    {
    }
}

```

Hope this helps.
> 0 votes

---
Tags: spi, arduino-due
---


# Question
Title: Why does an ESP01 WiFi module reset when it's connected to a DC motor/water pump?
When I connect an ESP01 WiFi module and water pump in a parallel circuit to an Arduino Uno's 5 V pin, the ESP01 stops working.

The ESP01's built-in LED starts blinking chaotically and the serial monitor outputs trash logs like these:

```
`��PA���PCA��B��PCA��B�Z-
T���B�������|��B��P�

�D  �'�VB������P�

 �`

```

Note that I don't connect the ESP01 to WiFi: I just power it on and observe its behavior, so the ESP-01 shouldn't consume peak voltage and current.

* Water pump parameters:
Voltage: 3-5 V DC
Current: 100-200 mA
* ESP-01S parameters:
Voltage: 3 V to 3.6 V
Current: 70-170 mA
* Arduino Uno parameters connected via USB to my laptop:
Voltage: 5 V
Current: 500 mA

Circuit diagram:

I know that an ESP01 shouldn't operate on 5 V and that a voltage regulator should be used, but I omitted it for test purposes and example simplicity.

# Answer
The abs. max. supply voltage for the ESP-01s is 3.6 V; leaving out the voltage regulator and using 5 V for its power supply will likely have killed or at least damaged it.

Also, the water pump needs a flyback diode, and it would be a good idea to supply the water pump from a separate power supply, and not from the Uno's 5 V pin; the motor's (start-up) current may be more than the Uno can handle, and the motor will introduce noise in the wrong places.

The quoted 200 mA is the *running current* of the pump motor; *start-up current* will be about equal to the stall current and *much higher*. This will drop the voltage and crash the ESP01.

You may want to google something like "powering water pump from arduino start up current" and read about how it should be done; you're not the first with this problem.
> 4 votes

---
Tags: arduino-uno, esp8266, motor
---


title: ATTiny85 pin definitions

text:
# Question
Title: ATTiny85 pin definitions
I have been tearing my hair out on and off for two weeks trying to figure out pin definitions for the ATTiny85 in PlatformIO. My wiring is basically this:

My sketch:

```
#include <Arduino.h>
#include <avr/io.h>

#define WIPER PB2

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

void loop()
{
  int wiper_raw = analogRead(WIPER);
  int wiper = map(wiper_raw, 13, 1024, 0, 255);
  // show the actual value, probably not relevant to the question

  delay(100);
}

```

(Showing the actual value is done by sending the mapped value over to a neopixel stick on the red channel, so basically turning the knob turns the stick from all the way off to brighter and brighter output of red.) The pot is connected to what should be physical pin 3, also known as PB4, also known as Arduino Pin 4, also known as ADC2, etc etc. (Using https://nerdytechy.com/wp-content/uploads/2021/01/attiny85-guide-pinout.png as a guide but it's not any different from any other pinout listing I've seen.)

In the sketch I'm referencing PB2, which VSCode tells me evaluates to `2`. That's physical pin 7. When I plugged the pot signal pin into pin 7, I got no response when manipulating the dial. So I started plugging it into all the other pins (except VCC, GND, and RESET) and the very last one I tried, pin 3, was the one that reacted to the changes on the pot.

No pinout guide I've ever seen lists PB2 on physical pin 3. What am I doing wrong?

# Answer
> 3 votes
The macros such as `PB2` are defined in the avr-libc for accessing the bits of the raw I/O ports, with statements such as

```
PORTB |= _BV(PB2);  // set PB2 as HIGH

```

They do not uniquely identify as pin: if you have more than one port (say, on an Uno), both `PB2` and `PC2` are equal to 2.

If you use the Arduino core functions, you should not use these macros. Instead, use the plain numbers 0, 1... with `digitalRead()` and `digitalWrite()`, and the macros `A0`, `A1`... with `analogRead()`. Alternatively, with `analogRead()`, you can use the raw analog pin numbers 0, 1, which are interpreted as synonyms of `A0`, `A1`...

Writing something like

```
analogRead(PB2);

```

is confusing, because you are using the avr-libc macro `PB2` in the wrong context. Furthermore, since this is the same as `analogRead(2);`, the Arduino core interprets it as equivalent to

```
analogRead(A2);

```

As the pinout image shows, Arduino pin `A2` is the same as ADC2, PB4 and physical pin 3.

---
Tags: attiny85, platformio
---


title: I can't connect a microSD card

text:
# Question
Title: I can't connect a microSD card
I can’t connect a microSD card to either the Arduino or the ESP32. It needs to be connected to the ESP32; I just tested it on the Arduino to see if it works at all.

Equipment: ESP32 devkit v1, Arduino Nano, MicroSD card adapter, MicroSD card SanDisk 64gb eXFat.

Software: Arduino IDE, library SdFat (version: 2.2.2). The sketch is an example from the sdfat library - (sdinfo).

Connection to pin: SD adapter pin - CS, SCK, MOSI, MISO, VCC, GND
Arduino to SD Adapter - (CS, D10) (SCK, D13) (MOSI, D11) (MISO, D12) (VCC, +5V) (GND, GND)
ESP32 to SD Adapter - (CS, D27) (SCK, D14) (MOSI, D12) (MISO, D13) (VCC, VIN) (GND, GND)

Result ESP32:

```
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5828
entry 0x400806ac

```

Result Arduino:

```
SdFat version: 2.2.2

Assuming the SD is the only SPI device.
Edit DISABLE_CS_PIN to disable an SPI device.

Assuming the SD chip select pin is: 10
Edit SD_CS_PIN to change the SD chip select pin.

type any character to start

```

These are the full port monitor results.

# Answer
> 0 votes
Found out what's wrong

1. Common for connecting to any equipment

SdFat doesn't work for me, I still don't understand what's wrong with this library so it's better to use standard SD library

2. Common for connecting to any equipment

SD card (no name, SDHC, 32 GB)

Formatting an Sd card for an SD library (possibly for SdFat) should be in Fat32 with a msdos partition table
I found the answer here (https://forum.arduino.cc/t/yet-another-sd-initialization-fail/286017)
Due to an incorrect partition table, my card could not be read

3. ESP32 pin connection
ESP32 to MicroSD Adapter - (CS , D5) (SCK , D18) (MOSI , D23) (MISO , D19) (VCC , VIN) (GND , GND)
4. Arduino Pin Connection
Arduino to MicroSD Adapter - (CS , D4) (SCK , D13) (MOSI , D11) (MISO , D12) (VCC , +5V) (GND , GND)

---
Tags: arduino-nano, esp32, sd-card
---


# Question
Title: Get ESP32 Chip ID into a string variable (Arduino/C++ newbie here)
It's just a few days since I started using Arduino IDE ( programming an ESP32 ). As I learn, I am trying to write some snippets. I wanted to store the Chip ID of ESP32 into a variable (preferably string?) so that I can generate an unique device name. I looked through the ESP32 example programs and came across this program which just prints the Chip ID to the serial console.

```
  uint64_t chipid;

  chipid = ESP.getEfuseMac(); //The chip ID is essentially its MAC address(length: 6 bytes).
  Serial.printf("ESP32 Chip ID = %04X", (uint16_t)(chipid >> 32)); //print High 2 bytes
  Serial.printf("%08X\n", (uint32_t)chipid); //print Low 4bytes.

```

Now this works fine but I needed to store it into a variable in the following format "ESP32-0A1B3C4D5E6F" ( the last part of which is the Chip/MAC ID which is 6 bytes ). I went about some reading and currently reading and managed to get this far

```
  char ssid1[15];
  char ssid2[15];

  uint64_t chipid = ESP.getEfuseMac(); // The chip ID is essentially its MAC address(length: 6 bytes).
  uint16_t chip = (uint16_t)(chipid >> 32);

  snprintf(ssid1, 15, "%04X", chip);
  snprintf(ssid2, 15, "%08X", (uint32_t)chipid);

  Serial.print(ssid1);
  Serial.println(ssid2);

```

I am trying to read this which seems to be an excellent article on handling Arduino strings but just being a few days old with Arduino/c++ I am having some difficulty in wrapping my head around some of the concepts. I come from a Python, PHP, Javascript background so I guess this is gona take a little bit of a time. I am getting the output that I want in the serial console but now I would need this in this format (MCUDEVICE-0A1B3C4D5E6F). I am sure this code can be written in a much nicer, cleaner manner but for now I need this to proceed with another snippet (which relies on device name in the above mentioned format). Can anyone provide some pointers while I try check out the different ways I could achieve this? I just want to be sure that I am not writing ugly (and dangerous code - crashes, buffer overruns etc). Greatly appreciate any pointers. I guess I am starting to get a little paranoid about handling strings ( especially on low memory devices like typical mcus ).

# Answer
> 5 votes
You can combine all your work into one single line with the snprintf. You aren't limited to just one variable, and you can add plain text:

```
char ssid[23];

snprintf(ssid, 23, "MCUDEVICE-%04X%08X", chip, (uint32_t)chipid);

```

# Answer
> 1 votes
Why don't you simply use:

```
char ssid[23];
snprintf(ssid, 23, "MCUDEVICE-%llX", ESP.getEfuseMac());

```

This way no need to bit-shift and extra middle variables...

Just watch out for capital X for uppercase result and small 'l' for type indication. (meaning use either llX or llx and not LLX).

# Answer
> 0 votes
This works on an ESP32-S3 WROOM on Arduino 1.8.19:

```
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  String MCUtype = "ESP32s3" ;
  char ssid[14];
  snprintf(ssid, 14, "%llX", ESP.getEfuseMac());
  Serial.println(ssid); //
  String ssid1 = ssid ; // convert from char to String
  Serial.println(ssid1);
  int StrLen = ssid1.length();
  Serial.printf("Length of the string %i characters \r\n",StrLen);
  String MAC ="";
  int i = 0; while ( i < 6) {
    MAC = MAC + ssid1.substring(StrLen-2-2*i,StrLen-2*i)+":";
    i++ ;
  }
  MAC = MAC.substring(0,17); // remove last :
  Serial.println(MAC);
  String Serialnumber = MCUtype+"-" ;
    int j = 3; while ( j < 6) {
  Serialnumber = Serialnumber + ssid1.substring(StrLen-2-2*j,StrLen-2*j);
  j++ ;
  }
  Serial.println(Serialnumber);
}

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

}

```

---
Tags: arduino-ide, c++
---