message:
How do I build and upload a C++ program without the Arduino Library or IDE?

*Note: This is a reference question (but feel free to write answers of your own!)*

---

I want to use the AVR tools directly -- no arduino-builder or arduino-cli. I would also like compilation and uploading to be as fast as reasonably possible

body:
1. Create a new file called `Makefile` in your project directory. Populate it with the following contents:

```Makefile
TEMPDIR := $(shell mktemp -d)

all:
 avr-g++ -DF_CPU=<CLK> -mmcu=<PARTNO> -fno-threadsafe-statics -O3 -flto -std=c++23 -isystem/usr/avr/include -lm -fuse-linker-plugin -Wl,--gc-sections *.cpp -o ${TEMPDIR}/a.elf

 avr-objcopy -O ihex -R .eeprom ${TEMPDIR}/a.elf ${TEMPDIR}/a.hex
 avrdude -V -p<PARTNO> -carduino -P/dev/tty<SERIAL_PORT> -b<BAUD> -D -Uflash:w:${TEMPDIR}/a.hex

 rm ${TEMPDIR}/a.elf ${TEMPDIR}/a.hex
 rm -d ${TEMPDIR}
```

2. In the Arduino IDE, press Ctrl+, and enable verbose output during compilation and uploading.
3. Start uploading with Ctrl+U. Replace the groups of angled brackets in Makefile (e.g. `<CLK>`) with the values in the Arduino IDE's build output.
4. Run `make`.

`-lm` links in the AVR math library. `*.cpp` refers to your c++ source files. `-V` prevents avrdude from reading back the flash contents and verifying it, which saves time, but you may want to disable it while diagnosing problems.


sender: user

message:
How do I escape a boot loop?

*Note: This is a reference question (but feel free to write answers of your own!)*

---

I uploaded code that contains a bug that causes my Arduino to immediately reset itself when starting using [this](https://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_softreset) code from the AVR libc FAQ. The built-in LED keeps flashing. Because it's in this state of constantly resetting, I'm unable to upload my sketch to it.

I tried holding the reset button while uploading and burning a new bootloader, but neither of those worked.

How do I get my Arduino out of this boot loop so I can upload sketches again?

sender: assistant

body:
1. Start holding the reset button. This is to prevent the Arduino from entering the boot loop.
2. Unplug the Arduino and plug it back in.
3. Open a new sketch. Remove all of the code and replace it with `int main(){}`. This is to create a small program that will upload quickly.
4. Start uploading the sketch. Avrdude will attempt to upload the sketch ten times -- each time it tries, the RX LED on the Arduino will flash briefly.
5. Notice how often the LED flashes (0.2 Hz for me). Right before it flashes again, release the reset button. There's a small window of oppurtunity for avrdude to upload the sketch before the arduino starts up. If the TX and RX LEDs flash, success!


message:
How do I upload a sketch without a bootloader, using another Arduino as a programmer?

*Note: This is a reference question (but feel free to write answers of your own!)*

---

My Arduino takes too long to start up, I need to use the space taken up by the bootloader and I don't want a brown-out to be able to move the program counter to bootloader code, which could lead to my code being corrupted.

I considered buying an Arduino programmer, but since I already have an Uno lying around doing nothing, I would rather use that as a programmer.

I found a few guides on the internet, but most of them leave important details out and aren't specific enough.

So, how can I upload a sketch without a bootloader, using another Arduino as a programmer?

body:
There are a few guides on the internet that explain how to do this, but I've
found that most of them contain too much ambiguity or leave important details
out. This is my attempt at writing a short but complete guide that's easy to
follow.

## Prerequisites

- The board that will run your sketch
- A board that will act as a programmer (a.k.a. "ISP")
- 7 wires
- Any small capacitor

## Steps

### Programming the programmer

First, you'll need to upload the ArduinoISP sketch to the programmer. Here's
how:
1. In the Arduino IDE, press Alt+F and open Examples ->
   11.ArduinoISP -> ArduinoISP.
2. Plug in the programmer board (USB).
2. Press Alt+T and set "Board" to your *programmer*
   board's type and "Port" to your *programmer* board's serial port.
3. Press Ctrl+U to upload the sketch to your programmer.

### Connecting the boards

Then you need to connect the programmer to the board that will run your sketch.

1. Unplug the programmer board. This is to prevent accidental short-circuits.
2. Connect pins **GND, 10, MOSI, MISO, SCK and 5V** of the programmer to pins
   **GND, RESET, MOSI, MISO, SCK and 5V** of the board that will run your
   sketch, respectively. Pins MOSI, MISO and SCK correspond to pins 11, 12 and
   13, respectively, on the Uno and the Nano. Consult your board's datasheet if
   you're uncertain.
3. Connect the capacitor between pins 5V and RESET of the programmer board. This
   is to prevent it from auto-resetting while programming.
4. Plug in the programmer board. You will never need to plug in the board that
   will run your sketch.

### Uploading your sketch

The order of these steps is important due to a bug in the Arduino IDE.

1. Press Alt+T and set "Board" to *the board that will run
   your sketch*'s type, "Port" to your *programmer* board's serial port and
   "Programmer" to "Arduino as ISP".
2. Open the sketch you would like to upload.
3. Press Ctrl+**Shift**+U to upload the sketch using the programmer.

## Troubleshooting

If something went wrong, press Ctrl+, and enable verbose
"compilation" and "upload" and repeat the step that went wrong. Look out for
these error messages:

### `avrdude: stk500_recv(): programmer is not responding`

Followed by something similar to:

```plaintext
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xe0
```

Remove the capacitor before uploading a sketch to your *programmer* board.

### `avrdude: Yikes!  Invalid device signature.`

Scroll up and copy the line that looks similar to the following:

```plaintext
...avrdude -C...avrdude.conf -v -V -p... -c... -P... -b... -Uflash:w:....hex:i
```

Paste it into a terminal and add ` -F` to the end. You can reuse this command
every time you upload the same sketch.

### The upload seems to succeed but my sketch is still running the same code!

If the board that runs your sketch's CPU clock is slower than 1MHz (e.g. your
sketch modifies the CPU prescaler), you need to change `(1000000/6)` in the
ArduinoISP sketch to something slower and re-upload the sketch to your
programmer.


message:
How can I clear two FastLEDs strip ws2812b separately? One strip is connected to pin 7 of UNO and other strip to pin 6 of UNO

The power supply is external. I want to clear one strip say pin 7, and meanwhile i dont want other strip say pin 6 to switch off...I use
         FastLED.clear();
         FastLED.show();
But it clears all the led strips connected to pin6 and pin7. What is the code to switch off only one strip?

body:
You can use two `CLEDController` instances, which you can control separately, and by using the `clearLedData` you can clear either one or the other LED strip (depending on the `CLEDController` instance).

Below is the code I copied from
https://forum.arduino.cc/t/xrads-fastled-fastled-clear-question/693569/8
which contains more info:

    #include <FastLED.h>

    #define COLOR_ORDER GRB
    #define LED_TYPE WS2812B

    #define DATA_PIN 9
    #define NUM_LEDS 26
    CRGB leds[NUM_LEDS];

    #define HEADLIGHTS 10   //headlight led pin
    #define NUM_HEADLIGHTS 2
    CRGB leds2[NUM_HEADLIGHTS];

    CLEDController &ledController = FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);
    CLEDController &headlightController =   FastLED.addLeds<LED_TYPE, HEADLIGHTS, COLOR_ORDER>(leds2, NUM_HEADLIGHTS);

    void setup() {
      ledController.setCorrection(TypicalLEDStrip);
      headlightController.setCorrection(TypicalLEDStrip);

      ledController.clearLedData();
      headlightController.clearLedData();
      FastLED.show();
    }

    void loop() {
    }


message:
Arduino Nano IOT33 - Using flash

I'm looking for a way to store data on flash as on ESP8266 or ESP32 using `FS.h`,  `LITTLEFS.h` but it fails.

Is is possible on Nano IOT33 ?

body:
It seems this library can be used:

https://github.com/cmaglie/FlashStorage

Library: FlashStorage library for Arduino

About info: A convenient way to store data into Flash memory on the ATSAMD21 and ATSAMD51 processor family

Mentioned in external related article (thanks to Juraj): https://forum.arduino.cc/t/persistent-storage-for-arduino-nano-33-iot-no-eeprom/623137

**UPDATE**

(See remark of Juraj below: this is NOT for a Nano IOT33)

See Library: https://github.com/khoih-prog/FS_Nano33BLE

About info: Wrapper of FS (LittleFS or not-advisable FATFS) for Arduino MBED nRF52840-based boards, such as Nano_33_BLE boards. This library facilitates your usage of FS (LittleFS or FATFS) for the onboard flash. FS supports power fail safety and high performance

Mentioned in:
https://forum.arduino.cc/t/fs-nano33ble-library-for-nano-33-ble-using-littlefs-fatfs/900463


message:
How can I log data to a thumb drive?

I am working on a project where I need to log data, but I was wondering if it is possible to log that data to a thumb drive? I know that I can log data to an SD card, but I thought a thumb drive would be more accessible to users who wish to obtain the data. And if it is possible to log to a thumb drive, could it be done in CSV format?
The data is just sensor data.

body:
In principle you can log to a thumb drive any data you want, binary and text (thus also CSV).

However, the Arduino Uno does not support connecting a USB stick directly. If you want to connect a USB stick, you need a so called USB Host shield (for Arduino).

More information can be read on the Arduino site at this page:

https://docs.arduino.cc/retired/shields/arduino-usb-host-shield


body:
[Updated]

As an alternative to a Uno host shield, changing to a different Arduino MCU may also assist. USB host capabilty is needed for communicating with thumb drives.

[Some Arduino models][1] have a native USB port (e.g., Arduino Due, Arduino Leonardo, Arduino Micro, Arduino Nano 33 IOT, Arduino Zero, Arduino MKR Zero, Arduino MKR1000 ... ) which will work as a USB client device role.

A smaller set of MCU can act as either a USB client or host (e.g., Arduino Due, Arduino Portenta, ...). There is a [USBHost][2] library for Arduino Due listed in the Arduino Reference. Documentation for Arduino Portenta in USB host mode is [here][3].

[Here][4] is a discussion (and reference to an alternative library) regarding using a Due to write files to a thumb drive.

Of course an adapter cable or a thumb drive with a physical connector matching the native USB port on the selected MCU is required. Both are commonly available.

See also https://arduino.stackexchange.com/questions/24177/can-the-arduino-interface-with-usb-devices-without-the-usb-host-shield

  [1]: https://forum.arduino.cc/t/how-to-tell-if-a-board-has-native-usb-support-for-a-midi-project-with-a-mac/667494
  [2]: https://www.arduino.cc/reference/en/libraries/usbhost/
  [3]: https://docs.arduino.cc/tutorials/portenta-h7/usb-host
  [4]: https://forum.arduino.cc/t/usb-host-due-support-for-mass-storage-devices-thumbdrives/635331


