message:
ESP32 SocketIO Client is not connecting to Flask-SocketIO Server

I'm trying to connect a ESP32 client using `SocketIO` with a `Flask-SocketIO` server and it's not getting connected.
The server uses SSL. The local server address is `https://192.168.1.137:3000`.Is the `https` causing issue here?

The following is the output from the ESP32 in the serial monitor. Note that esp32 successfully connects to the wifi.

    > ["myEvent",{"now":95506}]
    > [IOc] Disconnected!
    > [IOc] Disconnected!
    > [IOc] Disconnected!
    > ...

Esp32 code:

    /*
    * WebSocketClientSocketIOack.ino
    */

    #include <Arduino.h>

    #include <WiFi.h>
    #include <WiFiMulti.h>
    #include <WiFiClientSecure.h>

    #include <ArduinoJson.h>

    #include <WebSocketsClient.h>
    #include <SocketIOclient.h>

    WiFiMulti WiFiMulti;
    SocketIOclient socketIO;

    #define USE_SERIAL Serial

    void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
        switch(type) {
            case sIOtype_DISCONNECT:
                USE_SERIAL.printf("[IOc] Disconnected!\n");
                break;
            case sIOtype_CONNECT:
                USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);

                // join default namespace (no auto join in Socket.IO V3)
                socketIO.send(sIOtype_CONNECT, "/");
                break;
            case sIOtype_EVENT:
            {
                char * sptr = NULL;
                int id = strtol((char *)payload, &sptr, 10);
                USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
                if(id) {
                    payload = (uint8_t *)sptr;
                }
                DynamicJsonDocument doc(1024);
                DeserializationError error = deserializeJson(doc, payload, length);
                if(error) {
                    USE_SERIAL.print(F("deserializeJson() failed: "));
                    USE_SERIAL.println(error.c_str());
                    return;
                }

                String eventName = doc[0];
                USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());

                // Message Includes a ID for a ACK (callback)
                if(id) {
                    // creat JSON message for Socket.IO (ack)
                    DynamicJsonDocument docOut(1024);
                    JsonArray array = docOut.to<JsonArray>();

                    // add payload (parameters) for the ack (callback function)
                    JsonObject param1 = array.createNestedObject();
                    param1["now"] = millis();

                    // JSON to String (serializion)
                    String output;
                    output += id;
                    serializeJson(docOut, output);

                    // Send event
                    socketIO.send(sIOtype_ACK, output);
                }
            }
                break;
            case sIOtype_ACK:
                USE_SERIAL.printf("[IOc] get ack: %u\n", length);
                break;
            case sIOtype_ERROR:
                USE_SERIAL.printf("[IOc] get error: %u\n", length);
                break;
            case sIOtype_BINARY_EVENT:
                USE_SERIAL.printf("[IOc] get binary: %u\n", length);
                break;
            case sIOtype_BINARY_ACK:
                USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
                break;
        }
    }

    void setup() {
        //USE_SERIAL.begin(921600);
        USE_SERIAL.begin(115200);

        //Serial.setDebugOutput(true);
        USE_SERIAL.setDebugOutput(true);

        // USE_SERIAL.println();
        // USE_SERIAL.println();
        // USE_SERIAL.println();

          // for(uint8_t t = 4; t > 0; t--) {
          //     USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
          //     USE_SERIAL.flush();
          //     delay(1000);
          // }

        WiFiMulti.addAP("ssid", "mypass");

        //WiFi.disconnect();
        while(WiFiMulti.run() != WL_CONNECTED) {
            delay(100);
        }

        String ip = WiFi.localIP().toString();
        USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());

        // server address, port and URL
        socketIO.begin("192.168.1.137", 3000, "/socket.io/?EIO=4");

        // event handler
        socketIO.onEvent(socketIOEvent);
    }

    unsigned long messageTimestamp = 0;
    void loop() {
        socketIO.loop();

        uint64_t now = millis();

        if(now - messageTimestamp > 2000) {
            messageTimestamp = now;

            // creat JSON message for Socket.IO (event)
            DynamicJsonDocument doc(1024);
            JsonArray array = doc.to<JsonArray>();

            // add event name
            // Hint: socket.on('event_name', ....
            array.add("myEvent");

            // add payload (parameters) for the event
            JsonObject param1 = array.createNestedObject();
            param1["now"] = (uint32_t) now;

            // JSON to String (serializion)
            String output;
            serializeJson(doc, output);

            // Send event
            socketIO.sendEVENT(output);

            // Print JSON for debugging
            USE_SERIAL.println(output);
        }
    }

Server code (Removed unrelated parts):

 from flask import Flask, render_template, Blueprint, current_app, request, session, url_for, render_template
 from flask_socketio import SocketIO, emit

    from threading import Thread
    from queue import Queue
    import logging

    loggerPath = baseUrl + "logs/appLog.log"
    os.makedirs(os.path.dirname(loggerPath), exist_ok=True)
    with open(loggerPath, "a") as f:
     logging.basicConfig( level=logging.INFO,
      # format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
      format='%(levelname)s - %(message)s',
      filename=loggerPath
     )
 bp = Blueprint('audio', __name__, static_folder='static',
    template_folder='templates')
 app = Flask(__name__)

 async_mode = "threading"

 socketio = SocketIO(app, cors_allowed_origins="*", async_mode=async_mode)

    @socketio.on('myEvent')
    def test_connect(data):
     logging.info("receiving")

 def runApp():
  try:
   certificatePath = os.getenv('BASE_URL')+"SSL/"
   key = certificatePath+"localhost.key"
   certificate = certificatePath+"localhost.crt"
   context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
   context.load_cert_chain(certificate, key)
   ip = socket.gethostbyname(socket.gethostname())
   socketio.run(app, host=ip, port=3000,ssl_context=context)
  except Exception as e:
   logging.error("Exception occurred in: "+__file__, exc_info=True)

 q = Queue()
 t = Thread(target=wrapper, args=(q, runApp), daemon=True)
 t.start()

body:
This is version Socketio issue,I have successfully connected .
This installed version
Werkzeug 2.0.0
Flask 2.3.3
Flask-SocketIO 4.3.1
python-engineio 3.13.2
python-socketio 4.6.0


sender: user

message:
Strtok operations on Arduino Zero seem to fail in runtime

I am trying to test functionality of strtok() on a new piece of hardware, as I ran out of memory to develop on my Nano. This is a basic example from the internet involving tokenizing the string and reporting the tokenized entries via SerialUSB. I'm running a [Rocketscream V3][1] (Arduino Zero ATSAMD21G18A).

    #include <string.h>

    void setup() {
      char *token;
      char *mystring = "apples,pears,bananas";

      SerialUSB.begin(9600);
      while (!SerialUSB) { }

      SerialUSB.print("Serial established");

      token = strtok(mystring, ",");

      while (token != NULL) {
        SerialUSB.println(token);
        token=strtok(NULL, ",");
      }
    }

The code works as expected on my Nano (with Serial instead of SerialUSB), but while it does compile for the Arduino Zero, the Zero never makes it past printing "Serial established". I have confirmed this by including code (serial print, LED flashing) past the tokenization parts, and these are never executed. The loop() function is never reached, it seems to halt at "token = strtok(mystring, ",");".

I cannot think of a simpler possible way to test strtok(), but it's just not working. Any help would be appreciated.

  [1]: https://www.rocketscream.com/blog/product/mini-ultra-pro-v3-with-radio/

sender: assistant

body:
`strtok` works by modifying the source string. Your test string points to a constant string.

```
  char *mystring = "apples,pears,bananas";
```

This particular platform may put that into read-only memory. Try instead as your test string:

```
  char mystring [] = "apples,pears,bananas";
```

I don't have a Zero to test it on, but in any case using `strtok` on a const string is <s>not recommended</s> forbidden.

---

If you turn warnings on for the compiler (File -> Preferences) you see this:

     In function 'void setup()':
     warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
       char *mystring = "apples,pears,bananas";

If you are doing something "forbidden" then don't expect good results.


message:
Display images on Arduino LCD screen from PC

I am new to arduino and I am wondering if it is possible to store image data on my computer and send it to my arduino over the USB cable (which is also used for power) to display on a TFT LCD display I have hooked up. All the tutorials I see involve using an SD card to preload the image data on there beforehand.

Still, my display doesn't have an sd card slot, nor is it practical for my application as the images I want to display will be determined during runtime. I have sent small pieces of data over the COM port to my arduino from my PC but I don't know how I could do it with potentially large image data. The arduino will be plugged into my computer 24/7. If this is possible could I get a little guidance on where to start?  Thank you

body:
You could "stream" the data from the PC to the LCD, which means you wouldn't need to store it (or maybe store a line or so).

Without knowing which Arduino and which LCD it is hard to give more advice than that.


body:
There are so many different LCDs that with out specifying a specific LCD only very general answers can be provided that may be of limited value.

* Just about all Arduinos can handle an [Alpha Numeric LCDs][1]. But these have very limited graphics, if any.

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

* Most can handle low resolution [B&W Graphics LCDs][3].

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

 * Most can handle sending geometric shapes and alpha numeric to [(smart) Serial Port Color LCDs][5]. Only some Arduinos will be able to handle sending arbitrary images (like a photograph) to (smart) Serial Port Color LCDs.

[![enter image description here][6]][6]

And few will be able to handle sending data to a common TTL or [LVDS][7] Color LCDs.

[![enter image description here][8]][8]

  [1]: https://www.adafruit.com/product/772
  [2]: https://i.stack.imgur.com/bOL0K.jpg
  [3]: https://www.sparkfun.com/products/710
  [4]: https://i.stack.imgur.com/HTh7G.jpg
  [5]: https://www.adafruit.com/product/1770
  [6]: https://i.stack.imgur.com/jPLFa.jpg
  [7]: https://www.adafruit.com/product/4337
  [8]: https://i.stack.imgur.com/KcsVd.jpg


body:
Since you don't give a clue about the TFT you have in mind, I'll try to describe the process using the following assumptions about the TFT that have to be true for the rest to work:

* one full frame of pixel data for the TFT used would not fit into the Arduinos RAM, but one line of that frame will,
* the pixel data can be sent line by line to the TFT without a need to start the next line inside a certain timeframe (i.e. you could, in theory, just tell the TFT to update line 42 out of order, as an example),
* the TFT has its own way of remembering its display data (i.e. does not need a continuous refresh 60 times per second).

In this scenario, your image processing pipeline looks like this:

 * A program running on your PC decompresses (and possibly resizes) the image file in order to get access to the raw pixel data as it would be displayed on the TFT. This means that this program needs to know the resolution and "data feeding order" of your TFT.
 * This process then takes one line of the raw pixel data and converts it into a data package to be sent over the serial port. You will need to devise a communication protocol here that your Arduino sketch can work with. The easiest, but not most efficient, way would be to convert it into Base64, because libraries for that exist in practically every language and platform and you are then able to use text-based delimiters like a line break to mark the end of a pixel data line. (Sending binary data is more efficient, but harder and more prone to sychronization errors, because you have no in-band signalling of "end of data line".)
 * Your Arduino sketch reads that data package (if Base64-encoded: by using `Serial.read` until you encounter a line break) and converts it back to raw pixel data, in whatever format your TFT (or library for that TFT) needs the data (it might require the color format in e.g. GRB instead of RGB).
 * This raw pixel data line is then sent to the TFT.

You will have to determine the baud rate you can send over your serial link (determined by maximum baud rates of both PC and Arduino, and sometimes the cable quality in between). Keep in mind that a serial connection is slow; you probably will be able to watch the image rendering on the TFT line by line.

You may be able to make this more efficient by employing something like RLE (Run-Length Encoding) on the pixel data sent over the serial line, but that would be another iteration of your protocol.


message:
Reading from DHT22 with Arduino, powered by external source