message:
ESP32, NTP and SW reset

After HW reset (button or power reconnect) I get the correct NTP shift, but when I use `ESP.restart()` via MQTT I get the correct time without 3 3 HRS shift due to Tz. What happens after SW reset that behaves in such manner and how to fix it?

    bool myIOT2::_startNTP(const char *ntpServer, const char *ntpServer2)
    {
     unsigned long startLoop = millis();
     while (!_NTP_updated() && (millis() - startLoop < 20000))
     {
    #if defined(ESP8266)
      configTime(TZ_Asia_Jerusalem, ntpServer2, ntpServer); // configuring time offset and an NTP server
    #elif defined(ESP32)
      configTzTime(TZ_Asia_Jerusalem, ntpServer2, ntpServer);
    #endif
      delay(1000);
     }
     if (!_NTP_updated())
     {
      return 0;
     }
     else
     {
      return 1;
     }
    }
    bool myIOT2::_NTP_updated()
    {
     return now() > 1640803233;
    }

body:
Apparently, time in ESP32 survives a sw reset, while in ESP8266 doesn't.
So in code, which is same for both  - if clock is updated (a rough criteria that time is greater than some day in 2020 ), it skipped TZ update  `configTzTime(TZ_Asia_Jerusalem, ntpServer2, ntpServer);`

So after a crash and/or sending a MQTT message to reboot, time was missing TZ update.

Hope it'll help someone.

Guy


message:
How to cut down size of imported DigiKeyboard library

I'm working on a project with a Digispark ATTiny85, that performs keystrokes using the DigisparkKeyboard library (https://github.com/digistump/DigisparkArduinoIntegration/tree/master/libraries/DigisparkKeyboard). Besides the DigiKeyboard, I also import EEPROM.h.

My own code is only about 150 lines, I've cut down the size following a number of online guides, trying to avoid larger data types and so on. The Digispark is limited to ~6kB and the imported DigiKeyboard library takes up a little more that 5.4kB. In total the compiled project takes up about 7kB, which exceeds the boards capacity.

From the DigiKeyboard library I only use `DigiKeyboard.sendKeyStroke()` and `DigiKeyboard.print()` (with about only ten different characters). So I assume there is a lot of unused code I could remove, but I don't know how to approach this. I use Visual Studio Code and PlatformIO.

How could I reduce the size of the used DigisparkKeyboard library?

body:
The compiler/linker will remove unused functions/methods automatically, so I doubt you can save memory by removing unused functions/methods yourself.

However, you could possibly gain by:

- Removing the calls of check functions/methods when you know the result will be always `false`, `true`, or always the same number, string or data type in general.
- Removing (parts of) functions/methods which are related to physical or logical functionality you never use. Like e.g. `if`, `case` statements that will never apply).
- Prevent using an entire class (e.g. `String`) (see second comment of Emma Makes below).


body:
With input from @EdgarBonet, I looked into the functions used and it turned out that the `String()` function, I used once in my code, takes up about 3kB of space in the compiled program.

I ended up removing the line with `String()` and kept the imported DigiKeyboard library as it is.


message:
LED blink patterns with multiple LEDs with millis() not using Delay()

I want to make LED blink patterns with multiple LEDs with the `millis()` function. I researched about it but did not find a perfect solution.

I found [one blog][1], but it is using a LED pin number array; I need a solution without an array. Any help will be appreciated.

  [1]: https://www.baldengineer.com/arduino-chasing-leds-with-millis.html

This is my code which I have written:

    const int Button_code_1 = 2;
    const int Button_code_2 = 3;
    const int Button_code_stop = 4;

    const int LED_one = 6;
    const int LED_two = 8;
    const int LED_three = 10;
    const int LED_four = 12;

    int buttonState_code_1 = 0;
    int buttonState_code_2 = 0;
    int buttonState_code_stop = 0;

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

      Serial.begin(9600);

      pinMode(Button_code_1,INPUT);
      pinMode(Button_code_2,INPUT);
      pinMode(Button_code_stop,INPUT);

      pinMode(LED_Button_one,INPUT);
      pinMode(LED_Button_two,INPUT);
      pinMode(LED_Button_three,INPUT);
      pinMode(LED_Button_four,INPUT);

      pinMode(LED_one, OUTPUT);
      pinMode(LED_two, OUTPUT);
      pinMode(LED_three, OUTPUT);
      pinMode(LED_four, OUTPUT);
    }

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

      buttonState_code_1 = digitalRead(Button_code_1);
      Serial.println(buttonState_code_1);
      buttonState_code_2 = digitalRead(Button_code_2);
      Serial.println(buttonState_code_2);
      delay(1000);
      buttonState_code_stop = digitalRead(Button_code_stop);

      if(buttonState_code_1==1)
      {
        pattern_one();
      }
      if(buttonState_code_2==1)
      {
        pattern_two();
      }

    }

    void pattern_one()
    {
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, HIGH);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, LOW);
      delay(3000);
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, HIGH);
      delay(3000);
      digitalWrite(LED_one, HIGH);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, LOW);
      delay(3000);
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, HIGH);
      digitalWrite(LED_four, LOW);
      delay(3000);
    }

    void pattern_two()
    {
      digitalWrite(LED_one, HIGH);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, LOW);
      delay(3000);
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, HIGH);
      digitalWrite(LED_four, LOW);
      delay(3000);
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, HIGH);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, LOW);
      delay(3000);
      digitalWrite(LED_one, LOW);
      digitalWrite(LED_two, LOW);
      digitalWrite(LED_three, LOW);
      digitalWrite(LED_four, HIGH);
      delay(3000);
    }

This is my sample code with four LEDs. I have written this code with `delay()`, so when I want to change the pattern I can't because `delay()` is blocking the code.

I researched this and found the `millis()` function as the solution. How can I implement this code using the `millis()` function?

body:
This is one of the effects for 3 (sets) of LEDs from [my light alarm clock sketch][1]:
```
void cycleEffect() {

  static unsigned long previousMillis;
  static uint8_t cycleCounter;

  if (millis() - previousMillis > 100) {
    previousMillis = millis();
    digitalWrite(LEDS_CENTRAL_PIN, cycleCounter == 0);
    digitalWrite(LEDS_LEFT_PIN, cycleCounter == 1);
    digitalWrite(LEDS_RIGHT_PIN, cycleCounter == 2);
    cycleCounter++;
    if (cycleCounter == 3) {
      cycleCounter = 0;
    }
  }
}
```

  [1]: https://github.com/JAndrassy/SunriseClock/blob/main/SunriseClock/SunriseClock.ino


message:
Arduino IDE EEPROM put() then read() returns different data on ESP32

I'm trying to understand how to read/write [a UID struct from miguelbalboa](https://github.com/miguelbalboa/rfid/blob/master/src/MFRC522.h#L255) to EEPROM to persist a card ID across system restarts on my ESP32-S3 through the Arduino IDE. I expected Put/Get/Read to be symmetrical but can't seem to prove that. Here's my test program:

```
/**
 * This is a simple script to experiment with reading and writing MFRC522::Uid
 * structures to eeprom.
 */

#include <MFRC522.h>
#include <EEPROM.h>

#define UID_EEPROM_LOCATION 0
#define EEPROM_SIZE 256

void setup() {

  Serial.begin(115200);   // Initialize serial communications with the PC
  Serial.println("Serial started.");
  EEPROM.begin(EEPROM_SIZE);
  Serial.print("EEPROM started ");
  Serial.println(EEPROM_SIZE);
  printBytesFromEeprom();
  MFRC522::Uid uidToWrite = {
    0x04,
    {B00000000, B10000000, B11100000, B01100000},
    0
  };
  Serial.print("UID Before Write: ");
  printUid(&(uidToWrite));
  storeUidInEeprom(&(uidToWrite));
  printBytesFromEeprom();
  Serial.println("UID was put.");
  MFRC522::Uid uidFromRead;
  readUidFromEeprom(&(uidFromRead));
  printBytesFromEeprom();
  Serial.print("UID from Read: ");
  printUid(&(uidFromRead));
}

void loop() {
}

void printUid(MFRC522::Uid *uid) {
  Serial.print(uid->size, HEX);
  Serial.print(F(" byte card UID:"));
  for (byte i = 0; i < uid->size; i++) {
    if(uid->uidByte[i] < 0x10)
      Serial.print(F(" 0"));
    else
      Serial.print(F(" "));
    Serial.print(uid->uidByte[i], HEX);
  }
  Serial.println();
}

void readUidFromEeprom(MFRC522::Uid* result) {
  EEPROM.get(UID_EEPROM_LOCATION, result);
  delay(1000);
}

void storeUidInEeprom(MFRC522::Uid *uid) {
  EEPROM.put(UID_EEPROM_LOCATION, uid);
  EEPROM.commit();
  delay(1000);
}

void printBytesFromEeprom() {
  Serial.print("256 bytes from EEPROM: ");
  for (int i = 0; i < 256; i++) {
    byte myByte = EEPROM.read(UID_EEPROM_LOCATION + i);
    if(myByte < 0x10)
      Serial.print(F(" 0"));
    else
      Serial.print(F(" "));
    Serial.print(myByte, HEX);
  }
  Serial.println();
}
```

I'm an experienced Java developer, but new to C++. I could have made any number of basic errors.

When I run the above on my ESP32-S3-DevKitC-1, I get the following output:

```
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd0108,len:0x43c
load:0x403b6000,len:0xbd0
load:0x403ba000,len:0x29c8
entry 0x403b61d8
Serial started.
EEPROM started 256
256 bytes from EEPROM:  E4 2C CE 3F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID Before Write: 4 byte card UID: 00 80 E0 60
256 bytes from EEPROM:  94 2D CE 3F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID was put.
256 bytes from EEPROM:  94 2D CE 3F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID from Read: C0 byte card UID: 79 CD 3F 00 00 00 00 00 00 00 00 0C FA 3B C7 00 00 00 00 04 00 00 00 4C 2F CE 3F 01 00 00 80 00 00 00 00 F0 2D CE 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2E CE 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
```

There are two unexpected things from this output:

* The output of `readUidFromEeprom()` is different than the input to `storeUidInEeprom()`

Any help would be welcome!

body:
Well...

I still don't know why the above wasn't working. But if I switch to my own byte encoding in EEPROM (the obvious one that I assumed `put()` used, then I get the right behavior:

```
/**
 * This is a simple script to experiment with reading and writing MFRC522::Uid
 * structures to eeprom.
 */

#include <MFRC522.h>
#include <EEPROM.h>

#define UID_EEPROM_LOCATION 0
#define EEPROM_SIZE 256

void setup() {

  Serial.begin(115200);   // Initialize serial communications with the PC
  Serial.println("Serial started.");
  EEPROM.begin(EEPROM_SIZE);
  Serial.print("EEPROM started ");
  Serial.println(EEPROM_SIZE);
  printBytesFromEeprom();
  MFRC522::Uid uidToWrite = {
    0x04,
    {B00000000, B10000000, B11100000, B01100000},
    0
  };
  Serial.print("UID Before Write: ");
  printUid(&(uidToWrite));
  storeUidInEeprom(&(uidToWrite));
  printBytesFromEeprom();
  Serial.println("UID was put.");
  MFRC522::Uid uidFromRead;
  readUidFromEeprom(&(uidFromRead));
  printBytesFromEeprom();
  Serial.print("UID from Read: ");
  printUid(&(uidFromRead));
}

void loop() {
}

void printUid(MFRC522::Uid *uid) {
  Serial.print(uid->size, HEX);
  Serial.print(F(" byte card UID:"));
  for (byte i = 0; i < uid->size; i++) {
    if(uid->uidByte[i] < 0x10)
      Serial.print(F(" 0"));
    else
      Serial.print(F(" "));
    Serial.print(uid->uidByte[i], HEX);
  }
  Serial.println();
}

void readUidFromEeprom(MFRC522::Uid* result) {
  byte uidSize = EEPROM.read(UID_EEPROM_LOCATION);
  for (byte i = 0; i < uidSize; i++) {
    result->uidByte[i] = EEPROM.read(UID_EEPROM_LOCATION + 1 + i);
  }
  byte uidSak = EEPROM.read(UID_EEPROM_LOCATION + 2 + uidSize);
  result->size = uidSize;
  result->sak = uidSak;
}

void storeUidInEeprom(MFRC522::Uid *uid) {
  EEPROM.write(UID_EEPROM_LOCATION, uid->size);
  for (byte i = 0; i < uid->size; i++) {
    EEPROM.write(UID_EEPROM_LOCATION + 1 + i, uid->uidByte[i]);
  }
  EEPROM.write(UID_EEPROM_LOCATION + 2 + uid->size, uid->sak);
  EEPROM.commit();
}

void printBytesFromEeprom() {
  Serial.print("256 bytes from EEPROM: ");
  for (int i = 0; i < 256; i++) {
    byte myByte = EEPROM.read(UID_EEPROM_LOCATION + i);
    if(myByte < 0x10)
      Serial.print(F(" 0"));
    else
      Serial.print(F(" "));
    Serial.print(myByte, HEX);
  }
  Serial.println();
}
```

And output as expected is:

```
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd0108,len:0x43c
load:0x403b6000,len:0xbd0
load:0x403ba000,len:0x29c8
entry 0x403b61d8
Serial started.
EEPROM started 256
256 bytes from EEPROM:  04 00 80 E0 60 FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID Before Write: 4 byte card UID: 00 80 E0 60
256 bytes from EEPROM:  04 00 80 E0 60 FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID was put.
256 bytes from EEPROM:  04 00 80 E0 60 FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
UID from Read: 4 byte card UID: 00 80 E0 60

```


body:
You wrote:

```c++
void readUidFromEeprom(MFRC522::Uid* result) {
  EEPROM.get(UID_EEPROM_LOCATION, result);
  delay(1000);
}
```

The `EEPROM.get()` method expects a _reference_ to the variable you are
setting. Here, you are providing a _pointer_ instead. The outcome is
that this call is updating the `result` local variable (the pointer),
rather than the memory region pointed by it.

You may try this:

```c++
void readUidFromEeprom(MFRC522::Uid* result) {
  EEPROM.get(UID_EEPROM_LOCATION, *result);  // notice the `*' operator
  delay(1000);
}
```

Same thing for `EEPROM.put()`.

**Edit**: As suggested by Juraj in a comment, it can make more sense to
have `readUidFromEeprom()` accept a reference rather than a pointer:

```c++
void readUidFromEeprom(MFRC522::Uid &result) {
  EEPROM.get(UID_EEPROM_LOCATION, result);
  delay(1000);
}
```

But then you have to also change the caller:

```c++
readUidFromEeprom(uidFromRead);
```


message:
Using pyFirmata with a 360° servo; how do I stop it?

I am testing out pyFirmata. I have a 360° servo, and know how to change its direction, but I dont't know how to stop it.

What command, like `servo.write()`, would work to make it stop moving until prompted to move again?

body:
You'll need to check datasheets for your servos but a PWM value of 1500 microseconds would generally be near neutral / no rotation. Decreasing values less than this should generate increasing speed clockwise. Increasing values greater than neutral should generate increasing speed counter clockwise.

See https://arduino.stackexchange.com/a/88650/71575


message:
How does erasing the EEPROM work?

The datasheet for the ATmega328P contains this table, which describes bits 4 and 5 of EECR:

EEPM1 | EEPM0 | Programming Time | Operation
------|-------|------------------|----------
0     | 0     | 3.4ms            | Erase and write in one operation (atomic operation)
0     | 1     | 1.8ms            | Erase only
1     | 0     | 1.8ms            | Write only

I'm currently working on some non-blocking EEPROM-handling code and I'm wondering when and how I should erase the EEPROM.
- What does erasing do? Does it set one byte to 0x0, or the entire EEPROM?
- Should I erase it first whenever I want to write a byte?
  - If not, why is there an option to erase and write separately?
- How do I initiate an erase?

Either the datasheet is rather lacking concerning the EEPROM, or I'm just not finding what I'm looking for. I tried using a search engine, but all results are either about the Arduino EEPROM library or \<avr/eeprom.h>, both of which use polling instead of interrupts (and are therefore blocking).

body:
Your questions are answered in [the AVR ATMega328 datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf).

The procedure for erasing and writing the internal EEPROM is outlined in chapter 7.6 (Register Description).

 - The Erase operation erases 1 byte (erasing an EEPROM cell sets it to all 1s, i.e. 0xff).
 - The EEPROM address to be erased/programmed is pointed to by the EEARL and EEARH registers. The value to be programmed into that address is set by the EEDR. Reading a value from EEPROM returns the value in the same EEDR register.
 - Before writing a new value to the EEPROM, the old value must first be erased. You can do that as two separate actions or one single action. You could also leave the cell deprogrammed (erased) by only erasing it and not programming it again.
 - You initiate an erase of the EEPROM address pointed to by EEARH/EEARL, by setting EEPM1 to 1, EEPM0 to 0 and setting EEPE to 1 to start the erase operation. Setting EEPM1 and EEPM0 both to 0 will erase and program a new byte in a single operation.

As for making EEPROM writes non-blocking, you could set a (non-blocking) timer for the duration of the write, erase or erase/write operation. According to the datasheet these operations respectively take 1.8, 1.8 and 3.4 ms. Just make sure your code does not access the EEPROM while these operations are taking place.

You could also (non-blocking) periodically poll the EEPE bit until it is cleared, signalling the operation is finished.

The most elegant way, i.m.o. is to make use of the EERIE flag by setting it to 1, which will enable the ATmega to generate an interrupt when the EEPROM operation is finished.


message:
How can I use a LCD I2C and a RTC3231 on a Arduino Pro Mini?

On a small project, I have a DS3231 RTC module and a LCD I2C module that I'm trying to connect on a Arduino Pro Mini board. However, both the RTC and LCD require connecting the `SDA` and `SCL` to the pins `A4` and `A5` respectively.

The libraries do not seem to allow changing the connected pins. Why is that? I have other pins available, like `A6` and `A7`, can those be used?

body:
Welcome, I understand where you are coming from, without a background you do not know what to ask. Were were all where you are at one time. I hope this helps.  You need to do some studying on the I2C bus, online tutorials will make it easy. You you will find you can connect over 100 devices to it at one time The SCL and SDA lines go from module to module. Note each module has its own address, sometimes they are selectable. Some modules have pull up resistors, others do not. To keep it interesting the pull up resistors are mostly 10K but that is not a constant.

There are loading rules etc to be careful of if you have long wires or maybe more than three units. You need to add pull ups to each of the two lines (example: 4.7K from SCL to +5) or use something in the 3K range for a 3V3 system. The reason is because the bus has both dominant and recessive states where the recessive is high which the resistor provides. The SCL and SDA output/input on the parts have open collector/open drain outputs so they cannot source anything.

Once you have it hooked up you need to run a program called I2C scan or something like that. If you have wired it correctly it will give you the address of the module, you will probably get two or three as there is the RTC, Memory device and possible a temperature sensor.

The #1 rule is the Arduino A Power Supply it is NOT! A small module or two connected to the 5V out is fine but never connect a motor directly to any arduino you will probably fry the Arduino.

I use Vin and supply it with about 8 volts by using either a Buck or Sepic converter from a 12V 2A or larger supply. I do it this way because I get a more stable voltage on the Arduino because of the extra filtering etc built into the analog regulator section. Real nice when using the A/D, keeps things stable. Were here to help, ask questions any time and do not worry is some over eager person decides to vote you down. Read the guidelines etc and  you will do great.

You can search online for "Arduino RTC" and find a lot of programs with software.


message:
Garbage in serial monitor

I'm revisiting my Arduino stuff (I want to revive Teleinfo shield to monitor closely my power consumption). I just cannot get the thing to work ([Teleinfo Shield][1] + Uno Wifi).

When trying to check what's happening this is the kind of Serial Monitor screens that I get.

Any hints on how to solve? It happens with other Uno as well and different versions of IDE.

Thank for any help, the answers I found in different places didn't lead me to a solution.

I tried several baud settings, (same for port and monitor, each time) and sometimes nothing was written, sometimes complete garbage, sometimes as illustrated

The code is the following Teleinfo_Arduino_V0_3E.ino (just added some lines writing to serial to follow progress; and modified `Serial.begin` accordingly and "shortened" to stay within size limits but it's sending wrong characters ate beginning))

```c++
/*
              Datalogger Téléinfo 2 compteurs sur Arduino

              Compteur 1: consommation
              Compteur 2: production solaire en tarif BASE

              Juin 2011:
              v0.2  * passage automatique à l'heure d'été
                      correctif erreur abo BBR
                      modification ecriture sur SD (utilisation de teleinfoFile.print à la place s'une variable STRING
                      qui plante l'Arduino avec les abonnements BBR
              v0.2a * ajout mode sans puissance apparente pour ancien compteur et calcul de celle-ci pour les logiciels d'analyse
              v0.2b * pour Arduino 1.0 (mise à jour de la RTC et utilisation de la librairie SD livrée avec la 1.0)
              v0.2c * modif type de variable pour éviter d'avoir 2 enregistrements à la même minute (surtout sur des proc + rapide)
              v0.3  * détection automatique du type d'abonnement sur le compteur 1
              v0.3a * Fonction de mise à l'heure par l'usb (interface série) en 1200 bauds 7 bits parité pair
                      Procédure:
                      1- carte débranchée, enlevez la pile de son support (pour réinitialiser l'horloge)
                      2- enlevez le cavalier du shield téléinfo
                      3- configurer votre logiciel émulateur de terminal (termite,Hyperterminale...) en 1200 bauds 7 bits parité pair
                      4- mettre sous tension la carte.
                      -- Le programme détectera le reset de l'horloge et vous demandera de rentrer l'heure et la date. --

              v0.3b * Correction bug calcul PAP compteur 2, enregistrement journalier compteur 2
              v0.3c * Triphasé sur compteur 2
              v0.3d * correction bug retour ligne sur compteur 2 (entête fichier)
              v0.3e * Correction bug si pas de compteur 2
*/