I have the following situation. When I power my DHT22 with the 3.3V from the Arduino UNO (and Ground it there), then I can read the data perfectly fine using the DHT library from Adafruit.

However, when I connect the DHT22 to my own external power supply (and respective ground), it fails. The reason for using this external power supply is so I can hook it up to a ESP8266 later.

The power supply I build uses a 5V adapter, then an LD33V converter and (just for experimentation) an 100nF capacitor to reduce any noise on the line.
I measured this external power supply and it indeed gives off 3.3V after the LD33V. I check the datasheet of the LD33V and it should be able to 'give' 5mA, whereas the DHT22 needs less than 1mA for operation.

I don't know where to look at this moment. Can someone point me in the right direction? Much appreciated :)

Cheers

body: Have you connected the external power supply ground to the Arduino's ground? If not, one is "floating" with respect to the other. But they need to have the same reference - the ground sides of their power supplies.


message:
Issues using mini microphone module off AliExpress

I have been trying to get a mini microphone module with an inbuilt microphone module I got from AliExpress to my Arduino to confirm if it is working. It was a four pin microphone with pins labeled V, L, and two G pins. The V represents voltage in and the L represents audio output positive.

Here is the link to the microphone:
<https://www.aliexpress.com/item/1005004277353392.html?spm=a2g0o.productlist.main.23.61e36f2fBMHvFk&algo_pvid=15b05576-cd73-4eb7-a476-4503b8a706a7&algo_exp_id=15b05576-cd73-4eb7-a476-4503b8a706a7-11&pdp_npi=3@dis!USD!0.54!0.39!!!!!@211bf3f716869249882567444d07ba!12000028601598840!sea!NG!4345576938&curPageLogUid=plaZEQWq7SRB>

However, when I ran the code to check whether it works the value does not change that much, Is there something I'm doing wrong (I'm a beginner btw) or is the microphone not just working?

My code
```
const int audioPin = A0; // Analog input pin connected to the microphone module output

void setup() {
  Serial.begin(9600); // Initialize the Serial Monitor
}

void loop() {
  int audioValue = analogRead(audioPin); // Read the analog value from the microphone module

  Serial.println(audioValue); // Print the analog value to the Serial Monitor

  // Add a small delay to control the rate of readings
  delay(10);
}
```

I connected the output (L) to A0 and connected both the G pins to the arduino ground, I connected the V pin to the 3.3V pin on the Arduino Uno.

body: Have you checked to see if it is a hardware problem? It could be the fact that it is just off AliExpress. Usually, the display images are better than the actual product and if this is true, you can see a few bad soldering connections. I might want to go over some of them with a soldering iron.


message:
Arduino Uno R3 assembly code to push a button and turn on a LED

I've been trying this for days without success...

I need to turn on a LED on portb when a button in portd is pushed. Cabling works, I've tested it with Arduino IDE and it works like a charm.

This is what I got so far:
 ```
.global main
.equ LED, PB5
.equ BUTTON, PD3
main:
    ldi r22,0xff                    ;all bits in portb are output
    out _SFR_IO_ADDR(DDRB),r22
    ldi r21,0x00                    ;all bits in portd are input
    out _SFR_IO_ADDR(DDRD),r21
    ldi r19, 0b00000000             ;unpushed button
    ldi r18, 0b00100000             ;pushed button
    eor r16, r16
loop:
    out BUTTON, r16                 ;read button to r16
    cp r16, r18                     ;compare r16 with r19 (button on)
    cbi _SFR_IO_ADDR(PORTB),LED
    breq loop                       ;go back to loop
    sbi _SFR_IO_ADDR(PORTB),LED     ;if z=1, turn led on turn led on
    rjmp loop                       ;back to loop
```

It is much easier with `sbis`, if I got it right...

```
#include <avr/io.h>
.equ LED, PB5
.global main
ldi r16,0xff
out _SFR_IO_ADDR(DDRB),r16
ldi r16,0x00
out _SFR_IO_ADDR(DDRD),r16

main:
 sbis portd, 3
 rjmp ledoff
 ldi r16,0xff
    sbi _SFR_IO_ADDR(PORTB),LED   ; turn on led
 rjmp main
ledoff:
 ldi r16,0x00
    cbi _SFR_IO_ADDR(PORTB),LED   ; turn off led
 rjmp main
```
But I got this error compiling:
```
.pio\build\uno\src\main.o: In function `main':
(.text+0x8): undefined reference to `portd'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
```

body:
This line:

> ```lisp
>    ldi r18, 0b00100000             ;pushed button
> ```

does not match the definition of `BUTTON`. You are setting bit 5 of
the register, whereas the button is on bit 3. In order to avoid
this kind of error, I would rather write

```lisp
   ldi r18, _BV(BUTTON)            ;pushed button
```

Then, here:

> ```lisp
>    out BUTTON, r16                 ;read button to r16
> ```

you are not reading anything: you are writing somewhere. I guess you
mean:

```lisp
   in r16, _SFR_IO_ADDR(PIND)      ;read button to r16
```

Note that this reads the whole port at once. If you are only interested
in one bit, you should then

```lisp
   andi r16, _BV(BUTTON)           ;keep only the relevant bit
```

before the comparison.

One last thing: you may want to read about the `sbis` and `sbic`
instructions: they could simplify the code you have here.

------------------------------------------------------------------------
**Edit**: answering the updated question.

> undefined reference to \`portd'

This is because there is no such thing as “portd”. You mean
`_SFR_IO_ADDR(PORTD)`. Well, no, you should actually use
`_SFR_IO_ADDR(PIND)`, as this is the port _input_ register, whereas
`PORTD` is the _output_ register.

A couple of extra notes:

 * Do not put code before `main`: it will not be executed, as the C
   runtime jumps to `main` after its initialization.
 * The instructions `ldi r16, …` within the main loop serve no purpose:
   you are not using this register after the program initialization.


message:
With reference to Arduino Keyboard library, it does not have a keymap for UK keyboard, has anyone created a KeyboardLayout_en_UK.cpp file for this?

With reference to the Arduino Keyboard library, it does not have a keymap for the UK keyboard. I have tried to find a keyboard map that shows the hex value for the UK keyboard but I didn't have any luck.

If you look in the Arduino Keyboard library: `Arduino\libraries\Keyboard\scr\KeyboardLayout_en_US.cpp`
it has some other languages but no keyboard layout for a UK keyboard.

It does say somewhere I think on GitHub that a keyboard layout file can be added, but where can I get that file or how can I create that file?
Has anyone already created a KeyboardLayout_en_UK.cpp file I could use, please?

body:
I am not aware of a UK layout file for the Arduino Keyboard library. The
library itself does not have such a layout, and a Web search returned
nothing. You may consider creating this layout yourself. [The
documentation of `Keyboard.begin()`][begin] states:

> Custom layouts can be created by copying and modifying an existing
> layout. See the instructions in the Keyboard library’s
> KeyboardLayout.h file.

The file [KeyboardLayout.h][header] does indeed have detailed
instructions for this. Are they clear enough? If not, please tell me: I
wrote those instructions, and I may try to update them if something in
them is confusing.

Do you feel like trying to create this layout yourself? If so, it would
be nice if you could submit it to the official library as a pull
request. This way other users of the library may benefit from your work.
If you don't feel like doing it, I may give it a try (I have already
created a few of them). In this case, I would appreciate if you could
submit an issue, just to show the maintainers that there is some
interest in having the library provide this layout.

[begin]: https://www.arduino.cc/reference/en/language/functions/usb/keyboard/keyboardbegin/#_notes_and_warnings
[header]: https://github.com/arduino-libraries/Keyboard/blob/1.0.4/src/KeyboardLayout.h


body:
As an example of what you might do ...

First copy the file KeyboardLayout_en_US.cpp and rename it as KeyboardLayout_en_UK.cpp.

Most of the entries will be the same. Now looking at the layout in https://github.com/arduino-libraries/Keyboard/blob/1.0.4/src/KeyboardLayout.h we see this:

<!-- language: lang-none -->

      +---+---+---+---+---+---+---+---+---+---+---+---+---+-------+
      |35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp |
      +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+
      | Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret |
      +-----++--++--++--++--++--++--++--++--++--++--++--++--++    |
      |CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 |    |
      +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+
      |Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 |  Shift   |
      +----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+
      |Ctrl|Win |Alt |                        |AlGr|Win |Menu|Ctrl|
      +----+----+----+------------------------+----+----+----+----+

The third key along the top row of my (US) keyboard (below the function keys) has `@` on top and `2` on the bottom. It has the code `1f` in the chart.

In the US layout file we see, in part:

<!-- language: lang-none -->

 0x2c,          // ' '        0x20
 0x1e|SHIFT,    // !          0x21
 0x34|SHIFT,    // "          0x22
 0x20|SHIFT,    // #          0x23
 0x21|SHIFT,    // $          0x24
 0x22|SHIFT,    // %          0x25
 0x24|SHIFT,    // &          0x26
 0x34,          // '          0x27
 0x26|SHIFT,    // (          0x28
 0x27|SHIFT,    // )          0x29
 0x25|SHIFT,    // *          0x2a
 0x2e|SHIFT,    // +          0x2b
 0x36,          // ,          0x2c
 0x2d,          // -          0x2d
 0x37,          // .          0x2e
 0x38,          // /          0x2f
 0x27,          // 0          0x30
 0x1e,          // 1          0x31
 0x1f,          // 2          0x32
 0x20,          // 3          0x33
 0x21,          // 4          0x34
 0x22,          // 5          0x35
 0x23,          // 6          0x36
 0x24,          // 7          0x37
 0x25,          // 8          0x38
 0x26,          // 9          0x39
 0x33|SHIFT,    // :          0x3a
 0x33,          // ;          0x3b
 0x36|SHIFT,    // <          0x3c
 0x2e,          // =          0x3d
 0x37|SHIFT,    // >          0x3e
 0x38|SHIFT,    // ?          0x3f
 0x1f|SHIFT,    // @          0x40

I've put the *positions* of each entry on the right (the offset from the start of the array).

So looking at that table, when the scan code `1f` arrives, and SHIFT is pressed, we get `0x40` which is indeed `@` in the ASCII table.

Similarly, `1f` without SHIFT gives us `0x32` which is `2` in the ASCII table.

Now in your case I believe that key gives `"` when SHIFT is pressed, so the *third* line from the top in my example changes from:

<!-- language: lang-none -->

 0x34|SHIFT,    // "          0x22

to:

<!-- language: lang-none -->

 0x1f|SHIFT,    // "          0x22

And likewise for the other keys. So, the `@` symbol moves to where the quote is in the US keyboard. So change the *last* line in my example from:

<!-- language: lang-none -->

    0x1f|SHIFT,    // @          0x40

to:

<!-- language: lang-none -->

 0x34|SHIFT,    // "          0x40

Those two changes "swap" the locations of the `"` and the `@` symbols.

---

As noted in the comments, keys marked ¬ and £ do not have a 7-bit ASCII representation so you will not be able to put them in the table (there is no entry for them).


message:
NRF24L01 PA+LNA With Arduino

I am using the NRF module for remote communucation.I have been many research about nrf but my nrf module is not working This is my tranmistter code:

```
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8,4000000); // CE, CSN

const byte address[6] = "00001";

void setup() {
  Serial.begin(115200);
  radio.begin();
  radio.openWritingPipe(address);
  radio.setRetries(15,15);
  radio.setPALevel(RF24_PA_HIGH);

}

void loop() {
  radio.stopListening();
  const char text[32]="Hello world";
  if(radio.write(&text,sizeof(text))){
    Serial.println("Mesaj gönderildi");
  }
  delay(1000);
```

This is my receiver code:

```
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8,4000000); // CE, CSN

const byte address[6] = "00001";

void setup() {
  Serial.begin(9600);
  radio.begin();
  delay(400);
  radio.openReadingPipe(1, address);
  radio.setPALevel(RF24_PA_MAX);
//  radio.startListening();
   pinMode(10,OUTPUT);

}

void loop() {
 const char text[32]="";
  radio.startListening();
  if(radio.available())
  {
    while(radio.available()){
    radio.read(&text[0],sizeof(text[0]));
    Serial.println(text);
    delay(1000);
    }
  }
  delay(5);

}
```

ı tried the setPAlevel min but there is no change.In the transmitter side the write function returns true, but I can't get anything on the receiver side. Also, if I replace the cable connected to miso with the cable connected to mosi on the transmistter side, the write function still returns true. I also used adaptor ams1117

body:
In the receiver code, you are just reading one byte, as 6v6gt pointed out. Check the library to see [how `read()` works](https://github.com/nRF24/RF24/blob/a028813b285d6cec3090d2c96984bd67a399c52e/RF24.cpp#L408).

If you follow the [getting started example](https://nrf24.github.io/RF24/examples_2GettingStarted_2GettingStarted_8ino-example.html), this is how you should read bytes in the receiver:

    char text[32];

    if (radio.available())
    {
      uint8_t bytes = radio.getPayloadSize();  // get the size of the payload
      radio.read(&text, bytes);                // fetch payload from FIFO
    }

Don't use `const` for `text` in the receiver.
Also, you don't need to use `stopListening` and `startListening` in the `loop()`. They should just go to `setup()`.


message:
Need help individually controlling 3 LEDs with 3 toggle switches

I'm trying to individually control 3 LEDs with 3 toggle switches. This is the code I'm using

```c++
#define LED_PIN1 2
#define BUTTON_PIN1 14

#define LED_PIN2 3
#define BUTTON_PIN2 15

#define LED_PIN3 4
#define BUTTON_PIN3 16

void setup() {
  pinMode(LED_PIN1, OUTPUT);
  pinMode(BUTTON_PIN1, INPUT);

   pinMode(LED_PIN2, OUTPUT);
  pinMode(BUTTON_PIN2, INPUT);

   pinMode(LED_PIN3, OUTPUT);
  pinMode(BUTTON_PIN3, INPUT);

}
void loop() {
  if (digitalRead(BUTTON_PIN1) == HIGH) {
    digitalWrite(LED_PIN1, HIGH);
  }
  if (digitalRead(BUTTON_PIN1) == LOW)   {
    digitalWrite(LED_PIN1, LOW);
  }
  if (digitalRead(BUTTON_PIN2) == HIGH) {
    digitalWrite(LED_PIN2, HIGH);
  }
  if (digitalRead(BUTTON_PIN2) == LOW) {
    digitalWrite(LED_PIN2, LOW);
  }
  if (digitalRead(BUTTON_PIN3) == HIGH) {
    digitalWrite(LED_PIN3, HIGH);
  }
  if (digitalRead(BUTTON_PIN3) == LOW) {
    digitalWrite(LED_PIN3, LOW);
  }
}
```

The problem is that this code is causing all 3 LEDs to turn on or off together when any one of the three toggle switches is pushed. Can someone explain why this is happening? Also, what do I need to change so that each LED can be individually controlled?

Thanks!

body:
How is your wiring done?

This is a working example of how it can be done:
```c++
#define LED_PIN1 5
#define BUTTON_PIN1 14

#define LED_PIN2 6
#define BUTTON_PIN2 15

#define LED_PIN3 7
#define BUTTON_PIN3 16

void setup() {
  // set up all the LEDs as OUTPUT
  pinMode(LED_PIN1, OUTPUT);
  pinMode(LED_PIN2, OUTPUT);
  pinMode(LED_PIN3, OUTPUT);

  // set up all the buttons as INPUT
  pinMode(BUTTON_PIN1, INPUT);
  pinMode(BUTTON_PIN2, INPUT);
  pinMode(BUTTON_PIN3, INPUT);
}

void loop() {
  // turn the LED on when button is pressed
  digitalWrite(LED_PIN1, digitalRead(BUTTON_PIN1));
  digitalWrite(LED_PIN2, digitalRead(BUTTON_PIN2));
  digitalWrite(LED_PIN3, digitalRead(BUTTON_PIN3));
}
```

When you just want the LED to be on when the button is pressed and off when the button is unpressed you can simplify the code by directly writing the button state to the LED like so: `digitalWrite(LED_PIN, digitalRead(BUTTON_PIN))`. Because read of the button will return either `HIGH` or `LOW` you can directly drive the LED with this.

Also make sure you check the pin's you are using on your device. Pin 3 is the reset pin. I therefore changed the pins to 5, 6, 7 to make sure you're using digital pins.
[![Arduino Nano pinlayout][1]][1]

If you want to see a working example in action, take a look at [this][2] tinkercad. Be aware that I'm using an arduino uno here, so make sure that you use correct pins using the previous pin layout when adapting this to your Arduino nano. You can simulate this circuit by clicking on the 'simulate' button and test this working example by clicking on the buttons in the circuit.
[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/eDcJr.png
  [2]: https://www.tinkercad.com/things/6GXuqA5nYlP?sharecode=iEpjt-7qtN6PoFT5d26U1lMg5scu4wfO36ZPCcjMCwc
  [3]: https://i.stack.imgur.com/so4aa.png


message:
How do you take the simplest continuous reading from a Garmin Lidar Lite V4 using I2C on a Particle Boron v4.1.0?

Hey there Stack community.
I'm working with the Particle Boron v4.1.0.
I'm connecting a Garmin Lidar Lite V4 on I2C.
I'm using the LIDARLite_v4LED.h header file found in the library given for this device, "LIDAR-Lite" and my goal here is to op-check the sensor, by taking readings in the simplest way according to the .h file.

Wiring:
I've soldered 22AWG solid wire to each respective pin on the sensor:
GND : black, going directly to ground.
VCC : red, 3.3V pin on the Particle Boron.
I2C SDA : blue, SDA Pin0 on the Particle Boron with a 4.7K ohm pull-up resistor, connected to ground on one end, and running to Pin0 on the Boron.
I2C SCL : green, SCL Pin1 on the Particle Boron with a 4.7K ohm pull-up resistor, connected to ground on one end, and running to Pin1 on the Boron.

I've run an I2C scan which confirmed the address at 0x62.

According to the manual at: https://static.garmin.com/pumac/LIDAR-Lite LED v4 Instructions_EN-US.pdf

To take a reading you must perform the following actions, which are embedded in the library's .h file functions:

"Obtaining Measurements from the I2C Interface
You can obtain measurement results from the I2C interface.

 1.  Write 0x04 to register 0x00.
 2.  Read register 0x01.
 3.  Repeat step 2 until bit 0 (LSB) goes low.
 4.  Read two bytes from 0x10 (low byte 0x10 then high byte 0x11) to obtain the 16-bit measured distance in centimeters."

    #include <LIDARLite_v4LED.h>

    const int I2CADDRESS = 0X62;
    uint16_t distance;

    LIDARLite_v4LED L1;

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

    void loop() {
        L1.takeRange(I2CADDRESS);
        L1.waitForBusy(I2CADDRESS);
        L1.getBusyFlag(I2CADDRESS);
        distance = L1.readDistance(I2CADDRESS);
        Serial.printf("Distance = %u\n", distance);
    }

When I run the code above the Serial Monitor shows 0 continuously for the reading, which is incorrect.

Do you happen to see what I'm doing wrong?

Here is what's happening in each respective function call above:

    void LIDARLite_v4LED::takeRange(uint8_t lidarliteAddress)
    {
        uint8_t dataByte = 0x04;

        write(0x00, &dataByte, 1, lidarliteAddress);
    } /* LIDARLite_v4LED::takeRange */

    void LIDARLite_v4LED::waitForBusy(uint8_t lidarliteAddress)
    {
        uint8_t  busyFlag;

        do
        {
            busyFlag = getBusyFlag(lidarliteAddress);
        } while (busyFlag);

    } /* LIDARLite_v4LED::waitForBusy */

    uint8_t LIDARLite_v4LED::getBusyFlag(uint8_t lidarliteAddress)
    {
        uint8_t  statusByte = 0;
        uint8_t  busyFlag; // busyFlag monitors when the device is done with a measurement

        // Read status register to check busy flag
        read(0x01, &statusByte, 1, lidarliteAddress);

        // STATUS bit 0 is busyFlag
        busyFlag = statusByte & 0x01;

        return busyFlag;
    } /* LIDARLite_v4LED::getBusyFlag */

    uint16_t LIDARLite_v4LED::readDistance(uint8_t lidarliteAddress)
    {
        uint16_t  distance;
        uint8_t * dataBytes = (uint8_t *) &distance;
        // Read two bytes from registers 0x10 and 0x11
        read(0x10, dataBytes, 2, lidarliteAddress);
        return (distance);
    } /* LIDARLite_v4LED::readDistance */

Thanks in advance for any assistance!

NOTE: The code doesn't show any errors. It's possible I damaged the chip on the sensor when I soldered, as I'm a newb to all of this! However, I've put two sensors together and tried them each separately with the same code, and got the same results in an attempt to rule this out. I did better soldering the second sensor, and find it highly unlikely I damaged them both.

body:
As romkey pointed out, I had the pull-up resistors wired wrong. Pull-up resistors are connected to power, not to ground.

Then I had to include `wire.h` and initiate `Wire.begin();` in setup.


message:
Why does analogRead(A0) deliver different Values when called in a library file vs calling it in the sketch directly

I wanted to write a library representing a sensor to later on have an array of sensors.
I generated a file MoistureSensor.h:
```
#ifndef MoistureSensor_h
#define MoistureSensor_h

#include <Arduino.h>

class MoistureSensor {
  private:
    uint8_t sensPin;
    int sensValue;
    int sensId;

  public:
    MoistureSensor(uint8_t pin,int id);
    int getValue();
    int getId();
};

#endif
```
 and MoistureSensor.cpp:
```
    // MoistureSensor.cpp
#include "MoistureSensor.h"

MoistureSensor::MoistureSensor(uint8_t pin, int id) {
  sensPin = pin;
  sensId  = id;
}

int MoistureSensor::getValue() {
  sensValue = analogRead(sensPin);
  return sensValue;
}
int MoistureSensor::getId() {
  return sensId;
}
```
this is the main sketch running on a Arduino Mega:
```
#include "MoistureSensor.h"

MoistureSensor sens1("A0", 1);

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

void loop() {
  Serial.println("Value from analogread:");
  Serial.println(analogRead(A1));
  Serial.println("Value from library:");
  Serial.println(sens1.getValue());
  Serial.println("End");
  delay(1000);

}
```
So when I run this the serial monitor shows:
```
Value from analogread:
600
Value from library:
496
End
```

Why doesn't this print the same value?
Does the .cpp file interpret the data from `analogRead()` different than the sketch?

Also both values where moving up and down depending on the response of the sensor.

Thanks in advance.

body:
Trying to compile your sketch, I get the following compiler warning:

```text
warning: invalid conversion from 'const char*' to 'uint8_t {aka unsigned char}'
 MoistureSensor sens1("A0", 1);
                             ^
note:   initializing argument 1 of 'MoistureSensor::MoistureSensor(uint8_t, int)'
```

This means that, whereas the `MoistureSensor()` constructor expected its
first argument to be of type `uint8_t`, you provided a `const char*`
instead. Indeed, a string literal like `"A0"` decays to a `const char*`
pointer when you pass it as a function argument.

The fix is to pass the actual pin number to your constructor:

```c++
MoistureSensor sens1(A0, 1);
```

But then, there is a second issue. In your test sketch, you have your
`MoistureSensor` object read `A0`, whereas the direct `analogRead()`
reads pin `A1`. If you want to get the same value, you should read the
same pin.

**Side note**: the change from `uint8_t` to `byte` has absolutely
nothing to do with your issue. These two types are synonyms.


message:
Working with pulseIn() and millis()

I'm trying to use `pulseIn` with elapsed time using `millis()`, I don't want to use interrupts instead of `pulseIn` (I need `pulseIn` because I need accurate pulse time), the elapsed time doesn't need to be very accurate, so to calculate the elapsed time I've added to the elapsed time the time the arduino is blocked, The problem is the calculated elapsed is very inaccurate, I suspect it sometimes never enters `if(elapsed > 1000*60*2)`, Why is that? How can I fix that?

Thanks.

**Code**

    unsigned long startTime = 0;
    unsigned long elapsed = 0;
    unsigned int val = 0;
    uint32_t time_wait_pulse = 0;

    void setup(){
      startTime = millis();
    }

    void f(){
      uint32_t time = 0;
      time += pulseIn(pin, LOW);
      if(time > 0) {
       ...
       time_wait_pulse += time;
      } else {
       time_wait_pulse += 1000000; //default pulseIn timeout (micros)
      }
    }

    void loop(){
        elapsed = millis() - startTime + (unsigned long)(time_wait_pulse/1000);
        if(elapsed > 1000*60*2){
          val++;
          startTime = millis();
          time_wait_pulse = 0;
        }

         noInterrupts();
         f();
         interrupts();
    }

body:
`millis()` is using interrupts to work. When deactivating interrupts for your function `f()`, you prevent that the value returned by `millis()` can actually change in that time.

So if the interrupt associated with `millis()` occurs during the execution of `f()`, you will lose time in your measurement and it will be inaccurate. It will get worse the more time the code spends with interrupts off vs on. `micros()` will still be updated without interrupts on (since it directly reads the register of Timer0), but [it will still lose time after about 500ms][1], since then it cannot compensate for multiple overflows in that time period.

The way to go forward depends on your requirements. Is it really needed, that you disable interrupts for the `pulseIn()` measurement? What accuracy do you get in both cases (interrupts on vs off) and what accuracy do you need? If you absolutely need to turn off interrupts, only do it for the shortest time (only around `pulseIn()`). You can built your own time keeping analog to `millis()` using a 16bit Timer (you didn't specify what Arduino you are using), which would give you way more time, that the microcontroller can spend without interrupts on before loosing time in the measurement.You can also use a different prescaler to further increase this time, though sacrificing precision for it.

  [1]: https://arduino.stackexchange.com/questions/22212/using-millis-and-micros-inside-an-interrupt-routine#22237


body:
You can time reasonably long intervals using Timer 2 (on the Atmega328) as described in [my page about timers](http://www.gammon.com.au/forum/bbshowpost.php?id=11504&page=2).

The example there is this:

    void startTimer1 ()
      {
      // reset Timer 1
      TCCR1A = 0;
      TCCR1B = 0;
      // zero it
      TCNT1 = 0;
      TIFR1 |= bit (TOV1);  // clear overflow flag
      // start Timer 1
      TCCR1B =  bit (CS10) | bit (CS12);  //  prescaler of 1024
      }  // end of startTimer1

    unsigned long getTimer1Reading ()
      {
      unsigned long elapsed = TCNT1;
      if (TIFR1 &  bit (TOV1))
         elapsed += 65536;
      return elapsed;
      }  // end of getTimer1Reading

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

      }  // end of setup

    void loop ()
      {
      Serial.println ("Starting ...");
      Serial.flush ();

      startTimer1 ();

      delay (7560);
      float secs = (1.0 / F_CPU * 1024) * getTimer1Reading ();

      Serial.print ("Time taken = ");
      Serial.print (secs);
      Serial.println (" seconds.");

      } // end of loop

 The code above uses Timer 1 to time an interval up to 8.388 seconds. It users a prescaler of 1024, which means each "count" of timer 1 is 1/16e6 * 1024 of a second (0.000064 seconds, or 64 µs). Since it can count up to 65536 we can time 0.000064 * 65536 = 4.194304 seconds. Then the timer overflows, but we can test the "overflow flag" and know the overflow occurred. That lets us time up to 8.388608 seconds before we miss the fact that there was a second overflow.

This code works even if interrupts are off, because the timing is done by the hardware timer.

Output on my Uno:

```none
Starting ...
Time taken = 7.56 seconds.
```


message:
Unable to upload sketch to Lolin S3 Pro (ESP32-S3)

I'm trying to upload a simple sketch to the new Wemos Lolin S3 Pro but unfortunately I can't seem to get it to work. I get the following error message:

        Connecting......................................

    A fatal error occurred: Failed to connect to ESP32-S3: No serial data received.
    For troubleshooting steps visit: https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html
    Failed uploading: uploading error: exit status 2

The following board is causing problems:
https://www.wemos.cc/en/latest/s3/s3_pro.html

It seems that there is no USB to UART chip and also no boot button.
As board I selected the "LOLIN S3 Pro" in the Arduino IDE and under Platformio I had selected the "lolin_s3".
I have also tried it under platformio with the following build flags but unfortunately without success:

    build_flags = -DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=1

I am really perplexed what could be the cause?

Btw: I bought 3 of these boards and all 3 have the same issue.

body:
OK I managed to solve it although I find its a little bit annoying it seems that you need to always set this board in download mode manually. (Press and hold boot and click reset button once).

If you are using Arduino IDE use the following options:

 - USB CDC On Boot -> Enabled
 - Upload Mode -> Hardware CDC / UART0

If you are using PlatformIO use the following build flags:

    build_flags = '-DARDUINO_USB_MODE=1' '-DARDUINO_USB_CDC_ON_BOOT=1'
Also a good source: https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/tutorials/cdc_dfu_flash.html


message:
Arduino IDE equivalent to DataView?

I am working on a project with Bluetooth commands between various devices. I would like to try and convert a string to a DataView Object on Arduino, so I can send it over BLE, much like this function written in Javascript:

    function str2DV(str) {
      var buf = new ArrayBuffer(str.length);
      var bufView = new Uint8Array(buf);
      for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
      }
      var DV = new DataView(buf);
      return DV;
    }

Is this possible with Arduino? I have yet to find a solution....

body:
There is no use for a DataView in the Arduino environment. In the
JavaScript language, a string and an array of bytes are two very
different things. That's why you need something like this `str2DV()`
function to convert between them. In C++, they are one and the same
thing: no need to convert. Sometimes the type `uint8_t` (also named
`byte`) is used in preference of `char` for storing binary data, but you
can just typecast between these types. The typecast typically compiles
to zero machine instructions, as the underlying data representation is
the same.

For example:

```c++
extern some_lib_function(const uint8_t *buffer, int buffer_length);

const char *my_message = "Hello, World!\n";
some_lib_function((uint8_t *) my_message, strlen(my_message));
```

If your string is in the form of a `String` object, rather than a plain
C-string, then use the `c_str()` method to get the plain string back:

```c++
String my_message = "Hello, World!\n";
some_lib_function((uint8_t *) my_message.c_str(), my_message.length());
```


message:
Are intel hex files converted into a binary format before they are written to Atmega's flash?

I have been going through some resources on bootloaders, programmers, etc (I'm very new to this specific subject) and how they work with the Atmega chips and Arduino board programming. My research may have been shallow but none of the online articles/blogs/forum posts that I have been through mentioned that the .hex file (in intel hex ASCII format) needs to be converted to any other kind of binary format. It did seem odd to me though that one would directly write ASCII plain text into an MCU's flash. Also, when using AVR Burn-o-Mat (a GUI front end for avrdude) I did notice a couple of times that the number of bytes being flashed was significantly less than the actual size of the hex file. Most recently I went through [this](https://github.com/arkku/ihex) library on github which converts intel hex into a binary format. So am I right in saying that the hex file needs to be converted to binary? So for instance, does avrdude basically do this before sending the binary stream to the bootloader (when uploading a sketch via the IDE)?

body:
Yes, the hex codes in the .hex file are read in by avrdude (or other programs) and written to the MCU in binary. A small microprocessor would not be able to read ASCII format commands.

See my answer about https://arduino.stackexchange.com/questions/15936/what-happens-when-code-is-uploaded-using-the-bootloader/15937#15937

---

(Following on from some comments)

> I did notice a couple of times that the number of bytes being flashed was significantly less than the actual size of the hex file

I think there is some confusion here, because of the different way numbers can be represented, or stored. Just for example, the number which we know as "twenty" could be written (in a file) as:

* 20 (decimal)
* 00020 (decimal with leading zeroes)
* 0014  (hex)
* 0024 (octal)
* 10100 (binary digits)

Now a program like Avrdude could read numbers in any of those formats, internally convert them to "binary" and send a single byte, being that binary number, to the MCU for placing into a program memory byte.

The .hex format, which the Arduino system produces as part of the compilation process, uses lines in this format:

    Line format:
      :nnaaaatt(data)ss
      Where:
      :      = a colon
      (All of below in hex format)
      nn     = length of data part
      aaaa   = address (eg. where to write data)
      tt     = transaction type
               00 = data
               01 = end of file
               02 = extended segment address (changes high-order byte of the address)
               03 = start segment address *
               04 = linear address *
               05 = start linear address *
      (data) = variable length data
      ss     = sumcheck
                * We don't use these

The above from comments in my file https://github.com/nickgammon/arduino_sketches/blob/master/Atmega_Hex_Uploader/File_Utils.ino

**Example**: Optiboot in all its glory (only 512 bytes):

    :107E0000112484B714BE81FFF0D085E080938100F7
    :107E100082E08093C00088E18093C10086E0809377
    :107E2000C20080E18093C4008EE0C9D0259A86E02C
    :107E300020E33CEF91E0309385002093840096BBD3
    :107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4
    :107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7
    :107E6000A2D0813461F49FD0082FAFD0023811F036
    :107E7000013811F484E001C083E08DD089C08234E0
    :107E800011F484E103C0853419F485E0A6D080C0E4
    :107E9000853579F488D0E82EFF2485D0082F10E0AE
    :107EA000102F00270E291F29000F111F8ED06801E7
    :107EB0006FC0863521F484E090D080E0DECF843638
    :107EC00009F040C070D06FD0082F6DD080E0C81688
    :107ED00080E7D80618F4F601B7BEE895C0E0D1E017
    :107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8
    :107EF00018F0F601B7BEE89568D007B600FCFDCFD4
    :107F0000A601A0E0B1E02C9130E011968C91119780
    :107F100090E0982F8827822B932B1296FA010C0160
    :107F200087BEE89511244E5F5F4FF1E0A038BF0790
    :107F300051F7F601A7BEE89507B600FCFDCF97BE46
    :107F4000E89526C08437B1F42ED02DD0F82E2BD052
    :107F50003CD0F601EF2C8F010F5F1F4F84911BD097
    :107F6000EA94F801C1F70894C11CD11CFA94CF0C13
    :107F7000D11C0EC0853739F428D08EE10CD085E9AC
    :107F80000AD08FE07ACF813511F488E018D01DD067
    :107F900080E101D065CF982F8091C00085FFFCCF94
    :107FA0009093C60008958091C00087FFFCCF809118
    :107FB000C00084FD01C0A8958091C6000895E0E648
    :107FC000F0E098E1908380830895EDDF803219F02E
    :107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA
    :107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6
    :047FF000FF270994CA
    :027FFE00040479
    :0400000300007E007B
    :00000001FF

So, a line in the .hex file will start with a colon, then a length, then an address, then a transaction type, then some variable amount of data, and then a sumcheck. These are stored in the file in hexadecimal notation.

The very first thing we can deduce from this is that the file size will be over double the amount of memory that is programmed. For example, to program "AB" in hex, this would take two bytes in the .hex file ("A" followed by "B") but these would be converted into the equivalent one-byte "binary" number, which would end up in the MCU memory.

Then, because of the colon, the transaction type, the line length, and the sumcheck, the file will be somewhat longer still, than double the number of bytes to be programmed into the MCU. That is the file layout overhead.


message:
Best way to send a boolean (1/0) to a windows application in real time?

I have an arduino mega connected to a light sensor that reads the status of a machine's indicator light. I have a C++ application that controls the machine, and I would like the arduino to send the application the status of the indicator light in real-time so that the application can control the machine.

Essentially, I just want to constantly send a "1" or "0" through the serial monitor to a C++ application. What would the best way to do this be? I am confused as to the difference between `serial.Write()` and `serial.Print()`, what is more optimal for this application?

body:
`Serial.write` sends binary data, whereas `Serial.print` sends ASCII data.  So it depends on whether you want Windows to receive ASCII 0 and 1 or binary 0 and 1.

I would suggest that you use print and send ASCII data.


body:
It might sound like a good idea to send "0" or "1" in real time, for a fast response, but that might be counter-productive.

For one thing, you are spamming serial data which could slow down the receiving machine slightly. For another, if the sampling rate is faster than the baud rate, then the sending buffer will fill up, and the data being sent will be "old". Say the buffer size is 64 bytes, then the data being sent (and therefore received by windows) could be 64 bytes ago, and not real time.

I would suggest sending a "1" (with Print rather than Write) when the light is on, and then nothing until you detect that the light is off, then send a "0". And ditto for the transition back to being on. Thus the serial data flow merely indicates transitions and not the current state. This greatly reduces the amount of data, and makes it much less likely you will lose some or it will be out of date.

And just in case, send the current state (0 or 1) every second or so, just in case the listening end has only just been turned on.


body:
I agree with both previous answers. Nick Gammon gives excellent advise
on how to handle this situation, and Rohit Gupta gives you the gist of
`write()` v.s. `print()`. I would like to elaborate on this `write()` /
`print()` distinction though.

These methods of the Arduino API can be confusing, as they have [many
different signatures][api].

## write()

Let's look at `write()` first, as it is the simplest of them:

```c++
size_t write(uint8_t);
size_t write(const uint8_t *buffer, size_t size);
```

These are meant to send a single byte and an array of bytes
respectively. You can send _arbitrary bytes_, which is usually termed
“binary data”. Note that any data, including text, is binary data: the
term _binary_ here simply means that there is no restriction on the
bytes you can send.

```c++
size_t write(const char *buffer, size_t size);
```

This is the same as the previous one, for the case when the buffer is of
type “array of char”. It can still send arbitrary data.

```c++
size_t write(const char *str);
```

This is a version for sending C-strings, i.e. NUL-terminated buffers.
This one cannot send a zero byte, as that byte is interpreted as a
string terminator. It is thus inappropriate for sending binary (in the
sense of “arbitrary”) data. For this reason, I believe the inclusion of
this overload is a mistake made by the designers of the API, and I would
avoid it in preference of `print()` which, for this type of argument,
_does exactly the same thing_.

Note that, in every instance, `write()` takes the data you give it and
sends it as-is. There is no attempt at formatting it in any manner.

## print()

As stated by Rohit Gupta, `print()` is meant for sending text. If you
have some data to send that is text to start with (like a literal
string), `print()` sends it as-is, and is thus quite similar to
`write()`. This is the case for the following overloads:

```c++
size_t print(const String &);  // sends a String object
size_t print(const char[]);    // sends a C-string
size_t print(char);            // sends a single character
```

Then you have some overloads for printing various kinds of numbers. All
of these involve a binary-to-text conversion. The two remaining
overloads, which involve `__FlashStringHelper` and `Printable`, are a
bit too technical and I will not discuss them here.

## Comparison

All the statements below do the same thing, they send "A" through the
serial port:

```c++
Serial.write(65);        // sends a byte with binary value 65
Serial.write('A');       // the ASCII code of 'A' is 65
Serial.print('A');       // a char is print()ed by sending it as-is
Serial.print(char(65));  // 'A' is a shortcut for char(65)
Serial.print("A");       // a one-character string
```

All the statements below send "65" through the serial port:

```c++
Serial.write(54); Serial.write(53);    // send two binary values
Serial.write('6'); Serial.write('5');  // ASCII('6') = 54...
Serial.write("65");       // sends text in a pre-formatted buffer
Serial.print("65");       // same
Serial.print(65);         // print() does the number-to-text conversion
Serial.print(int('A'));   // same
```

As a general rule, I recommend to always use `print()` for sending text,
and use `write()` only for sending data that is not (reliably known to
be) text.

[api]: https://github.com/arduino/ArduinoCore-API/blob/1.4.0/api/Print.h#L49-L75


message:
Where to store struct used for driver initialization

I'm doing a small project with ESP32 board. When initializing a driver, multiple structs are passed to initialization functions. I know that there are two ways to store such structs:

1. Storing structs on heap (with `calloc` or `malloc`)

```C
adc_continuous_config_t cfg = calloc(1, sizeof(adc_continuous_config_t));

cfg->sample_freq_hz = 4500;
cfg->conv_mode = ADC_CONV_SINGLE_UNIT_1;
cfg->format = ADC_DIGI_OUTPUT_FORMAT_TYPE;

adc_continuous_config(*handle, cfg);
free(cfg);
```

2. Storing structs on stack

```c
adc_continuous_config_t cfg = {
    .sample_freq_hz = 4500,
    .conv_mode      = ADC_CONV_SINGLE_UNIT_1,
    .format         = ADC_DIGI_OUTPUT_FORMAT_TYPE1,
};

adc_continuous_config(*handle, &cfg)
```

I was wondering which approach is encouraged.

body:
You seem to be initializing this struct with constants. In such a case,
I would use neither the heap nor the stack, but a third option: the
“read-only data” section of the program. At global scope:

```c++
const adc_continuous_config_t cfg = {
    .sample_freq_hz = 4500,
    .conv_mode      = ADC_CONV_SINGLE_UNIT_1,
    .format         = ADC_DIGI_OUTPUT_FORMAT_TYPE1,
};
```

**Rationale**: The constants you are using to fill the struct have to be
stored somewhere in the flash when the program is not running. Although
I do not know the details of the machine language of the ESP32, it seems
to me the compiler has only two options to compile your example code. It
could say:

 * load a CPU register with the immediate value `4500`
 * store that register at the address of `cfg->sample_freq_hz`
 * load a CPU register with the immediate value `ADC_CONV_SINGLE_UNIT_1`
 * etc.

Then the values are stored as immediate operands of machine
instructions. The other option would be to store an anonymous version of
the initialized struct in the read-only data section of the program, and
issue a `memcpy()` to initialize the allocated space at run time.

If you instead store the initialized struct as a global constant, it
will go straight into the read-only data section of the program (like in
the second compiler strategy), and you will use it from there. No extra
copy needed. No extra machine instruction for initializing space
allocated on the heap or stack.

**Caveat**: I assume `adc_continuous_config()` expects its second
parameter to be of type “pointer to `const` data”. If it expects it to
be a pointer to modifiable data, then this will not work.


message:
Smoothing hx711 readings with atmega328

I am making a 50kg weighing scale using **HX711 ADC**. My project includes **Atmega328** along with **74HC595** for driving 5 7segment displays(multiplexed). I am using the function ```scale.get_units()```to fetch the data and the values are very well displayed on the 7segments. The problem I am facing is the readings on the 5th digit (right most 1's) are unstable. Now, if I use ```scale.read_average(5)```, **my display scanning gets slow**. I was wondering if there is a way to average the readings in a loop like the conventional way. I tried it but with no luck! It keeps showing random added numbers. Any help would be highly appriciated. Below is the code inside the loop. Let me know if full code is needed. Thanx in advance!

```c++
if (scale.is_ready()) {
    weight = scale.get_units();
    finalWeight = weight * 1000;
}
for (int i = 0; i < 10 ;i++) {
    sum += finalWeight;
}
average = sum / 10;
if (average < 0) {
    break_number(0);
} else {
    break_number(average);
}
display_number();
delay(1);
```

body:
First of all, this code:

```c++
for (int i = 0; i < 10 ;i++) {
    sum += finalWeight;
}
average = sum / 10;
```

does not average multiple readings. Instead, it takes the single reading
stored in `finalWeight`, multiplies it by ten (by means of successive
additions), then divides it by ten to get back the same value.

If you want to reduce the noise, you have to take multiple readings and
average them. The reading-taking code must thus be inside the loop. A
simple option may be like this:

```c++
void loop() {
    sum = 0;
    for (int i = 0; i < 10; i++) {
        while (!scale.is_ready()) {}  // wait for the scale to be ready
        sum += scale.get_units();
    }
    weight = sum / 10;  // compute the average
    display(weight);    // and display it
}
```

Note that I have simplified things a bit by removing the scaling
factors. You can take this as simple inspiration and adapt to your
specific needs.

The code above has one problem though: as the code is blocking while
waiting for the scale to be ready, the display is not refreshed. You
could fix this by explicitly refreshing the display within the waiting
loop:

```c++
void loop() {
    sum = 0;
    for (int i = 0; i < 10; i++) {
        while (!scale.is_ready()) {  // wait...
            display(weight);         // ...while refreshing the display
        }
        sum += scale.get_units();
    }
    weight = sum / 10;
    display(weight);
}
```

This should work, but I would however suggest instead a third approach:
write _non-blocking code_. This is code that never blocks: instead, if
something can be done _right now_, it does it. If not, it moves along:

```c++
void loop() {
    if (scale.is_ready()) {  // if something useful can be done NOW:
        sum += scale.get_units();
        count++;
        if (count >= 10) {
            weight = sum / count;  // update the value to be displayed
            sum = 0;               // reset the averaging variables
            count = 0;
        }
    }

    display(weight);  // unconditionally refresh the display
}
```

This way, your `loop()` always runs fast, and you can add code that will
not be blocked by the stuff you wrote earlier.

**Edit**: As suggested by chrisl in a comment, a moving average may
better serve your needs. I would try the exponentially-weighted version,
as it is lightweight and simpler to implement. You may want to explore
this path.


message:
stream a "big" array of measures to a server through wifi

I'm measuring accelerations at "high frequency" (4kHz) from an accelerometer (ADXL355/ADXL357) to an esp32. It's crucial that no sample is lost while performing a measure which last say 2 seconds, thus I first record all the samples and then send the complete array of measures to a server over wifi knowing the IP and the port of the server.

The measures array is an int array of size 3bytes * 3axis * 4000Hz * 2seconds = 72000 bytes.

I tried to make an http server and send the measures array from the microcontroller to the server with a POST request and serializing the payload with json (ArduinoJSON library), but this is very costy in terms of memory, because I need to duplicate the array of measures and convert it to an array of strings.

Is there a better way to send this array over wifi to the server (some sort of stream?) optimizing the memory usage on the microcontroller? which arduino libraries may help in the task? could you link an example with code of a similar situation?

body:
JSON is a format trivial to write: you do not need a library for this.
For example, an array of numbers could be serialized like this:

```c++
void serialize_array(Print &client, int *data, int count) {
    client.print('[');
    for (int i = 0; i < count; i++) {
        client.print(data[i]);
        client.print(i==count-1 ? ']' : ',');
    }
}
```

This would effectively stream the data without storing the JSON
representation in memory.


message:
Break a big file into smaller files

I had a really big `.ino` file and I decided to break it down into sub-files.

So I had the `.ino` file, the `globals.h` file and the `functions.h` file.

I moved all the global vars and functions to their respective files.
This is what is going on inside:

    //.ino
    #include "globals.h"
    #include "functions.h"

    //globals.h
    *Has header guard
    *All variables here are extern
    *Contains function prototypes - the definition is in functions.h
    *Contains objects (like softWareSerial)

    //functions.h
    #include "globals.h"
    *contains function definitions

However, my code will not work.
I get a huge list of errors, but the last of which is about `SoftwareSerial` (in `globals.h`)

    'SoftwareSerial' does not name a type; did you mean 'SoftwareSerial_h'?

Isn'e the code structure that I posted previously valid?

EDIT: I ask here and not on StackOverflow for example, because the IDE has symo idiosyncracies, like it first loads the `.ino` and then all the other files in an alphabetical manner.

EDIT 2: I followed user's `Edgar Bonet` advice (thank you). I reached somewhere, but I get `multiple definition` errors now. This is the pseudocode to show to display my code structure:

        //string_handling_functions.h
        HEADER_GUARD
        #include <SoftwareSerial.h> //used later. If this call happened in main .ino (even before the call to this header file, code would not work)
        #include <model_definitions.h> //used in the function definition in the .cpp file
        byte clear_Buffer(bool, SoftwareSerial*);

        //string_handling_functions.cpp
        #include <Arduino.h>
        #include "string_handling_functions.h"
        FUNCTION DEFINITION GOES HERE

        //model_definitions.h
        HEADER_GUARD
        #defines
        SoftwareSerial object_definition
        Other Objects Definitions (libs called in main .ino file)
        const char example_var PROGMEM = {0};

        //main_ino.ino
        #include "string_handling_functions.h"

I get these type of errors now:

    \sketch\string_handling_functions.cpp.o (symbol from plugin): In function `GSM_Module_SW_Serial':
    (.text+0x0): multiple definition of `GSM_Module_SW_Serial'
    \sketch\main_code.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

All errors are `multiple definitions`. The items that fall victim to this error are objects and arrays.

Some extra questions:

 1. All the vars in `.h` files have to be `extern`?
 2. Can they have a value in the header file? (eg `extern char value = {"0"};`)

**EDIT 3**:
After compying to all the rules, I had to create many files (`.h` and `.cpp`) to group everything together.
These are the last errors that I get, and they have to do with `SoftwareSerial`:

    In file included from \sketch_general_vars.cpp:2:0:
    model_definitions.h:498:1: error: 'SoftwareSerial' does not name a type; did you mean 'HardwareSerial'?
     SoftwareSerial Ter_1_SS_RXOnly (TER_1_RX_PIN, TER_1_TX_PIN);
     ^~~~~~~~~~~~~~
     HardwareSerial
    model_definitions.h:499:1: error: 'SoftwareSerial' does not name a type; did you mean 'HardwareSerial'?
     SoftwareSerial Ter_2_SS_RXOnly (TER_2_RX_PIN, TER_2_TX_PIN);
     ^~~~~~~~~~~~~~
     HardwareSerial
    model_definitions.h:536:1: error: 'SoftwareSerial' does not name a type; did you mean 'HardwareSerial'?
     SoftwareSerial GSM_Module_SW_Serial(GSM_RX_PIN, GSM_TX_PIN);
     ^~~~~~~~~~~~~~
     HardwareSerial

    exit status 1
    'SoftwareSerial' does not name a type; did you mean 'HardwareSerial'?

When I `#include <SoftwareSerial.h>` in that file, then so many errors pop up. Its a cat and mouse game.

First of all, the previous Object calls now get `multiple definitios` errors, for example `multiple definition of `GSM_Module_SW_Serial'`.

Secondly, I get countless of these messages (not only for `READ_GPS`):
`ino:1817: undefined reference to `READ_GPS'`

`READ_GPS` is defined in `globals_non_model.h`, defined in `globals_non_model.cpp`, included in `string_handling_functions.h`. This is then included in the main `ino` (`#include "string_handling_functions.h"`)

body:
This is not the right way to split a big .ino file. You should instead
think in terms of functional units, i.e. software “modules” that address
specific concerns. For example, if a subset of your code is intended to
manage an hyperdrive, then you could move that to a dedicated
“hyperdrive” module:

```c++
// hyperdrive.h -- module interface
* variable declarations (all extern, no initializers)
* function declarations (i.e. prototypes only)
* class definitions
```

```c++
// hyperdrive.cpp -- module implementation
#include <Arduino.h>     // needed if you use the Arduino API
#include "hyperdrive.h"  // to check consistency with the public interface
* variable definitions (without extern, with initializers when relevant)
* function definitions (with bodies)
* class method definitions
```

```c++
// main.ino
#include "hyperdrive.h"
* code of main program
```

**Edit 1**: Answering EDIT 2 of the question.

> All errors are `multiple definitions`

This typically happens when you define a variable in a header (.h) file:
the variable gets defined as many times as that header is included
somewhere. You should not do that. The only things you should ever
define in a header are _types_, which includes _classes_. Everything
else (functions and variables) should only be _declared_ in the header,
and _defined_ in the accompanying .cpp file.

> All the vars in `.h` files have to be `extern`?

Yes. Without the `extern` keyword, you would have a variable
_definition_, and variable definitions belong to the accompanying .cpp
file. The `extern` keyword is needed for writing a variable
_declaration_.

> Can [variables] have a value in the header file?

No. An initial value belongs to the variable _definition_, not to its
declaration.

**Edit 2**: Answering EDIT 3 of the question.

> ```
> model_definitions.h:498:1: error: 'SoftwareSerial' does not name a type
> ```

If the header file references types or objects that are defined
elsewhere, it needs to have the relevant `#include` lines. In this case
you need:

```c++
#include <SoftwareSerial.h>
```

> ```
> multiple definition of `GSM_Module_SW_Serial'
> ```

This line:

```c++
SoftwareSerial GSM_Module_SW_Serial(GSM_RX_PIN, GSM_TX_PIN);
```

is a variable definition. At the risk of repeating myself: _you should
not put variable definitions in header files_. The header should contain
only the declaration:

```c++
extern SoftwareSerial GSM_Module_SW_Serial;
```

whereas the definition should be in the corresponding .cpp file.


body: I had the same problem. This solution is wrong but I tried all types of solutions and eventually had the same problem. What I did was place the extracted code in another file and labeled it .ino in the same folder as the original file and it worked. Someday they might add the .insert"filename" command. It worked great in the assembler world.


body:
If you split the file into multiple .ino files, then the compiler will concatenate them all into one long .ino file before it compiles.  It will put the one that matches the name of the project first and the rest in alphabetical order.  This can cause problems if things end up being used in that long file before they are defined.

You can start the .ino file names with numbers or something and control the order that they get included in, or you can move that code into .h and .cpp files and include it that way.  Header files will be included in the order you include them in the code.


body:
> I moved all the global vars and functions to their respective files. This is what is going on inside:

As Delta_G said, the concatenated file is the main file first (the one with the name of the project) followed by the other files in alphabetic order. This may move global vars to be declared after they are used in other files. I would have left the global vars in the main file.

However as Edgar_Bonet said in his answer, it would probably be better to make the whole thing modular.

---

See my answer [How the IDE organizes things](https://arduino.stackexchange.com/a/13182/10794) - it explains it in more detail.

> 'SoftwareSerial' does not name a type; did you mean 'SoftwareSerial_h'?

Things like includes of libraries therefore have to go in the main file - putting them in sub files breaks the inclusion of those libraries, hence that error message.


body:
You need to treat the .ino file as a **project file**. Just put in that the includes for things like software serial. That triggers the IDE to include the appropriate libraries. Don't put any other code in it. Put declarations into .h files and definitions (ie. variable values and functions) into .cpp files.

If you do it that way make sure you do the usual C and C++ convention. Make forward declarations of functions, in case you attempt to use a function before its definition is found. These would normally go into .h files.

> Some extra questions:
>
>   All the vars in .h files have to be extern?

If you don't want multiple declaration errors you should be **declaring** but not **defining** variables in your .h files. So yes, they should be extern.

>    Can they have a value in the header file? (eg extern char value = {"0"};)

No - because you will be including it multiple times, probably. In fact you can't have a value on an extern, it doesn't make sense. Using extern means it is defined elsewhere.

---

Put the declarations in the .h files with extern in front of them. Then they have to be defined somewhere (ie. given a value). You could make a .cpp file specifically for that purpose.

Did you read [the link I gave](https://arduino.stackexchange.com/questions/13178/classes-and-objects-how-many-and-which-file-types-do-i-actually-need-to-use-the/13182#13182)? That goes into it in some detail.

---

>     //.ino
>     #include "globals.h"
>     #include "functions.h"
>
>     //globals.h
>     *Has header guard
>     *All variables here are extern
>     *Contains function prototypes - the definition is in functions.h
>     *Contains objects (like softWareSerial)

The includes for SoftwareSerial need to go into the .ino file because that is what the IDE scans for, to see what libraries to link into your project.

Just put the (includes for the) libraries into the .ino file, nothing else.

---

Header guards just stop multiple copies of the same .h file being included in the same compilation unit. They don't stop multiple .h files being included into different compilation units (multiple .cpp files). So they may not achieve much here.


message:
Arduino Freezes (probably because of I2C) - Need help to write robust script

Arduino Pro mini 3.3V stucks few hours after startup. After repowered, it begins to stuck within a few seconds. If I wait long enough before turning it on it stucks little later for example now it lasted 45 seconds before stuck. Whenever it is stuck SCL pin is high and SDA pin is low so I suspect somethin about I2C is wrong. There is an 60 seconds countdown at start and the stuck usually happens there, you will see it is an extremely simple for loop. There are SHT31 sensor, 128x64 SH1106 driven OLED screen, DS3231 clock module, hc-sr501PIR sensor, LDR, Encoder and a button on the project. Only first three works with I2C and the code for those devices are very short, they are in "start(), updatescreen(), getTime(), getDew()" functions in the long script below so I hope it is not hard to diagnose the problem. I have done some experiments. I isolated SHT31 and OLED, both caused freeze even though all other devices were disconnected (I added blink code to their example test sketch and the blinking stopped after few seconds which means stuck). OLED screen works when it is connected with jumpers outside the PCB so I even suspected the PCB but it is so simple that it shouldn't cause problems. The weird thing is that this device worked perfectly for 2 days before it crushed for the first time.

Schematic:
[![schematic][1]][1]

PCB (some mistakes were fixed later):
[![enter image description here][2]][2]

Real images:

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

Test script (the same freezing problem occurs but easier to read):

    #include <U8g2lib.h>
    #include <Wire.h>

    U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
    void setup() {
      u8g2.begin();
      u8g2.setFont(u8g2_font_ncenB14_tr);
      pinMode(LED_BUILTIN, OUTPUT);
    }

    void loop() {
      u8g2.firstPage();
      do {
        u8g2.setCursor(0, 20);
        u8g2.print(F("Hello World!"));
      } while (u8g2.nextPage());
      delay(1000);
      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
      delay(1000);                      // wait for a second
      digitalWrite(LED_BUILTIN, LOW);
    }

Test script 2 (this time for sht31, the same freezing problem occurs but easier to read):

    #include <Wire.h>
    #include "ClosedCube_SHT31D.h"

    ClosedCube_SHT31D sht3xd;
    void setup() {
      Wire.begin();
      sht3xd.begin(0x44);
      pinMode(LED_BUILTIN, OUTPUT);
    }

    void loop() {
      digitalWrite(LED_BUILTIN, HIGH);
      SHT31D result = sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50);
      delay(1000);
      digitalWrite(LED_BUILTIN, LOW);
      delay(1000);
    }

Full Script:

    #include "Wire.h"
    #include "ClosedCube_SHT31D.h"
    #include <DS3231.h>
    #include "LowPower.h"
    #include <EEPROM.h>
    #include <U8g2lib.h>

    #define PIR 2
    #define ENCODER_BUTTON 3
    #define ENC_A 4
    #define ENC_B 5
    #define FAN_MAIN_REL 8
    #define FAN_SECOND_REL 9
    #define BUZZER 10
    #define LIGHT_REL 11
    #define LDR_PWR 12
    #define LDR_READ A0
    #define FREE_RUN_BUTTON A2
    #define CLOCK_INT A3

    volatile bool PIR_flag, TIM1_flag, But_flag, FreeRun_flag, Settings_flag;
    uint8_t Weather_flag;  // Weather_flag is special, it is set/reset by a regular function, 0: Dew is under threshold, 1: Dew is over DewThres but less than DewThresExtreme, 2: Dew is over DewThresExtreme
    volatile int16_t encVal;

    // Variables:
    float Temp, Hum, Dew;
    bool DewTrigEnabled;
    uint8_t FanMotTrigEnabled;  // for fan relay
    bool LightRelEnabled;       // for light relay
    uint16_t waitDur;           // Setting 1
    uint16_t Runtime;           // Setting 2
    float DewThres;             // Setting 3
    float DewThresExtreme;
    uint16_t FreeRunDur;  // Setting 5
    bool FreeRunStatus;
    bool DNDenabled;
    uint8_t DND_SH;  // DND start Hour
    uint8_t DND_SM;  // DND start Minute
    uint8_t DND_FH;  // DND finish Hour
    uint8_t DND_FM;  // DND finish Minute
    uint16_t counter;
    uint8_t hour, minute;
    bool LDRenabled;
    uint16_t LDRThres;
    bool screen_awake = true;  // screen starts "on"
    uint8_t FanRelayStatus;
    const uint8_t screenTime = 60;  // Screen On time without motion (seconds)
    const float DewUSratio = 0.98;  // Determines the dew point which the FAN turns off if it was triggered by the Dew in the first place
    const uint8_t phaseLim = 120;   // Determines LDR check rate if light is off but LDR is enabled, each phase corresponds to 5 seconds.

    ClosedCube_SHT31D sht3xd;
    RTClib myRTC_1;
    DS3231 myRTC_2;
    U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

    void swCounter(bool turn_on, uint32_t cnt = 0) {
      if (turn_on) {
        counter = cnt;
        TCNT1 = 0;                            // TIM1 counter value
        TCCR1B |= (1 << CS12) | (1 << CS10);  // Start timer by setting prescaler to 1024
      } else
        TCCR1B &= ~(1 << CS12) | ~(1 << CS10);  // Stop TIM1
    }

    void setup() {
      LoadPinsAndEEPROM();

      Wire.begin();

      // Temp&Hum Sensor:
      sht3xd.begin(0x44);

      // Clock Module:
      myRTC_2.setA2Time(
        0, 0, 0,
        0b01110000, false, false, false);
      myRTC_2.turnOnAlarm(2);

      myRTC_2.setA1Time(
        0, 0, 0xFF, 0,
        0b00001110, false, false, false);
      myRTC_2.turnOffAlarm(1);
      myRTC_2.checkIfAlarm(1);  // clear Alarm 1 flag

      sht3xd.heaterEnable();
      // OLED Screen:
      u8g2.begin();
      u8g2.setFont(u8g2_font_lubB12_tr);
      for (int i = 60; i > 0; i--) {
        u8g2.firstPage();
        do {
          u8g2.drawStr(6, 25, "by Prince");
          u8g2.setCursor(58, 55);
          u8g2.print(i);
          if (i == 30) sht3xd.heaterDisable();
        } while (u8g2.nextPage());
        delay(1000);
      }
      u8g2.setDrawColor(2);

      //TIM1 Configuration:
      TCCR1A = 0;
      TCCR1B = 0;
      TIMSK1 |= (1 << OCIE1A);  // Output Compare A Match Interrupt Enable
      OCR1A = 39061;            // Output Compare A
      TCCR1B |= (1 << WGM12);   // CRC (auto reset timer when it reaches OCR1A)
      TCNT1 = 0;                // TIM1 counter value

      // Attach interrupts (PinChanges and INTpin)
      attachInterrupt(digitalPinToInterrupt(PIR), ISR_PIR, RISING);
      attachInterrupt(digitalPinToInterrupt(ENCODER_BUTTON), ISR_ENCODER_BUTTON, FALLING);
      PCICR |= (1 << PCIE1);                      // A0-A6 group can create interrupt
      PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);  // A2 and A3 pins can create interrupt
      PCMSK2 |= (1 << PCINT20) | (1 << PCINT21);  // D4 and D5 pins can create interrupt

      Beep(1, 100, 0);
      PIR_flag = false;
      But_flag = false;
    }

    void loop() {
      checkButtons();  // After execution it will return.
      if (!getDNDstatus()) {
        getDew();  // sets flag accordingly

        if (PIR_flag) {
          if (FanMotTrigEnabled == 1) {
            TIM1_flag = true;  // Update screen initially
            screenPwr(1);

            unsigned long lastMotion;
            uint8_t step = 1;
            if (waitDur <= 5) step = 2;  // PIR_flag is already true at this point
            else swCounter(1, waitDur);

            for (step = step; step <= 2; step++) {  // 1: waiting, 2: armed, 3: Running
              if (step == 2) {
                (waitDur >= 90) ? counter = 60 : counter = 30;  // Deciding how long ahead it will check for motion
                swCounter(1, counter);
                PIR_flag = false;
                updateScreen(step);
              }
              while (counter > 0) {  // Counter Loop
                if (checkButtons()) return;
                if (PIR_flag) {
                  PIR_flag = false;
                  lastMotion = millis();
                  if (step >= 2) {    // if it's armed or Running and Motion is detected
                    if (step == 2) {  // if it's armed and Motion is detected
                      if (FanRelayStatus != 2) swFanRelays(1);
                      step = 3;  // Motion..
                      updateScreen(step);
                    }
                    swCounter(1, Runtime);  // Restart interval
                  }
                }
                if (TIM1_flag) {
                  TIM1_flag = false;
                  if (getDNDstatus()) return;
                  if (step == 1 && (millis() - lastMotion) / 1000 >= screenTime) return;
                  getDew();
                  DewControl(step != 3);  // in case Dew increases while on wait
                  updateScreen(step);
                }
              }
            }
          } else if (FanMotTrigEnabled != 1) {  // Mot trig is disabled but there is motion
            PIR_flag = false;
            if (FanMotTrigEnabled == 2) swFanRelays(0);
            RunScreen(false);
          }
        }

        DewControl(true);
        Sleep(true);

      } else {  // if it's DND times:
        if (PIR_flag) {
          PIR_flag = false;
          RunScreen(true);
        }
        if (getDNDstatus()) Sleep(false);  // DnD status is rechecked because it might have been stuck in RunScreen by the user when DND is over.
      }
    }

    void DewControl(bool cmd1) {  // 0: cannot turn the fan "off" but only "on" 1: can both turn "on" and "off"
      if (Weather_flag == 0 && cmd1) swFanRelays(0);
      else if (Weather_flag == 1) swFanRelays(1);
      else if (Weather_flag == 2) swFanRelays(2);
    }

    void RunScreen(bool cmd1) {  // 0: dont return based on DND, 1: return if not in DND times anymore (prevents being stuck in DND if screen is on)
      TIM1_flag = true;          // Update screen initially
      screenPwr(1);
      swCounter(1, screenTime);  // Fixed Run screen time
      while (counter > 0) {
        if (checkButtons()) return;
        if (TIM1_flag) {
          if (getDNDstatus()) {
            if (FanRelayStatus) return;
          } else {
            if (cmd1) return;
            DewControl(true);
          }
          getDew();
          updateScreen(0);  // Idle or Dew

          if (PIR_flag) {
            counter = screenTime;
            PIR_flag = false;
          }
          TIM1_flag = false;
        }
      }
      LightRel_IfNeeded(0);
    }

    void getDew() {
      SHT31D result = sht3xd.readTempAndHumidity(SHT3XD_REPEATABILITY_LOW, SHT3XD_MODE_CLOCK_STRETCH, 50);  // used to be a static var
      Temp = result.t;
      Hum = result.rh;

      float a_func = log(Hum / 100) + 17.625 * Temp / (243.04 + Temp);
      Dew = (243.04 * a_func) / (17.625 - a_func);

      if (!DewTrigEnabled || (Dew <= DewThres * DewUSratio) || (Dew < DewThres && FanRelayStatus == 0)) Weather_flag = 0;
      else if (Dew < DewThresExtreme) Weather_flag = 1;
      else Weather_flag = 2;
    }

    bool getDNDstatus() {  // check if hours and minutes are in the interval
      if (!DNDenabled) return false;

      updateTime();
      uint16_t currentmin = hour * 60 + minute;

      uint16_t localDNDstart = DND_SH * 60 + DND_SM;
      uint16_t localDNDfinish = DND_FH * 60 + DND_FM;

      if (localDNDstart < localDNDfinish) return (currentmin >= localDNDstart && currentmin < localDNDfinish);
      else return (currentmin >= localDNDstart || currentmin < localDNDfinish);
    }

    void updateTime() {
      if (myRTC_2.checkIfAlarm(2)) {
        DateTime now;  // used to be a static var
        now = myRTC_1.now();
        hour = now.hour();
        minute = now.minute();
      }
    }

    void swFanRelays(uint8_t cmd1) {  // 0: turn off, 1: turn on
      if (FanRelayStatus == cmd1) return;
      bool PIR_flag_original = PIR_flag;
      if (cmd1 == 0) {
        digitalWrite(FAN_MAIN_REL, LOW);
        digitalWrite(FAN_SECOND_REL, LOW);
        FanRelayStatus = 0;
      } else if (cmd1 == 1) {
        digitalWrite(FAN_MAIN_REL, HIGH);
        if (FanRelayStatus != 2) {
          digitalWrite(FAN_SECOND_REL, HIGH);
          delay(500);
        }
        digitalWrite(FAN_SECOND_REL, LOW);
        FanRelayStatus = 1;
      } else if (cmd1 == 2) {
        digitalWrite(FAN_MAIN_REL, HIGH);
        digitalWrite(FAN_SECOND_REL, HIGH);
        FanRelayStatus = 2;
      }
      delay(100);
      if (!PIR_flag_original) PIR_flag = false;
      But_flag = false;
      FreeRun_flag = false;
    }

    void LightRel_IfNeeded(bool cmd1) {  // 0: turn OFF Light Relay, 1: turn ON Light Relay
      static bool LightRelStatus;
      bool LDRresult;
      static uint8_t phase;  // regularly check light level in case brightness changes in the room over time.

      switch (cmd1) {
        case 0:
          if (!LightRelStatus) return;
          LightRelStatus = false;
          phase = 0;
          digitalWrite(LIGHT_REL, LOW);
          delay(100);
          PIR_flag = false;
          But_flag = false;
          FreeRun_flag = false;
          break;

        case 1:
          if (!LightRelStatus && phase == 0) {
            if (LDRenabled) {
              digitalWrite(LDR_PWR, HIGH);
              delay(10);
              LDRresult = (analogRead(LDR_READ) > LDRThres);  // Darkness --> High resistance --> High voltage on LDR --> TRUE              Lit --> Low resistance --> Low voltage on LDR --> FALSE
              digitalWrite(LDR_PWR, LOW);
            } else LDRresult = true;

            if (LDRresult) {
              LightRelStatus = true;
              digitalWrite(LIGHT_REL, HIGH);
              delay(100);
              PIR_flag = false;
              But_flag = false;
              FreeRun_flag = false;
            }
          }
          phase++;
          if (phase > phaseLim) phase = 0;  // default value is 120 which means 10 minutes
          break;
      }
    }

    void Sleep(bool cmd1) {  // 0: Sleep normal 1: Sleep without turning off the Fan
      if (cmd1 == 0) swFanRelays(0);
      LightRel_IfNeeded(0);
      screenPwr(0);
      updateTime();
      PIR_flag = false;
      But_flag = false;
      FreeRun_flag = false;

      LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    }

    void updateScreen(uint8_t cmd1) {  // 0: idle or Dew Trig, 1: Detected, 2: Waiting, 3: Armed, 4: Mot Trig, 5: Free run dur
      String info;
      LightRel_IfNeeded(1);  // Regularly called because brigthness of the room info is updated every phase*5/60 minutes
      updateTime();

      switch (cmd1) {
        case 0:
          if (FanRelayStatus == 0) info = "Idle";
          else if (FanRelayStatus == 1) info = "Dew";
          else info = "OverDew";
          break;
        case 1:
          info = "Waiting";
          if (FanRelayStatus == 1) info += "&Dew";
          else if (FanRelayStatus == 2) info += "&OverDew";
          break;
        case 2:
          info = "Armed";
          if (FanRelayStatus == 1) info += "&Dew";
          else if (FanRelayStatus == 2) info += "&OverDew";
          break;
        case 3:
          info = "Motion";
          if (Weather_flag == 1) info += "&Dew";
          else if (Weather_flag == 2) info += "&OverDew";
          break;
        case 4:
          info = "<";
          info += String(counter / 60 + 1);
          info.remove(info.indexOf('.'));
          info += " mins";
          break;
      }

      u8g2.firstPage();
      do {
        u8g2.setFont(u8g2_font_6x10_mr);  // u8g2_font_haxrcorp4089_tn
        u8g2.setCursor(0, 7);
        u8g2.print(info);

        u8g2.setCursor(99, 7);
        if (hour < 10) u8g2.print("0");
        u8g2.print(hour);
        u8g2.print(":");
        if (minute < 10) u8g2.print("0");
        u8g2.print(minute);

        u8g2.drawLine(0, 10, 128, 10);

        u8g2.setFont(u8g2_font_fub20_tn);
        u8g2.setCursor(0, 38);
        if (Temp < 10 && Temp >= 0) u8g2.print("0");
        u8g2.print(Temp, 1);
        u8g2.setCursor(0, 64);
        u8g2.print(Hum, 1);
        u8g2.setCursor(71, 61);
        if (Dew < 10) u8g2.print("0");
        u8g2.print(Dew, 1);
        if (Dew < DewThres) u8g2.drawFrame(70, 38, 58, 26);
        else u8g2.drawBox(71, 39, 56, 24);

        u8g2.setFont(u8g2_font_lubB12_tr);
        u8g2.drawStr(55, 30, "*C");
        u8g2.drawStr(55, 64, "%");

        if (FreeRunStatus == true) u8g2.drawStr(81, 30, "FREE");
        else if (getDNDstatus()) u8g2.drawStr(82, 30, "DND");

      } while (u8g2.nextPage());
    }

    void screenPwr(bool cmd1) {
      if (cmd1 == screen_awake) return;

      switch (cmd1) {
        case 0:
          u8g2.setPowerSave(1);
          u8g2.clear();
          screen_awake = false;
          break;

        case 1:
          u8g2.setPowerSave(0);
          swCounter(0);
          screen_awake = true;
          break;
      }
    }

    void FreeRun() {
      Beep(1, 500, 0);
      FreeRun_flag = false;
      FreeRunStatus = true;
      getDew();
      swFanRelays(1);
      swCounter(1, FreeRunDur);
      updateScreen(4);
      screenPwr(1);
      while (counter > 0) {
        if (But_flag) {
          FreeRunStatus = false;
          Settings();
          return;
        }
        if (FreeRun_flag) {
          Beep(1, 100, 0);
          delay(1000);
          if (!digitalRead(FREE_RUN_BUTTON)) {  // if the user holds the button down
            swFanRelays(0);
            Beep(2, 100, 100);
            while (!digitalRead(FREE_RUN_BUTTON)) delay(100);  // For the user to remove hand
            delay(500);                                        // prevent debouncing
            FreeRun_flag = false;
            break;
          } else {
            FreeRun_flag = false;
            if (FanRelayStatus == 1) swFanRelays(2);
            else if (FanRelayStatus == 2) swFanRelays(1);
          }
        }
        if (TIM1_flag) {
          TIM1_flag = false;
          if (getDNDstatus()) break;
          getDew();
          updateScreen(4);
        }
      }
      DewControl(true);
      FreeRunStatus = false;
      PIR_flag = false;  // Ignore the motion while in "Free Run" mode
    }

    bool checkButtons() {
      if (FreeRun_flag) {
        if (!getDNDstatus()) {
          FreeRun();
          return 1;
        } else {  // if Free Run is pressed during DND, deny Free Run
          Beep(3, 50, 50);
          FreeRun_flag = false;
        }
      } else if (But_flag) {
        Beep(1, 100, 0);
        delay(1000);  // If button is held down
        if (!digitalRead(ENCODER_BUTTON)) {
          Settings();
          return 1;
        }
        But_flag = false;
      }
      return 0;
    }

    void Beep(uint8_t rep, uint8_t dur_act, uint8_t dur_pass) {  // repetition, duration of beeping, duration of pauses
      for (int i = 0; i < rep; i++) {
        digitalWrite(BUZZER, HIGH);
        delay(dur_act);
        digitalWrite(BUZZER, LOW);
        if (i < (rep - 1)) delay(dur_pass);
      }
    }

    void LoadPinsAndEEPROM() {

    #define FanMotTrigEnabled_Address 0
    #define waitDur_Address 1
    #define Runtime_Address 3
    #define DewTrigEnabled_Address 5
    #define DewThres_Address 6
    #define DewThresExtreme_Address 10
    #define LightRelEnabled_Address 14
    #define LDRenabled_Address 15
    #define LDRThres_Address 16
    #define DND_Enabled_Address 18  // DND enabled
    #define DND_SH_Address 19       // DND start Hour
    #define DND_SM_Address 20       // DND start Minute
    #define DND_FH_Address 21       // DND finish Hour
    #define DND_FM_Address 22       // DND finish Minute
    #define FreeRunDur_Address 23

      EEPROM.get(FanMotTrigEnabled_Address, FanMotTrigEnabled);
      EEPROM.get(waitDur_Address, waitDur);
      EEPROM.get(Runtime_Address, Runtime);
      EEPROM.get(DewTrigEnabled_Address, DewTrigEnabled);
      EEPROM.get(DewThres_Address, DewThres);
      EEPROM.get(DewThresExtreme_Address, DewThresExtreme);
      EEPROM.get(LightRelEnabled_Address, LightRelEnabled);
      EEPROM.get(LDRenabled_Address, LDRenabled);
      EEPROM.get(LDRThres_Address, LDRThres);
      EEPROM.get(DND_Enabled_Address, DNDenabled);
      EEPROM.get(DND_SH_Address, DND_SH);
      EEPROM.get(DND_SM_Address, DND_SM);
      EEPROM.get(DND_FH_Address, DND_FH);
      EEPROM.get(DND_FM_Address, DND_FM);
      EEPROM.get(FreeRunDur_Address, FreeRunDur);

      // DEBUG:
      /*
      FanMotTrigEnabled = 1;
      waitDur = 10;
      Runtime = 10;
      DewTrigEnabled = true;
      DewThres = 18.0;
      DewThresExtreme = 19.0;
      LightRelEnabled = true;
      LDRenabled = true;
      LDRThres = 512;
      DNDenabled = false;
      DND_SH = 23;
      DND_SM = 45;
      DND_FH = 0;
      DND_FM = 2;
      FreeRunDur = 30;
    */
      pinMode(PIR, INPUT);
      pinMode(LDR_READ, INPUT);
      pinMode(ENC_A, INPUT);
      pinMode(ENC_B, INPUT);

      pinMode(CLOCK_INT, INPUT_PULLUP);  // Datasheet states pullup resistor is necessary
      pinMode(FREE_RUN_BUTTON, INPUT_PULLUP);
      pinMode(ENCODER_BUTTON, INPUT_PULLUP);

      pinMode(FAN_MAIN_REL, OUTPUT);
      pinMode(FAN_SECOND_REL, OUTPUT);
      pinMode(LIGHT_REL, OUTPUT);
      pinMode(BUZZER, OUTPUT);
      pinMode(LDR_PWR, OUTPUT);
    }

    void ISR_PIR() {
      PIR_flag = true;
    }

    void ISR_ENCODER_BUTTON() {
      But_flag = true;
    }

    ISR(PCINT1_vect) {
      if (!digitalRead(FREE_RUN_BUTTON)) FreeRun_flag = true;  // Button has pullup resistor thus "!" is used.
    }

    ISR(TIMER1_COMPA_vect) {
      TIM1_flag = true;
      counter -= 5;
      if (counter <= 0) swCounter(0);
    }

    // Horrible Settings Codes xd:
    ISR(PCINT2_vect) {  // Rotary Encoder Interrupt
      static bool aLastState;
      bool aState = digitalRead(ENC_A);
      bool bState = digitalRead(ENC_B);

      if (aState != aLastState) {
        if (bState != aState) {
          encVal++;
        } else {
          encVal--;
        }
        aLastState = aState;
      }
    }

    void ButDebounce(bool cmd1) {  // 0: Encoder But, 1: Free Run
      if (cmd1) {
        while (!digitalRead(FREE_RUN_BUTTON)) delay(100);  // Wait until button is released
        delay(200);
        FreeRun_flag = false;
      } else {
        while (!digitalRead(ENCODER_BUTTON)) delay(100);  // Wait until button is released
        delay(200);
        But_flag = false;
      }
    }

    String formatTime(int input, bool type = true) {  // type = true means input is seconds, if false it means input is minutes
      int hours = input / 3600;                       // Get the number of hours
      int minutes = (input % 3600) / 60;              // Get the number of minutes
      int remainingSeconds = input % 60;              // Get the number of seconds

      if (!type) {
        hours = minutes;
        minutes = remainingSeconds;
        remainingSeconds = 0;
      }

      // Create a formatted string in the format "hour:minute:second"
      String formattedTime = "";

      if (hours < 10) {
        formattedTime += "0";  // Add leading zero for hours
      }
      formattedTime += String(hours) + ":";

      if (minutes < 10) {
        formattedTime += "0";  // Add leading zero for minutes
      }
      formattedTime += String(minutes) + ":";

      if (remainingSeconds < 10) {
        formattedTime += "0";  // Add leading zero for seconds
      }
      formattedTime += String(remainingSeconds);

      return formattedTime;
    }

    uint8_t setEncVal(uint16_t target, uint8_t inc1, uint8_t inc2, uint16_t inc3, uint8_t lim1, uint8_t lim2) {
      uint16_t a = 0;
      uint8_t b = 0;
      while (a < target) {
        if (b < lim1) a += inc1;
        else if (b < lim2) a += inc2;
        else a += inc3;
        b++;
      }
      return b;
    }

    void Settings() {} // removed because of character limit but I don't run this function before stuck anyway

  [1]: https://i.stack.imgur.com/HsCjA.png
  [2]: https://i.stack.imgur.com/q8XO4.png
  [3]: https://i.stack.imgur.com/WIccf.jpg
  [4]: https://i.stack.imgur.com/hAr9k.jpg

body:
It sounds like over ambitious pull up resistors. They should total about 3K on each bus. I will take a SWAG and say the I2C driver fet is drawing to much current and heating up. When it does that its resistance increase thereby delivering less current. Get your resistors correct and I believe it will work just fine.

If you have freeze spray chill them and they will probably start working until they warm up.

If it was left on for any period of time it is possible you damaged one of the ICs which is no longer driving the bus properly. If you can check it with a scope. If not swat parts.


body:
Are you sure you are using the latest I2C library?  Up until halfway through 2020, the 'official' I2C library had a known failure mode that would cause the I2C buss to hang.  [See my 'Paynters Palace' post on this subject][1] for additional info.

Frank

  [1]: https://www.fpaynter.com/2020/07/i2c-hangup-bug-cured-miracle-of-miracles-film-at-11/