#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>

const char version_logiciel[6] = "V0.3e";

// #define echo_USB            //envoie toutes les trames téléinfo sur l'USB
#define message_systeme_USB  //envoie des messages sur l'USB (init SD, heure au demarrage, et echo des erreures)

//*****************************************************************************************
byte inByte = 0;  // caractère entrant téléinfo
char buffteleinfo[21] = "";
byte bufflen = 0;
byte mem_sauv_minute = 1;
byte mem_sauv_journee = 1;
byte num_abo = 0;
byte type_mono_tri[2] = { 0, 0 };
uint8_t presence_teleinfo = 0;  // si signal teleinfo présent
byte presence_PAP = 0;          // si PAP présent
boolean cpt2_present = true;    // mémorisation de la présence du compteur 2
boolean compteursluOK = false;  // pour autoriser l'écriture de valeur sur la SD
boolean mem_affichage_cpt2_present = true;

int ReceptionOctet = 0;            // variable de stockage des octets reçus par port série
unsigned int ReceptionNombre = 0;  // variable de calcul du nombre reçu par port série
byte reg_horloge = 1;
boolean mem_reg_horloge = false;
const uint8_t val_max[6] = { 24, 59, 59, 31, 12, 99 };

// declarations Teleinfo
unsigned int papp = 0;  // Puissance apparente, VA

uint8_t IINST[2][3] = { { 0, 0, 0 }, { 0, 0, 0 } };  // Intensité Instantanée Phase 1, A  (intensité efficace instantanée) ou 1 phase en monophasé

unsigned long INDEX1 = 0;  // Index option Tempo - Heures Creuses Jours Bleus, Wh
unsigned long INDEX2 = 0;  // Index option Tempo - Heures Pleines Jours Bleus, Wh
unsigned long INDEX3 = 0;  // Index option Tempo - Heures Creuses Jours Blancs, Wh
unsigned long INDEX4 = 0;  // Index option Tempo - Heures Pleines Jours Blancs, Wh
unsigned long INDEX5 = 0;  // Index option Tempo - Heures Creuses Jours Rouges, Wh
unsigned long INDEX6 = 0;  // Index option Tempo - Heures Pleines Jours Rouges, Wh

// compteur 2 (solaire configuré en tarif BASE par ERDF)
unsigned long cpt2index = 0;     // Index option Base compteur production solaire, Wh
unsigned int cpt2puissance = 0;  // Puissance apparente compteur production solaire, VA

#define debtrame 0x02
#define debligne 0x0A
#define finligne 0x0D

// *************** déclaration carte micro SD ******************
const byte chipSelect = 4;

// *************** déclaration activation compteur 1 ou 2 ******
#define LEC_CPT1 5  // lecture compteur 1
#define LEC_CPT2 6  // lecture compteur 2
//
byte verif_cpt_lu = 0;
//

byte compteur_actif = 1;           // numero du compteur en cours de lecture
byte donnee_ok_cpt[2] = { 0, 0 };  // pour vérifier que les donnees sont bien en memoire avant ecriture dans fichier
byte donnee_ok_cpt_ph[2] = { 0, 0 };

// *************** variables RTC ************************************
byte minute, heure, seconde, jour, mois, jour_semaine;
unsigned int annee;
char date_heure[18];
char mois_jour[7];
byte mem_chg_heure = 0;  //pour pas passer perpetuellement de 3h à 2h du matin le dernier dimanche d'octobre
RTC_DS1307 RTC;

// ************** initialisation *******************************
void setup() {
  // initialisation du port 0-1 lecture Téléinfo
  Serial.begin(1200);
  // parité paire E
  // 7 bits data
  UCSR0C = B00100100;
#ifdef message_systeme_USB
  Serial.print(F("-- Teleinfo USB Arduino "));
  Serial.print(version_logiciel);
  Serial.println(F(" --"));
#endif
  // initialisation des sorties selection compteur
  pinMode(LEC_CPT1, OUTPUT);
  pinMode(LEC_CPT2, OUTPUT);
  digitalWrite(LEC_CPT1, HIGH);
  digitalWrite(LEC_CPT2, LOW);

  // verification de la présence de la microSD et si elle est initialisée:
#ifdef message_systeme_USB
  if (!SD.begin(chipSelect)) {
    Serial.println(F("> Erreur carte, ou carte absente !"));
    return;
  }
  Serial.println(F("> microSD initialisee !"));
#endif

  // initialisation RTC16

  Wire.begin();
  RTC.begin();

  if (!RTC.isrunning()) {
#ifdef message_systeme_USB
    Serial.println(F("RTC non configure !"));
#endif
  }

  DateTime now = RTC.now();  // lecture de l'horloge
  annee = now.year();
  mois = now.month();
  jour = now.day();
  heure = now.hour();
  minute = now.minute();
  jour_semaine = now.dayOfTheWeek();

  format_date_heure();
#ifdef message_systeme_USB
  Serial.println(date_heure);
#endif
}

// ************** boucle principale *******************************

void loop()  // Programme en boucle
{

  if (!(RTC.isrunning()) && (reg_horloge < 7)) {  // si l'horloge n'est pas configurée
    digitalWrite(LEC_CPT1, LOW);

    if (!mem_reg_horloge) {
      switch (reg_horloge) {  // debut de la structure
        case 1:
          Serial.print(F("Entrer Heure: "));
          break;
        case 2:
          Serial.print(F("Entrer Minute: "));
          break;
        case 3:
          Serial.print(F("Entrer Seconde: "));
          break;
        case 4:
          Serial.print(F("Entrer Jour: "));
          break;
        case 5:
          Serial.print(F("Entrer Mois: "));
          break;
        case 6:
          Serial.print(F("Entrer Annee 20xx: "));
          break;
      }
      mem_reg_horloge = true;
    }
    if (Serial.available() > 0) {  // si caractère dans la file d'attente

      Serial.print(F("un nombre a ete recu")); //---- lecture du nombre reçu
      while (Serial.available() > 0) {
        // tant que buffer pas vide pour lire d'une traite tous les caractères reçus
        inByte = Serial.read();         // renvoie le 1er octet présent dans la file attente série (-1 si aucun)
        Serial.println(inByte);
        if (((inByte > 47) && (inByte < 58)) || (inByte == 13)) {
          ReceptionOctet = inByte - 48;  // transforme valeur ASCII en valeur décimale
          if ((ReceptionOctet >= 0) && (ReceptionOctet <= 9)) ReceptionNombre = (ReceptionNombre * 10) + ReceptionOctet;
          // si valeur reçue correspond à un chiffre on calcule nombre
          Serial.print(ReceptionNombre);
          Serial.print(reg_horloge);
        } else
          presence_teleinfo = -1;
      }  // fin while
      if (inByte == 13) {
        if ((ReceptionNombre > val_max[reg_horloge - 1]) || (ReceptionNombre == -1)) {
          Serial.println(F("Erreur horaire"));
          ReceptionNombre = 0;
          mem_reg_horloge = true;
        } else {
          Serial.print("cela bugge");
          switch (reg_horloge) {  // debut de la structure
            case 1:
              heure = ReceptionNombre;
              Serial.print("heure:");
              Serial.println(heure);
            case 2:
              minute = ReceptionNombre;
              break;
            case 3:
              seconde = ReceptionNombre;
              break;
            case 4:
              jour = ReceptionNombre;
              break;
            case 5:
              mois = ReceptionNombre;
              break;
            case 6:
              annee = 2000 + ReceptionNombre;
              break;
          }

          mem_reg_horloge = false;
          ReceptionNombre = 0;
          ++reg_horloge;

          if (reg_horloge > 6) {
            RTCsetTime();
            Serial.println(F("Reglage heure OK - installer le cavalier pour la teleinfo"));
            digitalWrite(LEC_CPT1, HIGH);
          }
        }
      }
    }
  }

  else {

    DateTime now = RTC.now();  // lecture de l'horloge
    minute = now.minute();
    heure = now.hour();
    seconde = now.second();

    if ((heure == 0) && (minute == 0) && (seconde == 0)) {
      annee = now.year();
      mois = now.month();
      jour = now.day();
      jour_semaine = now.dayOfTheWeek();
    }

    // passage à l'heure d'été +1 heure
    // la lib RTC a une fonction: dayOfWeek qui donne le jour de la semaine (la DS1307 se charge de tout !)
    // réponse: 0 -> dimanche, 1 -> lundi etc...
    //
    if ((heure == 2) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 3) && (jour > 24)) {
      heure = 3;
      RTCsetTime();
    }

    // passage à l'heure d'hiver -1 heure
    if ((heure == 3) && (minute == 0) && (seconde == 0) && (jour_semaine == 0) && (mois == 10) && (jour > 24) && (mem_chg_heure == 0)) {
      heure = 2;
      RTCsetTime();
      mem_chg_heure = 1;
    }

    if ((heure == 23) && (minute == 59) && (seconde == 10))  // pour être sur de pas tomber pendant l'enregistrement toutes les minutes
    {
      if ((mem_sauv_journee == 0) && (compteursluOK))  // un seul enregistrement par jour !
      {
        fichier_annee();
        mem_sauv_journee = 1;
        mem_chg_heure = 0;
      }
    } else
      mem_sauv_journee = 0;

    if (seconde == 1) {
      if ((mem_sauv_minute == 0) && (compteursluOK))  // un seul enregistrement par minute !
      {
        enregistre();
        mem_sauv_minute = 1;
      }
    } else
      mem_sauv_minute = 0;

#ifdef message_systeme_USB
    if ((donnee_ok_cpt[1] == B00000111) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 detecte"));
      mem_affichage_cpt2_present = false;
    } else if ((!cpt2_present) && (mem_affichage_cpt2_present)) {
      if (mem_affichage_cpt2_present) Serial.println(F("- Compteur 2 non present !"));
      mem_affichage_cpt2_present = false;
    }
#endif

    if ((donnee_ok_cpt[0] == verif_cpt_lu) and (cpt2_present)) {
      if ((type_mono_tri[0] == 1) && (donnee_ok_cpt_ph[0] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[0] == 3) && (donnee_ok_cpt_ph[0] == B10000111))
        bascule_compteur();
    } else if ((donnee_ok_cpt[1] == B00000001) or ((compteur_actif == 2) and (!cpt2_present))) {
      if ((type_mono_tri[1] == 1) && (donnee_ok_cpt_ph[1] == B10000001)) bascule_compteur();
      else if ((type_mono_tri[1] == 3) && (donnee_ok_cpt_ph[1] == B10000111))
        bascule_compteur();
      compteursluOK = true;
    }

    if (compteur_actif == 2) {
      if (presence_teleinfo > 200) {
        cpt2_present = false;
        compteursluOK = true;
        bascule_compteur();
      } else
        cpt2_present = true;
    }

    read_teleinfo();
  }
}

///////////////////////////////////////////////////////////////////
// Calcul Checksum teleinfo
///////////////////////////////////////////////////////////////////
char chksum(char *buff, uint8_t len) {
  int i;
  char sum = 0;
  for (i = 1; i < (len - 2); i++) sum = sum + buff[i];
  sum = (sum & 0x3F) + 0x20;
  return (sum);
}

///////////////////////////////////////////////////////////////////
// mise en forme Date & heure pour affichage ou enregistrement
///////////////////////////////////////////////////////////////////
void format_mois_jour() {
  sprintf(mois_jour, "d,d,", mois, jour);
}

// Convert normal decimal numbers to binary coded decimal
static uint8_t bin2bcd(uint8_t val) {
  return val + 6 * (val / 10);
}

///////////////////////////////////////////////////////////////////
// mise à l'heure de la RTC (DS1307)
///////////////////////////////////////////////////////////////////
void RTCsetTime(void) {
  Wire.beginTransmission(104);  // 104 is DS1307 device address (0x68)
  Wire.write(bin2bcd(0));       // start at register 0

  Wire.write(bin2bcd(seconde));       //Send seconds as BCD
  Wire.write(bin2bcd(minute));        //Send minutes as BCD
  Wire.write(bin2bcd(heure));         //Send hours as BCD
  Wire.write(bin2bcd(jour_semaine));  // dow
  Wire.write(bin2bcd(jour));          //Send day as BCD
  Wire.write(bin2bcd(mois));          //Send month as BCD
  Wire.write(bin2bcd(annee % 1000));  //Send year as BCD

  Wire.endTransmission();
}
```

MacBookPro 2018 runnning Monterey

[![Example output on Serial Monitor][2]][2]

  [1]: https://www.cartelectronic.fr/teleinfo-compteur-enedis/11-shield-teleinfo-arduino-3760313520202.html
  [2]: https://i.stack.imgur.com/Qv9ty.png

body:
## Parity mismatch
The essence of the seems to be this:
```c++
Serial.begin(1200);
// parité paire E
// 7 bits data
UCSR0C = B00100100;
```

The code changes the USART to operate with **EVEN** parity and **1** stop bits, or 7E1 [for short][1]. The Arduino serial monitor uses the more common NO parity 1 stop bit configuration (8N1). I did a small hello world type test to confirm that the kind of output you're getting on the Serial Monitor is about like expected for this mismatch.

## Resolving

So, you need them to match. You can:

* Either remove/comment out `UCSR0C = B00100100;` to go with the normal 8N1 configuration.

* Or use a serial [terminal emulator][2] or other software capable of configuring for the port for even parity and 1 stop bits (7E1).

Incidentally, if you have good cause to use 7E1, [the conventional way][3] to do it is `Serial.begin(1200, SERIAL_7E1);` I don't know why they manually manipulated the hardware registers, perhaps the code predates support for this form of `begin()`.

## Serial Monitor Support

The IDE's Serial Monitor is [reportedly capable of being configured][4] for something other than 8N1 via `preferences.txt`. <s>I did not get it working, but I also didn't spend that long trying. Perhaps I will again and update this.</s> I think I didn't close all instances of the IDE. I've now verified that the Serial Monitor can be operated in 7E1 making the following changes to the [arduino15 directory's][5] `preferences.txt` file:

| Old line reading  | New line reading  |
|-------------------|-------------------|
|`serial.databits=8`|`serial.databits=7`|
|`serial.parity=N`  |`serial.parity=E`  |

That said, it is *probably a mistake* to have a change like that hidden away where it will cause lots of confusion later when 8N1 is needed. So, a terminal emulator is still probably a better choice if you actually want or need even parity and 1 stop bits. I in fact I'm going to change mine back now, just so this doesn't catch me. I'd use a regular software [terminal emulator][2] instead of messing with these, but it's to know that you *can* use Serial Monitor if you're forced to do that for whatever reason.

  [1]: https://en.wikipedia.org/wiki/Serial_port#Conventional_notation
  [2]: https://en.wikipedia.org/wiki/List_of_terminal_emulators
  [3]: https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/
  [4]: https://github.com/arduino/Arduino/blob/1.8.19/build/shared/lib/preferences.txt#L274,L276
  [5]: https://docs.arduino.cc/hacking/software/Preferences


message:
Will many nrf24L01 radio modules running at the same time cause interference?

I am working on a battle bot type of project where their will be 4 transmitters communicating with 4 receivers attached to the robots in the 4 foot x 4 foot playing field. Are their any complications that will arise when trying to run many radio modules at the same time? Like relating to interference or noise? If so, what solutions or work-arounds exist for this problem?

body: Welcome Rishikesh, there is a great possibility they will have problems. Because I do not know the environment or what the hardware is configured I cannot properly answer your question without a lot more information. I can suggest Look here for some information: https://forum.arduino.cc/t/nrf24l01-transmission-problem/526158/3 Here is another link that will help: https://devzone.nordicsemi.com/f/nordic-q-a/38005/nrf24l01-communication-is-interfered-by-wifi I hope this helps.


body:
According to [HowToMechatronics][1], the NRF24L01 module can use 125 different channels which gives a possibility to have a network of 125 independently working modems in one place. Each channel can have up to 6 addresses.

I believe that as long as you agree a channel allocation amongst competitors there shouldn’t be problems.

For more information on channel setting see https://arduino.stackexchange.com/questions/79452/nrf24l01-channel-switching

  [1]: https://howtomechatronics.com/tutorials/arduino/arduino-wireless-communication-nrf24l01-tutorial/


message:
Problem with push button

I am making a project where if the push button is pressed, the LCD screen will show a message. But with many trial and errors, it doesn't give the right result.

Here is the circuit:
[![][1]][1]

Here is the code:
```
#include <LiquidCrystal.h>

// initialize the library by associating any needed LCD interface pin
// with the arduino pin number it is connected to
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
#define BUTTON 7
void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  pinMode(BUTTON, INPUT);
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 0);
  // print the number of seconds since reset:
  lcd.print("Press Button");
  lcd.setCursor(0,1);
  lcd.print("to make COFFEE");
  if (digitalRead(BUTTON) == HIGH) {
    lcd.clear();
    lcd.print("SENT TO MACHINE");
  }
}
```

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

body:
you should implement debouncing because when you press the button with your hand it will bounce and make the signal instable so no High/Low, here's the doc from Arduino:

https://www.arduino.cc/en/Tutorial/BuiltInExamples/Debounce


body:
It looks like you have several issues.

1. The positive and negative supply "rails" on your prototyping board are not connected together internally. You should add a positive jumper wire.

2. You are trying to detect when the button provides a `HIGH` logic level, but there is no possibility of doing so with the current "wiring".

One more thing that could help to determine this, or another possible issue, is a picture of your setup from a different angle so we can see exactly how that button, capacitor, and resistor are connected.

This is the area which would be nice to see from a different angle.

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

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


message:
POST request (HTTPClient) with ESP8266 not working on localhost (http code = -1)

I've been looking around for a solution, but couldn't manage to find one. I'm looking to send a post request from an ESP8266 on a local API.
Here is my code :
```
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

String ssid = "HUAWEI P30 lite";
String password = "testazerty";
String serverName = "http://192.168.56.1:3030/drink/voltron";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
}

void loop() {

    if(WiFi.status()== WL_CONNECTED){
      WiFiClient client;
      HTTPClient http;

      http.begin(client, serverName);

      http.addHeader("Content-Type", "application/json");
      int httpResponseCode = http.POST("{\"city\":\"toronto\"}");

      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);

      http.end();
  }
}
```

Both my computer and ESP8266 are connected to my phone network (HUAWEI).

192.168.56.1 is the IP of my computer.

API is running, and I can successfully make the request from postman (see image below).

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

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

It always return -1 as http code. I activated debug level HTTP_CLIENT, here is what I have on the serial monitor :

```
11:07:41.645 -> SDK:2.2.2-dev(38a443e)/Core:3.0.2=30002000/lwIP:STABLE-2_1_2_RELEASE/glue:1.2-48-g7421258/BearSSL:6105635
11:07:41.645 -> fpm close 1
11:07:41.645 -> mode : sta(30:83:98:b1:da:62)
11:07:41.645 -> add if0
11:07:41.645 -> Connecting
11:07:42.160 -> .....scandone
11:07:45.348 -> state: 0 -> 2 (b0)
11:07:45.348 -> .state: 2 -> 3 (0)
11:07:45.441 -> state: 3 -> 5 (10)
11:07:45.441 -> add 0
11:07:45.441 -> aid 6
11:07:45.441 -> cnt
11:07:45.441 ->
11:07:45.441 -> connected with HUAWEI P30 lite, channel 6
11:07:45.441 -> dhcp client start...
11:07:45.864 -> ....ip:192.168.43.88,mask:255.255.255.0,gw:192.168.43.1
11:07:47.870 -> .
11:07:47.870 -> Connected to WiFi network with IP Address: 192.168.43.88
11:07:47.870 -> [HTTP-Client][begin] url: http://192.168.56.1:3030/drink/voltron
11:07:47.870 -> [HTTP-Client][begin] host: 192.168.56.1 port: 3030 url: /drink/voltron
11:07:47.870 -> [HTTP-Client][sendRequest] type: 'POST' redirCount: 0
11:07:53.021 -> [HTTP-Client] failed connect to 192.168.56.1:3030
11:07:53.021 -> [HTTP-Client][returnError] error(-1): connection failed
11:07:53.021 -> HTTP Response code: -1
11:07:53.021 -> [HTTP-Client][end] tcp is closed
```

body:
**TLDR**:

This is a networking problem, not a programming problem. Try changing your subnet mask to 255.255.0.0 on your router/network configuration, or make sure they're actually connected to the same router. If different routers, try to change one to a "Wireless Access Point" configuration. If you can't get them on the same network, you will have to expose your API to the Internet.

**Long version:**

You are on different subnets. Your API IP address is 192.168.56.1 and your device IP address is 192.168.43.88, but your subnet mask is 255.255.255.0. That puts these devices on separate subnets within the network.

There are a lot of complicated explanations of subnets and subnet masks on the internet. I linked one of the better ones below. Technically, you are not just on different subnets but on different networks entirely. You have a 192.x.x.x IP address, making it a Class C network. That makes your address pattern one of "network.network.network.node". Depending on your router configuration or other network hardware, you can upgrade it to a Class B network by customizing your subnet mask as 255.255.0.0 ("network.network.node.node"). Class B addresses might require a lot of customization on your end depending on your specific circumstances. By using a subnet mask of 255.255.0.0 on a Class B address, you classify the IP address parts .56.1 and .43.88 as being on the same network AND subnet. If you change it to Class B addressing without changing the subnet, the .56 will be one subnet and .43 will be a different subnet.

Sometimes this addressing is done automatically based on the installed hardware. This is especially problematic in home networks containing multiple wireless routers but connected to the same modem. Many home routers have a "Wireless Access Point" setting that removes a lot of the more complex router configuration. This _might_ convince your router(s) to put you onto the same subnet. If that works, you now have your devices able to connect locally! Additional router configuration might be required to expose ports for your API to incoming requests across subnets.

If your network class is being determined by your ISP and you can't get your devices onto the same network, you have to expose your API to the Wild Wild Web :D There are many services which allow for Dynamic DNS, but I'd suggest reading through https://www.ionos.com/digitalguide/server/tools/free-dynamic-dns-providers-an-overview/ and selecting one that meets your needs. This WILL require advanced router configuration to expose ports to the internet. *Please select a Dynamic DNS services that provides DDOS protection.* Once it is exposed, your ESP8266 can hit your API as it would any public API. *Please put authentication on your API.*

References:

 - Subnet explanation -
   http://www.steves-internet-guide.com/subnetting-subnet-masks-explained/
 - Dynamic DNS providers -
   https://www.ionos.com/digitalguide/server/tools/free-dynamic-dns-providers-an-overview/


message:
Noise in RF 434 transmitter and receiver

I'm working on RF transmitter and receiver modules using two Arduino UNOs. I'm getting an additional noise on the receiver side in serial.println.
To be more clear about the question. Hre is my transmitter code
```
// Include RadioHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// Include dependant SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

void setup()
{
    // Initialize ASK Object
    rf_driver.init();
    Serial.begin(9600);
}

void loop()
{

    const char *msg = "Hello World";
    rf_driver.send((uint8_t *)msg, strlen(msg));
    rf_driver.waitPacketSent();
    Serial.println((char *)msg);
    delay(1000);
}
```
Here is my receiver code

```
// Include RadioHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// Include dependant SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_driver;

void setup()
{
    // Initialize ASK Object
    rf_driver.init();
    // Setup Serial Monitor
    Serial.begin(9600);
}

void loop()
{
    // Set buffer to size of expected message
    uint8_t buf[11];
    uint8_t buflen = sizeof(buf);
    // Check if received packet is correct size
    if (rf_driver.recv(buf, &buflen))
    {

      // Message received with valid checksum
      Serial.print("Message Received: ");
      Serial.println((char*)buf);
    }
}
```
And here is my Serial monitor in receiver side
[![enter image description here][1]][1]

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

So, can somebody help me to sort out this issue

body:
You're treating a raw buffer as a string.

In C a string is an array of characters (11 in your case) terminated by a NULL character.  You receive 11 bytes into an 11 byte array and then try and print it - without any terminating character - so the output "overruns" into the memory following your array.

You need a buffer of 12 bytes not 11, and you have to make sure that the 12th byte (byte number 11) is zero.

Or use `Serial.write(buf, buflen);` function to write exactly 11 bytes to the serial.


message:
How to configure 16x2 character LCD to work with 8bit?

I have the [LiquidCrystal][1] library installed but all the examples are for 4bit connection, I want to drive the LCD with 8bit.

In [LiquidCrystal.cpp][2] file it says;

> When the display powers up, it is configured as follows:
>
> DL = 1;  8-bit interface data

But what's is the function, should it be like this: `LiquidCrystal DL(1);`? where and how should I call `DL = 1;`?

  [1]: https://github.com/arduino-libraries/LiquidCrystal
  [2]: https://github.com/arduino-libraries/LiquidCrystal/blob/master/src/LiquidCrystal.cpp

body:
You don't "do" anything to enable 8 bit. As it says *when the device powers up the DL bit in the configuration is already set, enabling 8 bit*.

You just need to wire it for 8 bit and specify all 8 bits of wiring in the constructor.

The manual entry for the constructor shows you what parameters you can specify:

* https://www.arduino.cc/reference/en/libraries/liquidcrystal/liquidcrystal/


message:
Connect an MPX10DP Pressure Sensor to an Arduino Mega 2560

I'm literally new to using Arduino, i am trying to build a Pitot Tube to measure airspeed using an MPX10DP differential pressure sensor and i am working with an Arduino Mega 2560.

Honestly, i have studied some tutorials of people building a Pitot Tube but the pressure sensors they use are not available in my region, the only pressure that i could afford is the MPX10DP but i am not sure of how to connect it to my arduino and make it get values.

Can someone help me or guide me a bit?

body: That part was originally introduced by Motorola many years ago. It is a silicon strain gauge in a bridge configuration. You need an external amplifier as it only has maybe 50 mVdc output depending on your circuit. It is a relative output voltage depending on how you excite it. The one you have is a differential unit, they also made absolute and gauge units as well.  There were many application notes published on the MPX family of pressure transducers. You may have to look in the Motorola archives to find them. The voltage will be either + or - from your reference point depending on what the differential pressure is. They are not temperature compensated so you need to design that into your circuit as well.


message:
USB serial port no longer detected after successful upload

I successfully uploaded a sketch to my Arduino Micro using the USB serial port but if I try to change the sketch that port is not available. The sketch I uploaded on the Micro runs fine when I plug in the USB cable. The ports shown are /dev/cu.Bluetooth-Incoming-Port and /dev/cu.wlan-debug. If I plug in a different chip the port is there. What would cause it to disappear for the Micro?

body: Problem fixed by following suggestion from namakada81 "Open an empty arduino sketch, select the pro micro and no port, click upload and as soon as the ide says "uploading" reset the arduino


message:
Why am I reading only zeroes from PORTB?

I am using a custom Arduino Nano compatible board with an Atmel 328P.  I am externally changing the values applied to several pins on PORTB.  I expect to be able to read the values of these pins (low or high) but I always read zeroes.  However, the pin change interrupt is called.  What do I need to do to read values from PORTB?

Supply voltage is 5 volts.  Pin applied high voltage is 3.3 volts.

With the below code, when I change the voltage applied to a pin, LED1 flashes but LED2 does not.

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

#define LED1_PORT                           (PORTD)
#define LED1_PIN_bm                         (_BV(4))         //D1, white

#define LED2_PORT                           (PORTD)
#define LED2_PIN_bm                         (_BV(3))         //D2, red

volatile bool g_bValueChanged = 0;

void setup()
{
  DDRB = 0;                     //set all as inputs
  PCMSK0 = 0xfb;                //exclude 1 pin because of noise
  PCICR |= (1 << PCIE0);        //enable pin change interrupt 0 (for pins PB0..7)

  sei();
}

uint8_t g_valuePrevious = 0;

void loop()
{
  if (g_bValueChanged)
  {
    g_bValueChanged = false;

    LED1_PORT |= LED1_PIN_bm;
    delay(40);
    LED1_PORT &= ~LED1_PIN_bm;
    delay(40);
  }

  uint8_t value = PORTB;
  if (value != g_valuePrevious)
  {
    g_valuePrevious = value;

    LED2_PORT |= LED2_PIN_bm;
    delay(40);
    LED2_PORT &= ~LED2_PIN_bm;
    delay(40);
  }
}

ISR(PCINT0_vect)
{
    g_bValueChanged = true;
}
```

body:
The `PORTB` register is initialized by the hardware to zero. You never
write to this register, so it always stays zero.

Maybe you are mixing up `PORTB` and `PINB`:

* `PORTB` is the port **output** register, controlled by you
* `PINB` is the port **input** register, for which the bits
  corresponding to input pins are controlled by whatever drives those
  pins from the outside.


message:
Stopwatch stop/start button and reset

i am trying to make a stop watch with a stop/start button and a reset button

i have made this

    #include "RTClib.h"
    //Setup the Real Time Clock, DS3231
    RTC_DS3231 rtc;

    const byte SQWinput = 2;  // Must be External Interrupt

    volatile uint32_t  MillisecondsAtStartOfSecond = 0;

     unsigned long secondss=0 ;
     unsigned long minutess=0 ;

     unsigned long  hourss =0;
     unsigned long ms;

    boolean passed_second=true;
    boolean start=true;

    const byte ledPin = 13;

    const byte startButton = 7;

    const byte resetButton = 3;
    // Instantiate another Bounce object

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

    // The SQW pin, when set to 1 Hz mode, has a falling edge at the beginning of every second.
    void SQWFallingISR()
    {
      MillisecondsAtStartOfSecond = millis();
    }

    void setup ()
    {
      Serial.begin(9600); // Set Serial Monitor to 115200
      delay(200);

      pinMode(7, INPUT);
      digitalWrite(7, HIGH);
      pinMode(3, INPUT);
      digitalWrite(3, HIGH);

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

      if (rtc.lostPower())
      {
        Serial.println("RTC lost power, let's set the time!");
        // When time needs to be set on a new device, or after a power loss, the
        // following line sets the RTC to the date & time this sketch was compiled
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
        // This line sets the RTC with an explicit date & time, for example to set
        // January 21, 2014 at 3am you would call:
        // rtc.adjust(DateTime(2022, 4, 03, 21, 14, 0));
      }

      // Configure SQW pin on the DS3231 to output a 1Hz squarewave
      rtc.writeSqwPinMode(DS3231_SquareWave1Hz);

      // Get MillisecondsAtStartOfSecond on the falling edge of SQW.
      attachInterrupt(digitalPinToInterrupt(SQWinput), SQWFallingISR, FALLING);
    }

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

        ms = millis();

      noInterrupts();
      // How long since the second started?

      ms -= MillisecondsAtStartOfSecond;
      interrupts();

      if(digitalRead(7) != HIGH)   //START BUTTON
    {    displayTime (now, ms);
         Serial.println("stopwatch  ");

      Serial.print(hourss);
      Serial.print(':');
      Serial.print(minutess);
      Serial.print(':');
      Serial.print(secondss);
      Serial.print(':');
      Serial.println(ms);
    }

     if(digitalRead(3) != HIGH)   //RESET BUTTON
    {
         Serial.println("stopwatch  ");

      Serial.print(0);
      Serial.print(':');
      Serial.print(0);
      Serial.print(':');
      Serial.print(0);
      Serial.print(':');
      Serial.println(0);
      ms=0;
    }
     // displayTime (now, ms);
      /*Serial.println("stopwatch  ");

      Serial.print(hourss);
      Serial.print(':');
      Serial.print(minutess);
      Serial.print(':');
      Serial.print(secondss);
      Serial.print(':');
      Serial.println(ms);
      Serial.println("*********************************");
      Serial.println("Clock & Date  ");*/

      }

    void displayTime(DateTime &now, unsigned long ms)
    {
      ms = ms % 1000;  // Ignore full seconds

      Serial.print(now.year(), DEC);
      Serial.print('/');
      Serial.print(now.month(), DEC);
      Serial.print('/');
      Serial.print(now.day(), DEC);
      Serial.print(" (");
      Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
      Serial.print(") ");
      Serial.print(now.hour(), DEC);
      Serial.print(':');
      if (now.minute() < 10)
        Serial.print('0');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      if (now.second() < 10)
        Serial.print('0');
      Serial.print(now.second(), DEC);
     // Serial.println();
      Serial.print(':');
      if (ms < 100)
        Serial.print('0');
      if (ms < 10)
        Serial.print('0');
      Serial.print(ms, DEC);
      Serial.println();
      Serial.println("*********************************");

      if(ms>998) {
          secondss++;

      }
        if(secondss>59) {
         secondss=0;
          minutess++;

        }
        if(minutess>59) {
         minutess=0;
          hourss++;}

        }

but it is not working properly

the time is not incrementing after ms reaches 999

what is causing this?

body:
This code is quite confusing, as you are using both `millis()` and an
RTC as time sources.

Your problem may come from here:

```c++
ms -= MillisecondsAtStartOfSecond;
```

If the internal clock of your Arduino is a bit off, it may happen that
an RTC second is only 999 milliseconds from `millis()`. If that happens,
then `ms` will never hit 999, and will instead go straight from 998
to 0.

Or maybe it's here:

```c++
ms = ms % 1000;  // Ignore full seconds
// ...
if (ms > 998) {
    secondss++;
}
```

If you sketch is busy (maybe it is communicating with the RTC), it may
not run this code precisely at millisecond 999. And 999 is the only
value of `ms` that can possibly increment `secondss`.

For a stopwatch, you don't really need the RTC data. You can implement
it entirely on the basis of `millis()`, and that would simplify things:

```c++
bool stop_watch_running;
uint32_t stop_watch_last_update;
uint16_t stop_watch_ms;
uint8_t stop_watch_s;
uint8_t stop_watch_min;
uint8_t stop_watch_h;

void stop_watch_reset() {
    stop_watch_running = false;
    stop_watch_ms = 0;
    stop_watch_s = 0;
    stop_watch_min = 0;
    stop_watch_h = 0;
}

void stop_watch_start() {
    stop_watch_last_update = millis();
    stop_watch_running = true;
}

// Call this periodically.
void stop_watch_update() {
    if (!stop_watch_running)
        return;
    uint32_t now = millis();
    stop_watch_ms += now - stop_watch_last_update;
    stop_watch_last_update = now;
    while (stop_watch_ms >= 1000) {
        stop_watch_ms -= 1000;
        stop_watch_s++;
        if (stop_watch_s >= 60) {
            stop_watch_s = 0;
            stop_watch_min++;
            if (stop_watch_min >= 60) {
                stop_watch_min = 0;
                stop_watch_h++;
            }
        }
    }
}

void stop_watch_stop() {
    stop_watch_update();
    stop_watch_running = false;
}
```

If you know a bit about C++ classes, you may want to turn this into a
class, and replace the `stop_watch_` prefix with `StopWatch::`.


message:
Servo not moving with PIR motion sensor

I am working on this code to turn a servo when the PIR motion sensor detects no motion, but it is not working.
Some symptoms include:

 1. Servo is turning extremely slowly
 2. PIR is not turning the servo
 3. Servo is turning to incorrect angles

I have tried test programs, and when I type in the serial monitor, the servo turns (slowly and inaccurately) (I coded the serial monitor to do this). I have input from the PIR sensor but it is constantly high, even after waiting 2 minutes for it to initialize. My code and schematic are shown below.

[![Schematic][1]][1]

My code:

    #include <Servo.h>
    Servo servo;

    void setup() {
      // put your setup code here, to run once:
      servo.attach(13);
      pinMode(2, INPUT);
      Serial.begin(9600);
      Serial.println("Please wait");
      delay(60000);
    }

    void ifMos() {
      if (digitalRead(2) == HIGH) {
        int USER = 270;
      }
    }

    void loop() {
      // put your main code here, to run repeatedly:
      int USER = Serial.parseInt();
      servo.write(USER);
      Serial.println(USER);
      ifMos();
      delay(10000);
    }

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

body:
> firget about the servo for now ... write the simplest code that lights an LED when motion is detected –
-jsotola

It worked! Thank you so much.
All I had to do was add the servo library, write to the servo and upload it. Only 21 lines of code! Final code:

    #include <Servo.h>
    Servo servo;

    void setup() {
      // put your setup code here, to run once:
      pinMode(2, INPUT);
      pinMode(3, OUTPUT);
      servo.attach(13);
    }

    void loop() {
      // put your main code here, to run repeatedly:
      if(digitalRead(2) == HIGH) {
        digitalWrite(3, HIGH);
        servo.write(270);
      }
      else {
        digitalWrite(3, LOW);
        servo.write(0);
      }
    }

Thank you to everyone. This was my first time posting on stack exchange, and it was a huge success. Thank you again!


message:
pointing to array of chars

I'm trying to pass a list of files (located in sketch) to be read using a library I write. List can have different filenames and vary in number of files.

How to pass a this array to my library?

for example:

`char *parameterFiles[3] = {"/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"};`

**EDIT_1**

To explain more clearly what are my needs:
Let's say that my library has a class name `myIOT2`. That class holds an array that contains a list of all filenames (what shown here is not all class). Those names are different from one use of the library to the other, and it might not have all 4 files ( can be also 0 files stored ).

I wish to have the flexibilty not to hard code exact filename in advance, but to pass that array as part of my sketch, as show prior to EDIT_1.

    class myIOT2
    {
    public:
    const char *parameter_filenames[4] = {nullptr, nullptr, nullptr, nullptr};

    };

body:
You have to pass both a pointer to the list, and the length of the list
as an extra argument. The signature of the function may be something
like:

```c++
void processFiles(const char *fileList[], int fileCount);
```

Note that `const char *fileList[]` is just a fancy way of writing
`const char **fileList`. I find the former more readable, but that is
completely subjective.

Here is a small test code showing this in action:

```c++
void processFiles(const char *fileList[], int fileCount)
{
    for (int i = 0; i < fileCount; ++i) {
        Serial.print("Processing file ");
        Serial.println(fileList[i]);
    }
}

const char *parameterFiles[3] = {
    "/myIOT_param.json",
    "/myIOT2_topics.json",
    "/sketch_param.json"
};

void setup() {
    Serial.begin(9600);
    processFiles(parameterFiles, 3);
}

void loop() {}
```

Alternatively, you may put a “sentinel” at the end of the list: a null
pointer that signifies that the list ends there:

```c++
void processFiles(const char *fileList[])
{
    for (const char **p = fileList; *p; ++p) {
        Serial.print("Processing file ");
        Serial.println(*p);
    }
}

const char *parameterFiles[] = {
    "/myIOT_param.json",
    "/myIOT2_topics.json",
    "/sketch_param.json",
    nullptr
};

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

void loop() {}
```

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

**Edit**: Answering to EDIT\_1.

> [My library's] class holds an array that contains a list of all
> filenames

First of all, you have to decide who is responsible for storing those
file names: the library or its client. When you write:

```c++
const char *parameterFiles[3] = {
    "/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"
};
```

you are creating 4 arrays: an array of 3 pointers named
`parameterFiles`, and three arrays of characters holding the file names.
Note that those 3 arrays are _anonymous_: they are not array
variables. If the client code tries to pass this `parameterFiles` to
your library, the array identifier will decay to a pointer, and your
library will receive that pointer. What should it do with it?

1. The library could just keep a copy of the pointer. The client is then
   responsible for ensuring that it remains valid for as long as the
   library may need it. This practically implies that `parameterFiles`
   should be a global variable, and should not be modified once given to
   the library.

2. The library could make a copy of the array. Then the client is freed
   from this responsibility. However, it is still responsible for
   ensuring that the pointers that were copied from the array remain
   valid, i.e. that the file names stay in the same place in memory.

3. The library could copy the file names themselves. Then the client
   doesn't have any responsibility about keeping pointers valid.

If you choose option 2 or 3, the library will have to hold one or more
arrays. You will then have to choose whether you allocate them
statically, or dynamically with `new`. Dynamic allocation is more
efficient when the arrays can vary greatly in length, but it can raise
issues of memory fragmentation in RAM-constrained devices.

I cannot tell you which option is best: it depends on your use case. In
any case, whatever you choose, you should document it: the user of the
library should know whether they are responsible for keeping any
pointers valid.

In the following, I will assume option 2 with static allocation. This is
consistent with the code snippets in your question. Also, if the client
provides the file names as string literals, then pointers to these
strings remain always valid.

Here is a toy implementation of the `myIOT2` class, where the list of
file names is copied by the constructor into the class:

```c++
class myIOT2 : public Printable
{
public:
    static const int maxFileCount = 4;

    myIOT2(const char *fileList[], int count) {
        if (count > maxFileCount)
            count = maxFileCount;  // discard extra files
        fileCount = count;
        for (int i = 0; i < fileCount; i++)
            filenames[i] = fileList[i];
    }

    size_t printTo(Print& p) const {
        size_t count = p.print(F("myIOT2["));
        for (int i = 0; i < fileCount; i++) {
            count += p.print('"');
            count += p.print(filenames[i]);
            count += p.print('"');
            if (i < fileCount - 1)
                count += p.print(", ");
        }
        count += p.print(']');
        return count;
    }

private:
    const char *filenames[maxFileCount];
    int fileCount;
};
```

Note that, the array of file names being statically allocated, there is
a hard maximum on the number of files that can be stored. I made the
class `Printable` only for debugging convenience.

And here is an example of this class in use:

```c++
const int fileCount = 3;

const char *parameterFiles[fileCount] = {
    "/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"
};

myIOT2 iot(parameterFiles, fileCount);

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

void loop() {}
```

This test sketch prints:

```text
myIOT2["/myIOT_param.json", "/myIOT2_topics.json", "/sketch_param.json"]
```


message:
Arduino Uno Analog pot values are not smooth

I have tired Arduino smoothing example but mine analog value are not staying constant even when I don't rotate the potentiometer. I am mapping the values from 0 -> 1024 to 0-> 100. I have tried exponential filter also but the result is same.

Values change 2 to 3 point mostly. Any idea how can I make the readings much more smooth.

body:
There will always be noise in the output an [Analog to Digital Converter (ADC)][1].

> An ADC converts a continuous-time and continuous-amplitude analog
> signal to a discrete-time and discrete-amplitude digital signal. The
> conversion involves quantization of the input, so it necessarily
> introduces a small amount of error or noise.

All one can do is mitigate the noise.  Consider cleaning up your power supply.  Make sure your voltage reference is well filtered.  Inspect these power rails with an oscilloscope if one is available.  Also consider keeping all wiring as short as possible and avoid using [Bread Boards][2] as they tend to introduce noise in sensitive circuits.

When using [exponential averaging][3] consider the equation / code can be modified easily to accommodate very noisy signals at the sacrifice of responsiveness.  If the application can tolerate the delay, the decay of historical samples can be lowered such that what most consider noise can be filtered out.  One can do this by picking very small values for alpha in the following equation found on wikipedia.org:

[![enter image description here][4]][4]

  [1]: https://en.wikipedia.org/wiki/Analog-to-digital_converter
  [2]: https://www.adafruit.com/product/239
  [3]: https://en.wikipedia.org/wiki/Exponential_smoothing
  [4]: https://i.stack.imgur.com/qLMuv.jpg


message:
What does the .ino file extension mean

**What does the `.ino` file extension mean?**

We have `.cpp` meaning C++, `.py` meaning Python, `.exe` meaning executable and so-on.They're obvious. The `.pde` file type that sketches previously used, I think, comes from _processing development environment_ (the arduino IDE being based<sup>*<sup> on / inspired by [processing](https://processing.org)).  But what does `.ino` mean?

There's plenty that explains what such files are, but nothing explains what those three letters mean, if anything.

<sub>\* source [wikipedia](https://en.wikipedia.org/wiki/Arduino)</sub>

body:
> Ardu***ino***

That's all there is to say about that really.

---

As [commented in the source code](https://github.com/arduino/Arduino/blob/1.0/build/shared/revisions.txt#L5-L7)

> The file extension for sketches has changed from .pde to .ino, to avoid
  conflicts with the Processing software ("ino" are the last three letters
  in "Arduino").


body:
"Arduino" is an Italian word, and "ino" is the suffix which lends itself well to a filename extension.

From [Google Translate of Italian ino][1]:

> ino
>
> 1. Suffisso alterativo di aggettivi e sostantivi; nei primi ha valore diminutivo-vezzeggiativo, talvolta con sfumatura ironica ( biondino, carino ), oppure significa appartenenza etnica ( alessandrino, cadorino ), collegamento con materie ( argentino, salino ); nei secondi, oltre ad avere valore diminutivo-vezzeggiativo ( gattino, pensierino ), indica pure un mestiere ( ciabattino, tamburino ), uno strumento o arnese o apparecchio ( cerino, lavandino ); in alcuni casi è applicato a verbi ( imbianchino, accendino ).
> 2. In chimica organica, suffisso che nella nomenclatura ufficiale indica gli idrocarburi acetilenici, cioè gli alchini ( etino ).

> 1. Alterative suffix of adjectives and nouns; in the former it has a diminutive-pet name, sometimes with an ironic tinge (blond, cute), or it means ethnic affiliation (Alexandrian, Cadore), connection with materials (Argentine, saline); in the latter, in addition to having a diminutive-pet name (kitten, little thought), it also indicates a trade (cobbler, drummer), an instrument or tool or apparatus (match, sink); in some cases it is applied to verbs (painter, lighter).
> 2. In organic chemistry, suffix that in the official nomenclature indicates acetylenic hydrocarbons, i.e. alkynes (ethin).

  [1]: https://translate.google.com/?sl=it&tl=en&text=ino

1
Suffisso alterativo di aggettivi e sostantivi; nei primi ha valore diminutivo-vezzeggiativo, talvolta con sfumatura ironica ( biondino, carino ), oppure significa appartenenza etnica ( alessandrino, cadorino ), collegamento con materie ( argentino, salino ); nei secondi, oltre ad avere valore diminutivo-vezzeggiativo ( gattino, pensierino ), indica pure un mestiere ( ciabattino, tamburino ), uno strumento o arnese o apparecchio ( cerino, lavandino ); in alcuni casi è applicato a verbi ( imbianchino, accendino ).
2
In chimica organica, suffisso che nella nomenclatura ufficiale indica gli idrocarburi acetilenici, cioè gli alchini ( etino ).&op=translate


message:
SNMP Manager - Multiple IP address -issue

I have multiple SNMP devices on the same network and I am trying to request, *via OID numbers*, each SNMP device and assign the **response** into an array.
When I request a single IP, I get the correct response as expected.

**Problem:**
If I run the same code in a for loop (*multiple ip's 192.168.1.150, 192.168.1.151, etc*), I get duplicate info.
*I might be using the wrong callback method, or the SNMP Manager can not dynamically change the ip address..*
I have researched a lot of topics and tried many avenues, but I can't get past this point.

**If anyone can assist me, it would help a lot!!**

__________

**Example Output:**
*The model name and serial should be different on each ip*
```
----------------------
192.168.8.150
KONICA MINOLTA bizhub C658
A79J021002278
----------------------
192.168.8.151
KONICA MINOLTA bizhub C658
A79J021002278
----------------------
192.168.8.152
KONICA MINOLTA bizhub C658
A79J021002278
----------------------
192.168.8.153
KONICA MINOLTA bizhub C658
A79J021002278
----------------------
192.168.8.154
KONICA MINOLTA bizhub C658
A79J021002278
```

**Here is the code**
```
#if defined(ESP8266)
#include <ESP8266WiFi.h> // ESP8266 Core WiFi Library
#else
#include <WiFi.h>        // ESP32 Core WiFi Library
#endif

#include <string.h>
#include <WiFiUdp.h>
#include <Arduino_SNMP_Manager.h>

//************************************
//* Your WiFi info                   *
//************************************
const char *ssid = "Workmin_Sales";
const char *password = "workmin92429242";
//************************************

//************************************
//* SNMP Device Info                 *
//************************************
const char *community = "public";
const int snmpVersion = 1; // SNMP Version 1 = 0, SNMP Version 2 = 1
// OIDs
const char *oidModelName = ".1.3.6.1.2.1.25.3.2.1.3.1";               // OctetString SysName
const char *oidSerialNumber = ".1.3.6.1.2.1.43.5.1.1.17.1";              // OctetString SysName
//************************************

//************************************
//* Settings                         *
//************************************
int pollInterval = 20000; // delay in milliseconds
//************************************

//************************************
//* Initialise                       *
//************************************
// Variables
char *modelNameArray[5];
char *serialNumberArray[5];

char modelName[50];
char *modelNameResponse = modelName;
char serialNumber[50];
char *serialNumberResponse = serialNumber;

// Blank callback pointer for each OID
ValueCallback *callbackSerialNumber;
ValueCallback *callbackModelName;
//************************************

unsigned long pollStart = 0;
// SNMP Objects
WiFiUDP udp;                                           // UDP object used to send and receive packets
SNMPManager snmp = SNMPManager(community);             // Starts an SMMPManager to listen to replies to get-requests
SNMPGet snmpRequest = SNMPGet(community, snmpVersion); // Starts an SMMPGet instance to send requests

//************************************
//* Function declarations            *
//************************************
void getSNMP();
//************************************

void setup()
{
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to SSID: ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  snmp.setUDP(&udp); // give snmp a pointer to the UDP object
  snmp.begin();      // start the SNMP Manager
}

void loop()
{
  // put your main code here, to run repeatedly:
  snmp.loop();
  if (millis() - pollStart >= pollInterval)
  {
    pollStart += pollInterval; // this prevents drift in the delays

    getSNMP();
    // doSNMPCalculations(); // Do something with the data collected
  }
}

void getSNMP()
{
  for (int i = 0; i < 5; i++) {
    // Build a SNMP get-request add each OID to the request
    IPAddress router(192, 168, 8, i + 150);

    // Get callbacks from creating a handler for each of the OID
    callbackSerialNumber = snmp.addStringHandler(router, oidSerialNumber, &serialNumberResponse);
    callbackModelName = snmp.addStringHandler(router, oidModelName, &modelNameResponse);

    snmpRequest.addOIDPointer(callbackSerialNumber);
    snmpRequest.addOIDPointer(callbackModelName);

    snmpRequest.setIP(WiFi.localIP()); // IP of the listening MCU
    // snmpRequest.setPort(501);  // Default is UDP port 161 for SNMP. But can be overriden if necessary.
    snmpRequest.setUDP(&udp);
    snmpRequest.setRequestID(rand() % 5555);
    snmpRequest.sendTo(router);
    snmpRequest.clearOIDList();
    delay(1000);

    modelNameArray[i] = modelNameResponse;
    serialNumberArray[i] = serialNumberResponse;
    Serial.print("192.168.8.");
    Serial.println(i + 150);
    Serial.println(modelNameArray[i]);
    Serial.println(serialNumberArray[i]);
    Serial.println("----------------------");
  }
}
```

body:
You're not storing the data in your array, you're storing a pointer to the storage where the callback stores its data. So every entry gets the same pointer to the same storage, which gets its content changed. So all the array entries see the same (last) content.

It took me many years to properly get my head around C pointers.

Instead of just assigning (`=`) the value you need to *copy the content*.

Since you just have an array of pointers that can be done with `strdup()` which allocates a new block of RAM and copies the contents to it. Be sure to use `free()` on that allocated block when you've finished with it.

* [strdup](https://man7.org/linux/man-pages/man3/strdup.3.html)


body:
I think I see multiple issues with the example above.
1. The `snmpRequest.sendTo(router);` will send the SNMP packet out. But you need to call `snmp.loop()` to read the incoming replies to your request. So you need to restructure the code so that you can call loop() potentially many times in order to wait for the incoming replies before you read and store the values.
2. `serialNumberResponse` is a pointer to a character array `serialNumber` (likewise for the model). If the callback returned serial number `123ABC` the first time, and the next device was called `1XD` then the array would have a value of `1XDABC`. So if you plan to re-use the variable, you'll need to clear it between uses something like: `memset(serialNumber, 0, sizeof(serialNumber));`
3. As you might not always get a successful response, or a response within the time allowed, the value may be still blank, if you're looking to store the values in another variable, you may want to ensure they aren't empty, as this would overwrite the value you may have had back on a previously successful call. If you were dealing with numbers, the value might also be that of a previous call. As pointed out in the answer above, you're dealing with pointers, so if you want to store the value you need to copy the value out, otherwise, you'll just point to the same pointer.

I hope this helps point you in the right direction. I've added an example to the library to show how multiple devices can be queried and the results stored in an array, see: https://github.com/shortbloke/Arduino_SNMP_Manager/tree/master/examples/ESP_Multiple_SNMP_Device_Polling. It stores the responses directly into the array. This might cause values to be cleared in the event of a timeout, I've not tested it completely.

Martin