message:
SoftwareSerial will not read all of the printed string when calling readString()

I have an Arduino UNO and an ESP32 that need to communicate to each other using SoftwareSerial. The problem I am coming across is that when I call readString and print it out using Serial, it will not give me everything that has been printed out from my ESP32.

I have my Arduino RX Pin hooked up to 4 and TX hooked up to 5
I have my ESP32 RX2 Pin hooked up to 16 and TX2 pin hooked up to 17, with the GND hooked up to directly to the Arduino GND
I am not using any resistors, straight up 5v of pure power

Arduino UNO Code:
```
// C-standard library
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include <SoftwareSerial.h>

#define RX_PIN 4
#define TX_PIN 5

SoftwareSerial ardSerial(RX_PIN, TX_PIN);

void setup(void) {
  // Get access to network
  pinMode(RX_PIN, INPUT);
  pinMode(TX_PIN, OUTPUT);
  Serial.begin(9600);
  while(!Serial) {}
  ardSerial.begin(9600);
  while(!ardSerial) {}
}

void loop(void) {
  while (ardSerial.available() > 0) {
    String payload = ardSerial.readString();
    Serial.println(payload);
  }
  delay(1000);

}
```

ESP32 Code
```
#include <stdlib.h>
#include <string.h>

#include <SoftwareSerial.h>

SoftwareSerial ardSerial;

void setup(void) {
  // Begin connections
  Serial.begin(115200);
  while (!Serial) {}

  ardSerial.begin(9600, SWSERIAL_8N1, RX2_PIN, TX2_PIN);
  while (!ardSerial) {}
  return;
}

void loop(void) {
  {
    String spotData = "Huge JSON File that needs transferred";
    ardSerial.print(spotData);
  }

  delay(5000);
}
```

Expected result:
- Able to retrieve every little bit of the JSON file that was printed out

Actual result:
- Only receive like half of the JSON file

body:
I see 2 problems with your code:

- You wrote in the comments, that the JSON file is huge. The Uno has only 2kB of RAM and you are trying to lead the complete file into RAM at once. Such a JSON file from Spotify will easily exceed the 2kB (in fact you have even less, because the Arduino framework and SoftwareSerial also use some of the RAM). So you just cannot handle the complete file at once with an Uno.

- You use `readString()`. This function is sure easy, but also has some pitfalls. It uses the `String` class, which utilizes dynamic memory allocation. It allocates a bigger character array in RAM, if the current array is not big enough. That means, that you would need up to 2 versions of your String fitting into RAM while receiving, leaving only about 1kB. Also it will read from the SoftwareSerial interface, until a timeout is hit (1s by default I think). For building a robust communication between the two devices you should read until you reach a special character, for example via `readStringUntil()`. That special character is often the newline character `'\n'`.

**Possible solution:** First we should talk about the limited RAM problem. As stated above you cannot handle the full file at once. You need to handle it in chunks. Whatever you want to do with the data in the end, the Uno will need some time handling the current chunk of data. So you need to pause the transmission of data at the ESP, until the Uno is ready to receive more. Here you can go two ways:

- Send the data in chunks of predefined size (small enough for the Uno to hold at once in its RAM) and wait a predefined time between each chunk, that is long enough for the Uno to handle every data it might have gotten in that chunk. This is the easiest to program, but will necessarily take more execution time.
- Let the Uno signal to the ESP, that its buffer is full, for example by sending a special character to the ESP. The ESP should then stop sending, until it gets the OK from the Uno to proceed the transmission. To send without loosing data the Uno should probably also send the number of bytes received in that chunk. That way the ESP knows exactly, where in the data String the Uno is currently. This is a bit more difficult, though still easy enough and robust.

To handle the sending in chunks I would use the `write(const uint8_t *buffer, size_t size)` method of SoftwareSerial (actually this function comes from the `Print` class, from which `SoftwareSerial` inherits). The buffer is the pointer to the first element of the current chunk in the `char` array with the data. You can get the `char` array via `spotData.c_str()` and you can get the pointer to the n-th element of it via `&(spotData.c_str()[n])`. The second parameter is the size of the chunk in bytes. This needs to be small enough, that the data will fit into the RAM of the UNO, together with all the RAM needed for processing the data.

On the Uno I would then do the reading bytewise. Something like this:

    char data[BUFFER_SIZE]="";
    int pos=0;

    void loop(){
        if(ardSerial.available()){
            data[pos] = ardSerial.read();
            if(pos == BUFFER_SIZE - 1){
                // Handle chunk of data
                pos = 0; // reset position to reuse buffer
            } else {
                pos++;
            }
        }
    }

I have left out some parts to only demonstrate the principle. Also you need to define `BUFFER_SIZE` yourself, depending on the available RAM.

Obviously this does not implement the second option with the pause signal, which is more complex.

---

Apart from sending and receiving you will need to think about how to process the chunks of data. This depends largely on what exactly you want to do with that data. Just sending them via Serial is easy. Interpreting the data in chunks is more difficult.


sender: user

sender: assistant

body:
There are two ways to implement a parser for a language like JSON or
XML:

1. Have the parser swallow the whole document at once, and produce an
   in-memory representation of the same data.

2. Have the parser return control to the caller for each “event” it
   detects, where an “event” is typically a primitive data item, or the
   start or the end of a container.

Parsers of the first kind are much easier to use, but this can be
expensive in RAM usage if you want to parse a alrge document. The second
kind of parsers are harder to use, but they are able to parse huge
documents using a minimal amount of memory.

On an Arduino, you would typically use ArduinoJson, which is a parser of
the first kind, not ideal for parsing huge documents on little memory. A
quick search for “event driven C++ JSON parser” got me [JsonReader][]. I
did not try it, and do not know whether that would work on Arduino, but
it shows that at least this kind of parsers do exist for JSON in C++.
You may want to search further along this way.

Before you dig into this, however, I suggest you give ArduinoJson a
second chance. ArduinoJson has a couple of tricks that can help dealing
with large documents:

* You can ask it to filter the data as it reads it, in order to only
  keep in memory the items you are actually interested in.

* You can deserialize in chunks, and use the data extracted from one
  chunk at a time.

Both techniques are explained in the tutorial [How to deserialize a very
large document?][tut].

Also, let's not forget the obvious: you should not attempt to store the
raw JSON document in memory. Instead, you should give ArduinoJson a
reference to your stream (namely `ardSerial`), and let it directly pull
the bytes as it parses.

[JsonReader]: https://github.com/xquintana/JsonReader
[tut]: https://arduinojson.org/v6/how-to/deserialize-a-very-large-document/


message:
Just installed Arduino 2.0.3 - what is windows path to associated libraries?

Just installed Arduino 2.0.3 and I attempted to build a sketch which includes a library that I manually installed in version 1.8.19 and it can't be found:

In my program I have
`#include <DS3231.h>`

Now, attempting to compile it cannot find the library.

What is the path to the basic libraries in Arduino 2.0.3?

body:
I found the location by examining the app while it was running.

The associated libraries are at:

`%localappdata%\arduino15\Libraries`

That will look like : `C:\Users\<username>\AppData\Local\Arduino15\libraries`

I created a new folder named `DS3231` dropped in the .cpp, .h and .config files and now my sketch compiles with the `#include <DS3231.h>`

Kind of blows my mind that the Arduino 2.0.3 Libraries are found in a directory named Arduino15.  Is that an old version or something?

Here's what I see in preferences -- don't see a location for user libraries:

[![arduino preferences][1]][1]

The best location will be your sketchbook location + a folder named `libraries`.

For example, in my case my sketchbook location is :

`c:\users\<username>\dev\arduino`

so my library folder should be:

`c:\users\<username>\dev\arduino\libraries`

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


message:
Arduino nano timing precision

How precisely can an Arduino nano be timed? The project I am working on needs two Arduino nano to work synchronously. Arduino one have to activate a relay after 2700 sec and Arduino two have to activate a second relay after 2700.360 sec (360 milli seconds after )

With the code given below the required accuracy is not achieved.

```
volatile uint32_t ovfCount = 0UL;
volatile uint32_t currentTime = 0UL;
volatile unsigned long time_prev = 0UL;
volatile unsigned long dT = 0UL;

unsigned long delayTime = 2700UL;     //Seconds
unsigned long coilActivateTime = 5UL;  // seconds

volatile unsigned long _waitTime = delayTime * 1000UL + 360UL;
uint32_t _burnTime = coilActivateTime * 1000UL;

volatile bool coilOn_flag = false;

ISR(INT0_vect) {

  EIMSK = 0b00000000;

  TCCR1B = B00011100;
  PORTB ^= (1<<0);
  ovfCount = 0;
  TIFR2 = 0;
  TCNT2 = 0;

}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(TIMER1_OVF_vect) {
  //pass
}

ISR(TIMER1_COMPA_vect) {
  //pass
}

ISR(TIMER1_COMPB_vect) {
  uint8_t tcnt2 = TCNT2;
  uint32_t ovf_count = ovfCount;

  if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
    ovf_count++;
  }

  uint32_t totalCount = ovf_count << 8 | tcnt2;  // raw count
  // uint32_t currentTime = totalCount * 0.004;     // milli second
  currentTime = totalCount * 4UL/1000UL;  // milli second

  if (currentTime >= _waitTime) {
    PORTC ^= (1 << 5);   // relay Switch
    TCCR1A = B00000010;
    TIMSK1 = B00000101;
    PORTB |= (1<<1);
    if (coilOn_flag) {
      TCCR1B = 0;
      PORTB ^= (1 << 1) | (1<<0);
    }
    coilOn_flag = true;
    _waitTime = _burnTime;
    ovfCount = 0;
    TCNT2 = 0;
  }
}

void setup() {
  Serial.begin(115200);
  /*setting the pin directions*/
  DDRB |= (1 << 1) | (1 << 0); // gL, rL
  DDRC |= (1 << 5);  // relay
  DDRD &= B11111011; // interrupt- interrupt

  /* INITIAL STATE SETTING FOR THE PINS */
  PORTB &= B11111100; // rL, gL
  PORTC &= B11011111; // relay

  /* 8Bit Timer*/
  TCCR2A = 0;
  TCCR2B = 0;
  TCCR2A = B00000011;
  TCCR2B = B00001100;
  OCR2A = 250;
  TCNT2 = 0;
  TIFR2 = 0;
  TIMSK2 = B00000001;

  /* 16 bit timer */
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1A = B10000010;
  // TCCR1B = B00011100;
  TCCR1B = 0;
  ICR1 = 62461;
  OCR1A = 6206;
  OCR1B = 624;
  TCNT1 = 0;
  TIFR1 = 0;
  TIMSK1 = B00000111;

  /* External INTERRUPT */
  EICRA = 0b00000010;
  EIFR = 0;
  EIMSK = 0b00000001;

  PORTB ^= (1<<0);
}

void loop() {

}
```

How to correct the code.?

body:
The Arduino Nano is nowhere accurate enough for your application, and
this has nothing to do with your code: it is a hardware limitation. 360
extra milliseconds after 2,700 seconds is a difference of only
133 ppm (parts per million). The Arduino Nano is clocked off a
ceramic resonator, and these time sources carry a typical error of the
order of 1,000 ppm. The best thing the code can do is count the
clock cycles with perfect accuracy, which makes the software timing as
good as the underlying hardware, but never better.

Some options you may try:

1. The one that seems most obvious is to have the first Arduino somehow
   send a trigger signal to the second one when it activates the first
   relay. Or have the second Arduino sense the state of that relay.
   Then, all the second Arduino has to do is wait for 360 ms, which
   it can easily do with reasonable accuracy.

2. If there is no way the Arduinos can communicate, then you could try
   to add external time sources to the Arduinos. Some RTC modules can
   output a 32,768 Hz signal that could be accurate enough for your
   needs. Look for a temperature-compensated RTC, as those are more
   accurate.

3. If you cannot add extra hardware, you could try to calibrate the
   clocks of your Arduinos in order to compensate for their relative
   drift. Keep in mind though that the drift rate is
   temperature-dependent, and wanders randomly even at constant
   temperature. First read the article [Arduino clock frequency
   accuracy][jorisvr], by Joris\_VR, to get an idea of the accuracy you
   could expect from such calibration.

[jorisvr]: http://jorisvr.nl/article/arduino-frequency


message:
avrdude: usbdev_open(): cannot open device: Permission denied

I'm trying to upload anything to my Arduino Uno Wifi Rev2, I'm on Arch Linux, but I'm failing with the following error be it via IDEv2 or `arduino-cli`:

> avrdude: usbdev_open(): cannot open device: Permission denied
>
> avrdude: jtag3_open_common(): Did not find any device matching VID 0x03eb and PID list: 0x2145

The device permissions:

    crw-rw-rw- 166,0 root uucp  9 Jan 23:22 /dev/ttyACM0

My udev rule:

    KERNEL=="ttyACM[0-9]",MODE="0666",GROUP="uucp",TAG+="uaccess"

`lsusb`:

    Bus 001 Device 005: ID 03eb:2145 Atmel Corp. ATMEGA328P-XMINI (CDC ACM)

First two entries from `udevadm info -a -n /dev/ttyACM0`:

      looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1/tty/ttyACM0':
        KERNEL=="ttyACM0"
        SUBSYSTEM=="tty"
        DRIVER==""
        ATTR{power/control}=="auto"
        ATTR{power/runtime_active_time}=="0"
        ATTR{power/runtime_status}=="unsupported"
        ATTR{power/runtime_suspended_time}=="0"

      looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.1':
        KERNELS=="1-3:1.1"
        SUBSYSTEMS=="usb"
        DRIVERS=="cdc_acm"
        ATTRS{authorized}=="1"
        ATTRS{bAlternateSetting}==" 0"
        ATTRS{bInterfaceClass}=="02"
        ATTRS{bInterfaceNumber}=="01"
        ATTRS{bInterfaceProtocol}=="01"
        ATTRS{bInterfaceSubClass}=="02"
        ATTRS{bNumEndpoints}=="01"
        ATTRS{bmCapabilities}=="6"
        ATTRS{iad_bFirstInterface}=="01"
        ATTRS{iad_bFunctionClass}=="02"
        ATTRS{iad_bFunctionProtocol}=="01"
        ATTRS{iad_bFunctionSubClass}=="02"
        ATTRS{iad_bInterfaceCount}=="02"
        ATTRS{physical_location/dock}=="no"
        ATTRS{physical_location/horizontal_position}=="left"
        ATTRS{physical_location/lid}=="no"
        ATTRS{physical_location/panel}=="top"
        ATTRS{physical_location/vertical_position}=="upper"
        ATTRS{supports_autosuspend}=="1"

I feel like I've tried everything so far:
 - `sudo chmod a+rw /dev/ttyACM0`
 - `sudo usermod -a -G uucp $USER`
 - adding udev rule with all different configs (although if chown/chmod doesn't work what will it change??)
 - changing ownership to my user...
 - I checked the process for the IDE to make sure it runs on my user and it does
 - After all these steps I always either restarted and/or reloaded everything with `sudo udevadm control --reload-rules && sudo udevadm trigger`
 - Went through plethora of similar topics, no clues

I feel like I must be doing something awfully stupid here, it doesn't make any sense to me why it wouldn't work even after I chown'ed it to my user...

body:
Looking at the board definition for the UNO WIFI R2, it doesn't use the serial port for upload. It's using an mdbg chip that it speaks to over a non-cdcacm USB protocol. Getting yourself into the group-owner for the serial device is good for communicating to the board through the serial monitor though.

The megaavr board package seems to [come with a file][1] for creating your udev rules that you should find at:
```sh
"${USER}/.arduino15/packages/arduino/hardware/megaavr/1.8.8/scripts/create_dfu_udev_rule"
```

The 1.8.8 subdirectory of megaavr is current as of writing. It will no doubt change. I still have 1.8.7 on my system.

Running it should create the necessary udev rule for allowing avrdude to speak directly to the USB device. Specifically they're adding this:
```txt
SUBSYSTEM=="usb", ATTR{idVendor}=="03eb", ATTR{idProduct}=="2145", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1"
```

They seem to be creating a udev rule for the tty device as well, though that shouldn't strictly be necessary given what you've already done with becoming a member of the serial device's group. Basically you're doing it by becoming a member of the owning group where what they did was just open the device up to RW permissions for everyone.

  [1]: https://github.com/arduino/ArduinoCore-megaavr/blob/1.8.8/scripts/create_dfu_udev_rule


message:
Is it possible to know how long an ESP8266 was in deep sleep?

I'm working on a low power device that implements an ESP8266 MCU and uses it's deep sleep feature. The firmware uses the Arduino C++ library.

Part of the functionality requires knowing the time. To do this, I am using `configTime` to get the time (i.e. NTP). But, to reduce power consumption, I only connect to WiFi every 24 hours. The ESP8266 wakes every hour (to decide if it should do something or go back to sleep). To keep time, I record the last known unix timestamp to RTC memory and upon waking add the amount of time that the device was told to deep sleep (i.e. 1 hour).

The flaw in this design: Part of the requirement is that the user needs to be able to wake the device manually with a button press and interrupt the normal sleep pattern, but if the device is woken with the reset button, it adds an hour to the time and the time becomes completely inaccurate (because an hour was added, even though it could be seconds since deep sleep started).

Is there a way, using the ESP8266 API, to tell how long the device was *actually* in deep sleep? That way, on wake, instead of blindly adding 1 hour to the RTC-saved unix timestamp, I can add the amount of time that the MCU was in deep sleep. The [datasheet][1] seems to only mention the RTC a few times in not much detail.

If no firmware solution exists, what hardware solution could I use?

Thinking out loud: I think a compromise could be to detect if the reset button was pressed (latch/flip flop/register, maybe?). In this case I still wouldn't be able to tell how long the MCU was asleep, but at least I'd be able to tell if I should add time. I found that `system_get_rst_info` is based on how the device went to sleep (i.e. if woken from deep sleep by pressing the reset button, the reason is `REANSON_DEEP_SLEEP_AWAKE`), so I couldn't see how to make use of that in this case. I suppose I could add an external RTC, negating the need to calculate how long the MCU was in deep sleep, and just use that external IC for time keeping.

Edit: Apparently, [`rtctime.dsleep()`][2] provides time keeping across deep sleep, but it's [LUA only][3] so not useful to me. The [source][4] is written in C, but I can't see anything that would help.

> Time is kept across the deep sleep. I.e. rtctime.get() will keep working (provided time was available before the sleep).

  [1]: https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
  [2]: https://nodemcu.readthedocs.io/en/release/modules/rtctime/#rtctimedsleep
  [3]: https://www.esp8266.com/viewtopic.php?p=67168
  [4]: https://github.com/nodemcu/nodemcu-firmware/blob/release/app/modules/rtctime.c

body:
I believe the answer is **no** (you cannot tell exactly how long an ESP8266 was asleep), given these constraints:

 1. If an external RTC cannot be used.
 2. If the MCU does not connect to Wi-Fi every time it wakes.
 3. If the MCU can be woken arbitrarily by the user pressing the reset button.

In other words, if the ESP8266 does not connect to Wi-Fi every time it wakes, you can only estimate the time based on how long it *should* have been in deep sleep, but you can't know for sure without either going online or using an external RTC.


message:
Wire.write invalid conversion from ‘char*’ to ‘const uint8_t*

I have written this code:

    char message[4];
    memcpy(message, &delta, 4);

    Wire.write(message, 4);

When I try to compile I get this warning:

    warning: invalid conversion from ‘char*’ to ‘const uint8_t* {aka const unsigned char*}’ [-fpermissive]
       Wire.write(message, 4);
                            ^

Also followed by this note:

    In file included from main.ino:5:0:
    /usr/share/arduino/libraries/Wire/Wire.h:61:20: note:   initializing argument 1 of ‘virtual size_t TwoWire::write(const uint8_t*, size_t)’
         virtual size_t write(const uint8_t *, size_t);
                        ^

I do not understand what is wrong?

body:
Try

    Wire.write((const uint8_t*) message, 4);

I.e., cast it to the correct type, uint8_t and char are the same (at least on Arduino and for this example, as you do not char about unsigned/signed values).

(see also the comment of the busybee below, for using the cleaner C++ cast).


message:
How to send multiple bytes with Wire without copying

When I need to send multiple bytes via Wire, for example a long int, I cast it to a byte array and specify a length

    long int i;
    Wire.write((byte*)&i, 4);

But if I want to send bytes from more than 1 variable I need to create a buffer

    byte i;
    byte j;
    byte message[2] = {i, j};
    Wire.write(message, 2);

If I want to send them without copying the data I can put them in a struct

    struct message {
      byte i;
      byte j;
    };
    Wire.write((byte*)&message, 2);

But this would require me to refactor existing code.

Is there any c voodoo that I can perform to send bytes of different places of my code over Wire without copying them in a buffer and without refactoring the code?

body:
```
// Written by Nick Gammon
// May 2012

template <typename T> unsigned int I2C_writeAnything (const T& value)
  {
  Wire.write((byte *) &value, sizeof (value));
  return sizeof (value);
  }  // end of I2C_writeAnything

template <typename T> unsigned int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything
```

Then in the body of your code you can:

```
I2C_writeAnything(message);
```

Similarly your other end can `I2C_readAnything`.

There is a small amount of refactoring required, changing the function call.


body:
No, you cannot.

C does not guarantee any allocation properties of variables. Even if you write one variable definition right after another, both variables can have addresses assigned that have other memory in between.

So, if you want a "packet" sent via `Wire` that contains values of multiple variables, you need to fill a buffer with these values.

Even though C maintains the order of members of a structure, please be aware that depending on the target's architecture there can be gaps between the members for alignment. However, some compilers have language extensions to tackle this issue.


body:
No, this function overwrite of `Wire.write()` is meant for buffers, meaning connected spaces in memory, which can be covered by simply incrementing the buffer. That is not the case for distinct variables.

But that begs the question, why you want to do that in one call to `Wire.write()` in the first place. This function does **not** do any communication on the I2C lines, it just **writes to the libraries internal buffer**. The data gets actually send in `Wire.endTransmission()` or in the onRequest interrupts in the background (depending on where you have those write statements). Thus you already have a buffer and don't need another one. Just call `Wire.write()` multiple times, once for each variable. That will build up the data sequentially inside the internal buffer.


body:
As @chrisl said, there is an internal buffer so the best I can do is just use multiple `Wire.write` calls, but in my case that wasn't working. I got only the last written value or rubbish data.

I dug through the source of the Wire library and found that [the version in github](https://github.com/arduino/ArduinoCore-avr/blob/8b327d7bede1c1245db99daeba4e168c92c11194/libraries/Wire/src/utility/twi.c#L342) (as of this writing) makes it possible to use multiple writes by appending to the buffer:

    // set length and copy data into tx buffer
    for(i = 0; i < length; ++i){
      twi_txBuffer[twi_txBufferLength+i] = data[i];
    }
    twi_txBufferLength += length;

But the one I have installed locally looks like this:

    // set length and copy data into tx buffer
    twi_txBufferLength = length;
    for(i = 0; i < length; ++i){
      twi_txBuffer[i] = data[i];
    }

So that explains a lot.

In case someone else also has this problem, you just need to update.

I was even too lazy to update, so I just replaced the function. Probably not the best decision, but it works!

Thanks!


message:
Cannot communicate with software serial on particular devices (SIM7600G-H)

I have 3 devices:
- An [UNO](https://auseparts.com.au/SainSmart-UNO-ATMEGA328P-PU-ATMEGA8U2-Microcontroller) (non-genuine)

[![UNO][1]][1]

- An [SMS hat/shield device `SIM7600G-H`](https://core-electronics.com.au/sim7600g-h-m2-4g-hat-for-raspberry-pi-lte-cat4-high-speed-4g3g2g-gnss-global-band-1.html) to communicate with via UART

[![SMS Device][2]][2]

- A [USB UART controller](https://core-electronics.com.au/usb-to-ttl-uart-rs232-serial-converter-module-pl2303hx-au-local-shipping.html) for debugging purposes

[![UART USB][3]][3]

---

I'm using the UNO to talk to the SMS device via UART at `9600` baud to send and receive SMS commands. I need the hardware port open to debug, and I am trying to use a software port to talk to the SMS device via it's TX RX pins.

But I cannot get the software port to talk to the SMS device at all.

This is the success I've had trying to talk to and from devices. The bold boxes are needed to be solved for this setup to work. ✅ = working coms, ❌ = nothing on coms at all. Read left to right, **HAT serial (SMS DEVICE)** can communicate with UNO hardware serial.

[![Connection matrix][4]][4]

And I'm using this code to just relay inputs and outputs between the hardware and software ports for testing.

```cpp
// Must be same on mock and serial
const int baud = 9600;

// Communication with mock hat
SoftwareSerial mockPort(2, 3);

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

  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  mockPort.begin(baud);
  Serial.println("Mock port has started @ " + String(baud));
}

void loop()
{

  while (mockPort.available() > 0)
  {
    char inByte = mockPort.read();
    // and send to the hardware serial port:
    Serial.write(inByte);
  }

  // while there is data coming in FROM SERIAL, read it and send it back to mock
  while (Serial.available() > 0)
  {
    char inByte = Serial.read();
    // and send to the mock serial port:
    mockPort.write(inByte);
  }
}
```

Why can't I communicate to the SMS device with the software ports? (or the USB UART as well?) When testing, I can see the UNO's RX light turn on, but I never receive any data back from the SMS device (the serial monitor is just black).

---

Notes:

- I've tried the AltSoftSerial library as well
- I've set the SMS hat's baud rate default to `9600`
- I've tried different communication pins
- I've got the TX pins on RX pins and vice versa

  [1]: https://i.stack.imgur.com/4QNLxs.png
  [2]: https://i.stack.imgur.com/A9I7Fs.png
  [3]: https://i.stack.imgur.com/WIQjYs.png
  [4]: https://i.stack.imgur.com/ojMCll.png

body: The `TX` and `RX` labels mirror the Raspberry Pi. So I swapped the `RX` and `TX` wires to connect as `RX`->`RX` and `TX`->`TX` and now it works


message:
Can an Arduino and an NI USB-6009 DAQ board interfere with each other's signals when they are simultaneously reading signals from different sensors?

Hello dear Arduino SE community.

I have 5 sensors. I read 4 of them with an NI USB-6009 DAQ board and I read the fifth one with an Arduino UNO R3. Though, with the fifth sensor not only I read a signal from it, but I also send a signal to it.

Both the Arduino and the NI board are connected to a computer via two different USB ports and send the signals to the computer simultaneously. Also - simultaneously - the Arduino sends a signal to the fifth sensor.

I noticed a strange behavior with the signal from one of the sensors read by the NI board. It starts with giving me a signal that is clearly wrong and over the course of, approximately, 5 minutes gradually changes to a correct reading.

That hadn't happened when I didn't have Arduino connected to the computer at the same time.

Thus, I'm wondering if it is possible that an Arduino and an NI board can interfere with each other's signals when connected to the computer simultaneously. If it is possible, is it something widespread and is there a working solution?

Thank you in advance.
Ivan

P.S. I deliberately don't provide the specs of my system because the point of my question is not to resolve the issue but to learn if what I described is possible theoretically and if such cases have been encountered.

body:
I have found a solution to my problem.

The sensor that was giving me the wrong signal was plugged to the same electrical circuit with "heavy" equipment (two DC laboratory power supplies). It is well known that one shouldn't do it because "heavy" equipment sends noise back to the circuit which, ultimately, causes noise in the signal generated by the sensor.

Thus, my issue had nothing to do with the Arduino interfering with the USB-6009 through the computer.

To make sure, I disconnected the Arduino from the computer and still got the same wrong signal from the problematic sensor. Then, I plugged the problematic sensor to another electrical circuit, connected the Arduino back to the computer and got the right signal.

Thus, I conclude that one can safely use an Arduino and a USB-6009 with the same computer.


message:
How to increase pinout switching?

Consider this code:

    void loop() {
        digitalWrite(pinTest, HIGH);
        digitalWrite(pinTest, LOW);
    }

On an Arduino Mega 2560, running 16MHz (=0.06us), I would expect the width of the pulse to be somewhere around 0.1us.

However, when measuring with my oscilloscope, I get around 4us high and 5-6 us low. I understand it could take some cycles to run the `digitalWrite` code, but this seems quite a lot.

How is that difference explained?

body:
I fixed it by using assembly code to run the program. Because I am using Linux, I couldn't use Atmel Studio, but you can easily use AVR assembly with `arduino-cli`.

Make your `.ino` like this:

    extern "C" void myAssemblyMain();

    void setup() {
        myAssemblyMain();
    }
    void loop() {
    }

then add a `pulse.S` file with the assembly code:

    #define __SFR_OFFSET 0

    #include "avr/io.h"

    .global myAssemblyMain

    myAssemblyMain:
      sbi   DDRA, 0     ; Set PA0 as output

    blink:
      sbi   PINA, 0     ; Toggle PINB
      jmp   blink

Using this code, I get a ~400ns pulse. Which is more than enough for my needs.


body:
You do not need to go all the way down to assembly in order to get that
speed. You can do direct port access from your `.ino` file:

```c++
void setup() {
    DDRA |= _BV(PA0);  // pin 22 = PA0 as output
    for (;;) {
        PINA |= _BV(PA0);  // toggle PA0
    }
}

void loop(){}
```

This compiles to something that is almost equivalent to your assembly
code. Actually, it is a bit faster, as it uses `rjmp` instead of the
slower `jmp` instruction.

**Edit**: A few notes

1. As pointed out by timemage in a comment, you can save another CPU
   cycle by writing `PINA =` instead of `PINA |=`.

2. This code, as well as your two examples, will exhibit a glitch every
   1,024 µs. This is caused by the periodic timer interrupt used
   by the Arduino core for timekeeping (`millis()`, `micros()` and
   `delay()`). You can avoid the glitch by disabling interrupts before
   going into the tight loop. Alternatively, if you do not use the
   Arduino core at all, you can define a function called `main()`
   instead of `setup()` and `loop()`: this will completely remove the
   Arduino core initialization for your compiled program.

3. `arduino-cli` is useful for sparing you the complexity of the Arduino
   build system (automatic installation of the cores and libraries,
   libraries in multiple places that depend on the core you use...). If
   you do not use the Arduino core, `arduino-cli` is of little use: a
   very simple Makefile that calls `avr-gcc` and `avrdude` is all you
   need for basic AVR development.


message:
Arduino Output Panel Font Color Change

I am using Arduino IDE 2.0.3.  When compiling code if there is an error it shows on a black background with a red font, that is hard for me to read.  Can I change either the background or the font?  Looking within the IDE I don't see how and not seeing anything on the internet.  TIA

body: Thank you dankeboy36 for pointing out "Themes".  Fixed it right up.


message:
How does Arduino handle passing this union?

I'm unsure how this will be handled by the Arduino compiler. If anyone can explain what and why, I'd appreciate it. This is obviously very simplified, but it does contain the actual issue.

At the module level I have this `union`. I understand that this is strictly speaking not correct C++, but it does work for me, at least when used directly and not passed as a argument to a function.

      union _TAT {          // access as bytes or uint32
        uint32_t wide = 0;
        uint8_t bytes[4];
      };

      _TAT oneTAT;        // a variable of _TAT

Suppose I also have a function that works on these:

      void fix_Term(_TAT atat) {
        atat.wide = 0;
        atat.bytes[3] = 17;
      }

...and I invoke it with:

      fix_Term(oneTAT);

As I understand it, passing `AnArray[]` is equivalent to passing `*AnArray`, so the function might/should see `atat.bytes[3]` as a pointer to that byte of the variable. But what about `atat.wide`? I haven't explicitly passed `oneTAT` by reference, so...?

What might actually happen here? It does compile without complaint but I can't test it because the hardware it depends on isn't available yet. Besides, even if it works, I'd like to know why.

And of course, if it's just wrong, how do I best accomplish passing and modifying a variable like this?

body:
Yes passing `AnArray[]` is equivalent to passing `*AnArray`. **But** declaring `uint8_t *anarray1` is _not_ equivalent to declaring `uint8_t anarray2[4]` in a struct/class/union definition. The former includes a pointer to a byte in the struct, the later actually includes 4 bytes in the struct. So in the later case, `anarray2` already points to data, and using `variable.anarray2[0]` correctly gets you the value in the structure, while calling `variable.anarray1[0]` would result in undefined behavior, because the pointer just points anywhere.

So your code is compiling and executing without error, but since you're passing the union by value, the effect of your `fix_term` function is discarded, much like if you had passed in an ordinary value type instead (such as int).


body:
It is confusing in C and C++ that arrays are passed as pointers but an instance of class, struct or union is always passed by value (so as a copy) including the arrays which are part of the memory space of the structure as in the case of your union.

If you want to pass by reference, declare the function's parameter as a reference 'type'. For example `void fix_Term(_TAT& atat) {`.


message:
Multiplexing three VFD tubes — why are the segments and the display timing incorrect?

I'm using an Arduino Nano, a UNL2803 IC, and three 2N3904 transistors to drive three seven-segment vacuum fluorescent display tubes (IV-6) in a multiplex configuration. The UNL2803 is used to drive the segments: when an Arduino pin is pulled low, 25V is sent to the corresponding segment. The 2N3904 transistors are used to drive each of the digits: when the Arduino pin is high, 25V is sent to the digit's grid, thereby activating the digit.

The problem: the tubes aren't showing the correct segments, and the displays aren't being activated with correct timing. I have checked each segment connection to make sure it is connected to the correct segment. By slowing down the time interval between digits, I can see that the second and third digits (the 10s and 1s) are being displayed sequentially with the correct interval, but the first digit (the 100s) comes on with the second digit and stays on for twice the interval time. It also appears that some of the digits are attempting to display more than one number (sequentially) while activated.

The code:

    // Pin assignments for segments
    const int SEG_A = 2;
    const int SEG_B = 3;
    const int SEG_C = 4;
    const int SEG_D = 6;
    const int SEG_E = 5;
    const int SEG_F = 7;
    const int SEG_G = 8;

    // Pin assignments for digits
    const int DIG1 = 9;
    const int DIG2 = 10;
    const int DIG3 = 11;

    int digit = 1;
    int dig_number = 0;
    unsigned int number = 321;

    void setup() {

      Serial.begin(9600);

      // Set segment pins as outputs
      pinMode(SEG_A, OUTPUT);
      pinMode(SEG_B, OUTPUT);
      pinMode(SEG_C, OUTPUT);
      pinMode(SEG_D, OUTPUT);
      pinMode(SEG_E, OUTPUT);
      pinMode(SEG_F, OUTPUT);
      pinMode(SEG_G, OUTPUT);

      // Set digit pins as outputs
      pinMode(DIG1, OUTPUT);
      pinMode(DIG2, OUTPUT);
      pinMode(DIG3, OUTPUT);

      // Turn off digits
      digitalWrite(DIG1, LOW);
      digitalWrite(DIG2, LOW);
      digitalWrite(DIG3, LOW);
    }

    void loop() {
          if (digit == 1) {
            digitalWrite(DIG1, HIGH);
            digitalWrite(DIG2, LOW);
            digitalWrite(DIG3, LOW);
            dig_number = number / 100;
            if (number < 100) {      // to disable the digit if it's not being used
              dig_number == 99;      // triggers 'default' in switch/case
              display_number(dig_number);
            } else {
              display_number(dig_number);
            }
            digit = 2;
            Serial.println("The first digit is: ");
            Serial.print(dig_number);
            delay (250);
          }

          if (digit == 2) {
            digitalWrite(DIG1, LOW);
            digitalWrite(DIG2, HIGH);
            digitalWrite(DIG3, LOW);
            dig_number = (number / 10) % 10;
            if (dig_number == 0 && number < 10) {       // to disable the digit if it's not being used
              dig_number == 99;        // triggers 'default' in switch/case
              display_number(dig_number);
            } else {
              display_number(dig_number);
            }
            digit = 3;
            Serial.println("The second digit is: ");
            Serial.print(dig_number);
            delay (250);
          }

          if (digit == 3) {
            digitalWrite(DIG1, LOW);
            digitalWrite(DIG2, LOW);
            digitalWrite(DIG3, HIGH);
            dig_number = number % 10;
            display_number(dig_number);
            digit = 1;
            Serial.println("The third digit is: ");
            Serial.print(dig_number);
            delay (250);
          }
    }

    void display_number(int dig_number) {

        switch (dig_number) {
            case 0:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, LOW);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, HIGH);
            break;

        case 1:
            digitalWrite(SEG_A, HIGH);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, HIGH);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, HIGH);
            digitalWrite(SEG_G, HIGH);
            break;

        case 2:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, HIGH);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, LOW);
            digitalWrite(SEG_F, HIGH);
            digitalWrite(SEG_G, LOW);
            break;

        case 3:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, HIGH);
            digitalWrite(SEG_G, LOW);
            break;

        case 4:
            digitalWrite(SEG_A, HIGH);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, HIGH);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, LOW);
            break;

        case 5:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, HIGH);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, LOW);
            break;

        case 6:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, HIGH);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, LOW);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, LOW);
            break;

        case 7:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, HIGH);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, HIGH);
            digitalWrite(SEG_G, HIGH);
            break;

        case 8:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, LOW);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, LOW);
            break;

        case 9:
            digitalWrite(SEG_A, LOW);
            digitalWrite(SEG_B, LOW);
            digitalWrite(SEG_C, LOW);
            digitalWrite(SEG_D, LOW);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, LOW);
            digitalWrite(SEG_G, LOW);
            break;

        default:
            digitalWrite(SEG_A, HIGH);
            digitalWrite(SEG_B, HIGH);
            digitalWrite(SEG_C, HIGH);
            digitalWrite(SEG_D, HIGH);
            digitalWrite(SEG_E, HIGH);
            digitalWrite(SEG_F, HIGH);
            digitalWrite(SEG_G, HIGH);
            break;
        }
    }

The circuit diagram:

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

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

I have heard rumor that using delay() instead of millis() for multiplexing can be problematic. Is that what's going on here?

Many thanks in advance for considering this problem!

body:
I made a VFD clock using some really cool old DG10B tubes from an early calculator a year or so ago. I had a heck of a time getting it to work, until I decided try tackling one problem at a time, and then put it all together.

In my clock I used the MAX6921 VFD driver IC, a DS3231 RTC with super cap, and a XIAO for the brains. The VFD driver chip is controlled by pwm/serial (data, load, clock) and the RTC is over I2c.

Instead of trying to multiplex them, I just got them all working at once, I did a nice slow count of all digits being on and displaying the same digits. This helped me detect a couple wiring faults, and helped me figure out which segments needed to be lit for each number I wanted displayed. (the digits on my tubes are quite unique!)

[![tube pinout][1]][1]
[![DG10b tubes][2]][2]

once I had my "fonts" figured out and a case for each digit, I created a simple loop that counted through 0-9 on all digits with all four of them on. 4444, 5555, etc

Then I started trying to get just one digit lit at a time.  (this helped me find another wiring issue)
// [pihgfedcba------1234}; //this is what the data stream looks like when sent to the driver
// ...where the first 10 digits are the segments, and the last 4 are the grids for each digit from left to right 1-4.
// The rest are currently unused and should be padded with zero's or 1's)

Next I made a loop that would check the time, and print out the digits. I DO use delay() in my code, in order to deliberately flicker my tubes (for the antique steampunk effect)
But here's the thing, I believe my code checks the time for each individual digit.
the loop says for each digits 1-4 (check time, display digit)

there was a lot more involved, and it's been a while since I worked on it so I am not sure I am being helpful here.  I just wanted to suggest you follow a good troubleshooting process. (smaller problems are easier to solve)

[![my vfd clock][3]][3]

  [1]: https://i.stack.imgur.com/ILazO.jpg
  [2]: https://i.stack.imgur.com/k3La5.jpg
  [3]: https://i.stack.imgur.com/WntvY.jpg


body:
Your code appears to invert the switching pattern of the digits. Instead of switching the  selected digit on and the other two off, you are doing the opposite.

The grid of a VFD tube has to have a voltage applied to it to illuminate the selected segments. Those segments are also selected by having a voltage applied. The circuit you have shown, by default, powers both the grids and the segments via 10k resistors connected to the 25 volt power rail. The transistors, also in the uln2803, when switched on, pull the grids and segments to ground, thus switching those elements off. This arrangement reduces the complexity of the circuit by eliminating the need for high side switching but "wastes" power.

A simple code correction should solve the problem:

```
// Turn off digits
   digitalWrite(DIG1, HIGH);  // high turns the grid off.
   digitalWrite(DIG2, HIGH);
   digitalWrite(DIG3, HIGH);
 }
```

```
if (digit == 1) {
   digitalWrite(DIG1, LOW);  // digit one ON
   digitalWrite(DIG2, HIGH); // digit two OFF
   digitalWrite(DIG3, HIGH); // digit three OFF
}
```
Do the equivalent for digits 2 and 3.

Use resistors (say 1k) in series with the transistor bases to limit the current and protect the arduino pins. See https://learn.sparkfun.com/tutorials/transistors/applications-i-switches

You still have to confirm if the wire connecting R9, R10 and R11 goes to all the way to the +25 volt rail. This is not clear from the schematic.


body:
For future searchers, I finally got this circuit going using two ULN2803 transistor arrays, instead of discrete transistors for the digit connections. Here's the final schematic:

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

You can check out more about the final project [here][2]. Many thanks to those who commented——your feedback was very helpful!

  [1]: https://i.stack.imgur.com/F2YWv.png
  [2]: https://www.hackster.io/tmburns/driving-vfd-tubes-with-an-arduino-nano-14f71e


message:
Can an ethernet shield function as an adapter?

I want to communicate with my Arduino over a long distance so I decided to use an Ethernet cable between my computer and Arduino. Searching up a few tutorials I've found them all mentioning IP addresses and establishing a network.

Simply put my question is can an Ethernet shield make the Arduino function basically the same as with a direct USB connection into its port(with Serial and all) without having to establish a network/other things. If so, is it as simple as saying something like "Ethernet.begin()" and then continuing?

Thank you, and please note that I (clearly) do not have much TCP/IP experience (but am more than willing to learn).

body:
No, you cannot do that. Ethernet is _very_ different from a serial link.
You will have to deal with IP addresses, port numbers, the notions of
client and server, and so on. Note that, once you manage to establish a
TCP connection through Ethernet, _that connection_ does behave pretty
much like a (somewhat virtualized) serial link. But you have to
establish the connection first. So you will have to study a bit, read
documentations, etc.

Alternatively, if you only need a short-distance link (say, a couple of
km), you can try RS-485 instead of Ethernet. RS-485 is a physical layer
commonly used to transmit regular serial data. From the software point
of view, it is pretty much a regular serial link, save for the fact that
you usually cannot speak and listen at the same time (you could, with
more expensive cabling).


message:
Using multiple ultrasonic sensors simultanously with the same trigger

I want to use three ultrasonic sensors together and would prefer to use as few pins as possible, so I was thinking of using one trigger for all 3 sensors. The sensors will have an angle of 90 degrees between them. I was wondering if this would still cause false readings? Since they are a large angle (and some distance) apart?

body:
I was looking into this a while back using HC-SR04 sensors and did have some issues with bad (well, strange) readings. but I was just fiddling around with it and haven't gone back to it.

That being said, if you connect the triggers together, but the echo lines individually, and put at least 60ms delay between triggering and reading each sensor, then it might work for your application.

This thread briefly touches on how the time it takes for a ping to decay is part of the issue.
https://forum.arduino.cc/t/multiple-ultrasonic-sensors-close-together/410358

My understanding of it suggests that if you send out a ping in multiple directions, the ping going right echoes off a surface, then echoes off a surface on the left side, which returns to the sensor on the other side, so the sensor might receive a lot of noise.

The datasheet on the HC-SR04 indicates that the cycle time of a single measurement should be 60ms, so a trigger signal doesn't align with an echo...
https://forum.arduino.cc/uploads/short-url/961oW5W0LoHZ6t5XOP40HryBlZK.pdf

In any case, these sensors are cheap and I find that throwing a few bits on a proto board and testing experimenting with them is the best way to learn.

Start with two sensors opposing each other with a surface at 2 inches in front of one, and at 4 inches from the other. trigger them together, see if you can get a clean read from either one. Experiment with different distances to objects (like within an inch on each side, etc). Then repeat the process with a third at the front, and with surface objects at odd angles.

I hope this is helpful, if not encouraging at least :)


message:
Arudino receiving interrupt command BEFORE entering sleep mode causing it not to receive any interrupt commands in order to wake up

I've written code for an Arduino Nano that when a button is pressed, it sends an IR command. It is set so that if no button press has been received for a period of 10 seconds, it will enter sleep mode until a button press is received. The button to send the IR command is the same button being used to send the wake up interrupt (button connected to pin D2). When testing the code the Arduino is able to go to sleep and wake up from the interrupt 1-3 times before it will suddenly receive an interrupt signal just before entering sleep mode. When this happens it gets stuck in sleep mode and will no longer accept the wake up interrupt. I am currently using Serial Monitor outputs and the built-in LED to determine when the Arduino is in sleep mode or not.

```
#include <IRLib.h>
#include <avr/sleep.h>
#define interruptPin 2

IRsend My_Sender;

const int button = 2;
int buttonState = 0;
int timeSinceCommand = 0;
const unsigned long eventInterval = 1000;
unsigned long previousTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);         //delete once code finalized and working
  pinMode(interruptPin, INPUT_PULLUP);
  digitalWrite(LED_BUILTIN, HIGH);      //delete once code finalized and working
  Serial.println("---------------------------New Run---------------------------");
}

void loop() {
  while (timeSinceCommand < 10) {
    unsigned long currentTime = millis();
    buttonState = digitalRead(button);
    if (buttonState == HIGH) {
      My_Sender.send(SONY, 0xC90, 12);
      timeSinceCommand = 0;
      previousTime = currentTime;
    }
    if (currentTime - previousTime >= eventInterval) {
      timeSinceCommand++;
      previousTime = currentTime;
    }
  }
  if (timeSinceCommand >= 10) {
    Going_To_Sleep();
    timeSinceCommand = 0;
  }
}

void Going_To_Sleep() {
  sleep_enable();
  attachInterrupt(0, wakeUp, RISING);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  digitalWrite(LED_BUILTIN, LOW);             //delete once code finalized and working
  Serial.println("Arudino going to sleep!");  //delete once code finalized and working
  delay(1000);                                //delete once code finalized and working
  sleep_cpu();
  Serial.println("Arudino has waken up!");    //delete once code finalized and working
  digitalWrite(LED_BUILTIN, HIGH);            //delete once code finalized and working
}

void wakeUp() {
  Serial.println("Interrupt received!");      //delete once code finalized and working
  sleep_disable();
  detachInterrupt(0);
}
```
Here is the Serial Monitor output from a couple of tests:
```
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!
---------------------------New Run---------------------------
Arudino going to sleep!
Interrupt received!
Arudino has waken up!
Interrupt received!
Arudino going to sleep!
```

body:
There are a couple of tricky things going on here... First, you should
be aware of a few facts:

1. Buttons are prone to mechanical bounce. You press a button once, and
   quite often the microcontroller senses multiple transitions on the
   input pin.

2. When INT0 is configured to sense rising edges, any rising edge on the
   pin will set the INTF0 interrupt flag, _whether the interrupt is
   enabled or not_. Once the flag is set, it will fire an interrupt
   request as soon as the interrupt is enabled.

3. When the CPU receives an interrupt request, it finishes executing the
   current instruction before servicing the request.

With that in mind, here is an explanation of what goes on:

When you wake up the Arduino with the push button, it often triggers
multiple signal transitions. The first rising edge wakes up the Arduino
and triggers the interrupt. The second rising edge only sets the INTF0
interrupt flag: the interrupt is “on hold”, because interrupts are not
themselves interruptible. However, before exiting, `wakeUp()` disables
servicing that interrupt, which means the flags just stays set. It is a
pending interrupt of sorts.

Some time later, `Going_To_Sleep()` is called again. `attachInterrupt()`
enables the interrupt and, since the flag is still set, the (pending)
interrupt fires immediately. That's when you see the message “Interrupt
received!” printed right before the Arduino goes to sleep. The problem
is that the interrupt is disabled by `wakeUp()`. One second later,
`sleep_cpu()` puts the CPU to sleep, and now our wake-up source is
disabled, so the Arduino is just locked into its dreams.

There is still one issue with this scenario. The interrupt handler
supposedly disabled sleeping, so how come the Arduino went to sleep
anyway? The answer is that sleeping was accidentally re-enabled by
`set_sleep_mode()` because of a data-race. Here is a disassembly of
`set_sleep_mode()`:

```lisp
in   r24, 0x33 ; read SMCR (Sleep Mode Control Register) into r24
andi r24, 0xF1 ; clear the Sleep Mode Select bits
ori  r24, 0x04 ; select the Power Down mode
out  0x33, r24 ; write back SMCR
```

The first instruction in this sequence comes right after the instruction
in `attachInterrupt()` that enables the INT0 interrupt. When that
instruction generates an interrupt request (because the interrupt flag
was already set), the interrupt request reaches the CPU while it is
already executing the `in` instruction above, and this instruction is
completed before servicing the interrupt request. This means that we
have now in register r24 a copy of the Sleep Mode Control Register from
before the interrupt is serviced. In this copy, the SE bit (Sleep
Enable) is set. Even though `wakeUp()` clears that bit in the actual
SMCR register, it stays set in our copy in r24. Then, the `out`
instruction re-enables sleeping. I experimented putting a single `nop`
instruction right before `set_sleep_mode()` and that was enough to
prevent the data race.

So here you have an explanation of the observed behavior. I may come
up with some suggestions for fixing the problem, but it need
to take some sleep before that (do not worry, I will make double sure I
have one interrupt source enabled before executing `sleep`).


body:
I'm taking this opportunity to include a simple basic sleep sketch which eliminates the possible race condition risk that Edgar Bonet identified in the standard approach to using the sleep mode for AVR class MCUs. See the reference in the sketch to further optimise, if required, to switch off the ADC, Brown out detection etc.

```
/*
   Sleep mode demonstration (Uno/Nano ATmega328P)
   based on https://www.gammon.com.au/power Sketch J
   but stripped down for demonstration purposes to exclude some optimisation (BOD and ADC etc.)
   See also: https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

   Connect a button switch between pin 2 and ground
   Press the button. It wakes, blinks the led and then sleeps.

*/

#include <avr/sleep.h>

const byte LED = 13;  // built in led

void wake()
{
  // nothing here. All done in the loop
}

void setup()
{
  Serial.begin( 115200 ) ;
  pinMode( LED, OUTPUT );
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt ( digitalPinToInterrupt(2), wake, FALLING);
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
}

void loop()
{
  Serial.println( "waking . . . ") ;

  // your own code could go here instead

  for ( int i = 0; i < 4; i++ ) {
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    delay (50);
  }
  delay(3000) ;

  Serial.println( "Sleeping. . . " ) ;
  Serial.flush() ;
  delay(20) ; // allow message to be written

  sleep_mode();
  // *** we wake here ***
}
```


message:
Why are ATTiny so expensive compared to ESP modules compared to features they offer?

I was looking for a cheap MCU solution for a project, apart from being compact, ATTiny doesn't seem to provide much value. I was hoping it is cheaper but nope, They are mostly above 1.5 USD in any shop. Whereas I can easily get an ESP module for a comparable price if not cheaper, added WiFi, and optionally Bluetooth, and they are not too huge for my use cases. Am I missing something?

body:
You can get ATTINYs for much less than $1.50.

For example, right now you can order the ATTINY202 from stock in single unit quantiles from Microchip for $0.48 each. They drop to $0.35 each at 5K units (also in stock).

https://www.microchipdirect.com/product/search/all/ATTINY202

If you are really price sensitive then you can sometimes get the smaller ATTINYs for even less when buying in reels at a time, but you have to shop around.

Anytime you pick a part you have to trade-off purchase price, availability (both now and in the future), and suitability. The AVR parts can often be the best choice- but all depends on what you are using it for!


message:
ESP8266 - error after board update to 3.1.1

I'm using a Ubuntu 22.04 and Arduino IDE 1.8.19 for my ESP8266 Projects.

Yesterday I upgraded to 3.1.1 (using board library manager), and right after that - I got the following message (few seconds after compilation start):

    Traceback (most recent call last):
      File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 846, in <module>
        sys.exit(main())
      File "/home/guy/snap/arduino/85/.arduino15/packages/esp8266/hardware/esp8266/3.1.1/tools/mkbuildoptglobals.py", line 759, in main
        if time.time_ns() < os.stat(commonhfile_fqfn).st_mtime_ns:
    AttributeError: module 'time' has no attribute 'time_ns'
    exit status 1
    Error compiling for board LOLIN(WEMOS) D1 R2 & mini.

Steps done to find the reason:
1. Empty Sketch - occurs.
2. Any other ESP8266 board - occurs.
3. Going back to prior version, 3.1.0 - occurs.
4. Going back to 3.0.2 - OK!
5. Checking 3.1.1 on Mac, same IDE version - OK!

Any ideas why ?
Am I the only one ?

Guy

body:
The error tells you, that the time.time_ns() python function does not exist. This function was added to the python time lib with Python3 version 3.7.

The most likely scenario I can imagin here is, that a python 3.6 or lower version is installed on your ubuntu and therefore the board software does not find the required function.

Depending on how the ARDUINO IDE is configured, the globally installed python or a special installation of python is used. We dicussed these two possibilities in the chat and realized that in your case, snap installs its own dependency of python. I assume that the version of this python was below 3.7 and therefore the plugin was unable to find the required time function.

If the Arduino IDe would have been depent on the global python installation, it would have been enough to install a newer python (e.g. 3.10+) globally.

In you case (dependency defined by snap), the only solution I have, is to install the IDE not with snap but with the manual installation or by using apt. There are instruction in the internet like https://www.computingpost.com/how-to-install-arduino-ide-on-ubuntu-22-04-lts/.

Please check the comment of @userfuser (about usíng an .AppImage file) in the dicussion below the question also.


message:
Direct port manipulation takes 300 nanoseconds to execute for some reason

I have this code
```
#include <Arduino.h>

void setup() {

  DDRD  = B00001000;

}
void delayNanoSeconds(int time){
    int ans = (float)time / 62.5;
    for(int i = 0; i < ans; i++){
        _NOP();

    }

}
#define delay250 _NOP(); _NOP();_NOP(); _NOP();
#define delay1000 delay250 delay250 delay250 delay250
void loop() {
  while(1){
       PORTD ^= B00001000;
       delay1000; delay1000;
  }

  }
 ```
but I am getting delay of 2300 us
here is a picture of the logic analyzer [![enter image description here][1]][1]
and when I change delay to 250 or 1000 I am still getting this extra 300ns so why

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

body:
Remember: every single thing the CPU does takes time. Here is a
disassembly of your `loop()`:

```lisp
    ldi  r25, 0b00001000 ; r25 = B00001000
1:  in   r24, PORTD      ; r24 = PORTD
    eor  r24, r25        ; r24 ^= r25
    out  PORTD, r24      ; PORTD = r24
    nop
    nop
    ...
    nop
    rjmp 1b              ; goto previous label 1
```

As you see, besides your series of `nop`, there are four instructions in
the loop:

 * `in`, `eor` and `out` take one cycle each
 * `rjmp` takes two cycles.

That is a total overhead of 5 CPU cycles, or 312.5 ns when
running at 16 MHz. Pretty close to what you are seeing.

If you want an exact timings, you will have to disassemble your code and
count the overhead cycles, as I did here. Then, I suggest this simpler
approach:

```cpp
#define OVERHEAD_CYCLES 5

void loop() {
    for (;;) {
        PORTD ^= _BV(PD3);
        _delay_us(2 - OVERHEAD_CYCLES / (F_CPU / 1e6));
    }
}
```


message:
How do I properly use an ISR inside a class definition?

I want to write a class for a model bike.

For controlling the steering I use a DC motor with two encoders.
To get the steering angle `stAng` of the bike, I attach a interrupt to the pin `ST_ENC_A` where one of the encoders is connected to. This interrupt is attached when the bike is initialized with the function `bike.begin()`. When the interrupt is triggerd, the increment-steering-angle-function `incStAng` is triggerd.
Said function is member of the class `Bike`. To make the whole code compile and upload I had to make the increment-steering-angle-function `static void incStAng()` and the steering-angle-variable `volatile static float stAng` static.

The code is running, there are no errors or warnings.

Now, when I provide pin `ST_ENC_A` with 3.3V the interrupt should be triggerd and I should see the printed value of `stAng` increse in the Serial Monitor. This is not the case. It stays at 0.00.

This is my first real class I am writing. I only want to create one instance of my bike so the static definition of `stAng` and `incStAng` should be no problem.

So far I found the following websites helpful for information on '[static][1]' and [ISR][2].

I would be glad if someone could help me and give me a hint why the steering angle is not increasing when I give said pin 3.3V!

Board: Arduino Nano RP2040 Connect

Below you will see the .ino, .h, .cpp files in this order.

```
// myBike.ino - main file

#include "Bike.h"

Bike bike;

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

void loop() {
  float val = bike.getStAng();
  Serial.println(val);
}
```

```
// Bike.h - header file for the Bike library

#ifndef Bike_h
#define Bike_h

#include "Arduino.h"

class Bike {
  public:
    Bike();
    void begin();
    float getStAng();
  private:
    volatile static float stAng;
    static void incStAng();
};

#endif
```

```
// Bike.cpp - implementation file for the Bike library

#include "Bike.h"

#define ST_ENC_A      12
#define ST_ENC_B      11

#define DEG_PER_CNT   0.51428571428

Bike::Bike() {
  pinMode(ST_ENC_A, INPUT);
  pinMode(ST_ENC_B, INPUT);
}

void Bike::begin() {
  attachInterrupt(digitalPinToInterrupt(ST_ENC_A),incStAng,RISING);
}

void Bike::incStAng() {
  volatile float stAng;
  int b = digitalRead(ST_ENC_B);
  if(b==HIGH){
    stAng = stAng - DEG_PER_CNT;
  }else{
    stAng = stAng - DEG_PER_CNT;
  }
}

float Bike::getStAng() {
  volatile float stAng;
  return stAng;
}

```

  [1]: https://stackoverflow.com/questions/31305717/member-function-with-static-linkage
  [2]: https://forum.arduino.cc/t/using-a-class-member-for-isr-is-it-possible/380127

body:
You have _three_ different variables named `stAng` here:

 * a static member of the `Bike` class, which has been declared but not
   defined, and is never used
 * a local variable of the `Bike::incStAng()` method
 * a local variable of the `Bike::getStAng()` method

There should be only one such variable. For this, you should define the
first one: in Bike.cpp

```c++
volatile float Bike::stAng;
```

and get rid of the other two.

Side note: I would recommend avoiding floating point computations within
an ISR, as these can be quite slow. Instead, count the _integer_ number
of encoder steps in the ISR, and convert to an angle within
`Bike::getStAng()`.


message:
Passing function as argument, with capture, what type to declare in function?

This probably has a simple resolution, but can't find the right combination.

I'm trying to setup a function (`setupScreen`) to take as an argument a function to do the actual setup:

```c++
void ScreenHelpers::setupScreen(void (*setupFunc)(ThinkInk_290_Tricolor_Z10*)){
 ScreenHelpers::waitTilCanRefreshScreen();

 (* setupFunc)(&display_two);

 lastUpdateTime = millis();
}
//...
void ScreenHelpers::displayErrorMessage(const String message){
 const char* text = message.c_str();
 ScreenHelpers::setupScreen([text](ThinkInk_290_Tricolor_Z10* screen) {
  screen->clearBuffer();
   ScreenHelpers::simpleDisplayText(
    screen,
    text,
    EPD_RED
   );
  });
}
```

This works, until I added the `[text]` to capture the `text` variable in the lambda, where it resulted in:

```
ScreenHelpers.cpp: In static member function 'static void ScreenHelpers::displayErrorMessage(String)':
ScreenHelpers.cpp:45:4: error: no matching function for call to 'ScreenHelpers::setupScreen(ScreenHelpers::displayErrorMessage(String)::<lambda(ThinkInk_290_Tricolor_Z10*)>)'
   });
    ^
ScreenHelpers.cpp:21:6: note: candidate: 'static void ScreenHelpers::setupScreen(void (*)(ThinkInk_290_Tricolor_Z10*))'
 void ScreenHelpers::setupScreen(void (*setupFunc)(ThinkInk_290_Tricolor_Z10*)){
      ^~~~~~~~~~~~~
```

What should my function declaration look like to accept this?

body:
`ScreenHelpers::setupScreen()` expects its argument to be a plain
function. A capturing lambda is not a plain function: it is rather a
functor, i.e. an object that is callable like a function.

The standard way of passing such a lambda in C++ is to declare the
parameter to be of type [`std::function`][cppref]:

```c++
#include <functional>

void ScreenHelpers::setupScreen(std::function<void(ThinkInk_290_Tricolor_Z10*)> setupFunc) {
    ...
}
```

This may or may not work depending on the Arduino board you are using.
AVR-based boards rely on a C library that only minimally supports C++.
You cannot use `<functional>` on those boards. If you are using one of
those boards, your options are:

1. Try to find an implementation of of the C++ STL for AVR-based boards.
   I have seen at least one floating around in the Net.

2. Use the standard C idiom for defining a callback with a `void*`
   parameter:

```c++
void ScreenHelpers::setupScreen(
      void (*setupFunc)(ThinkInk_290_Tricolor_Z10*, void*),
      void *callback_data) {
   setupFunc(&display_two, callback_data);
   //...
}

// elsewhere:
ScreenHelpers::setupScreen([](ThinkInk_290_Tricolor_Z10 *screen, void *data) {
   const char *text = (const char *) data;
   // ...
}, (void *) text);
```

[cppref]: https://en.cppreference.com/w/cpp/utility/functional/function


message:
Carbon dioxide sensor MG 811

I am using MG811 carbon dioxide sensor with ESP8266 module. CO2 values is being read inside closed room. The value comes around 400 ppm. Using CO2 generator does not make increase in reading. Checked with pSense RH co2 Temp handheld meter. It shows around 750-800 ppm. But ESP8266 still shows around 420 ppm on oled display.

    #include "CO2Sensor.h"
    CO2Sensor co2Sensor(A0, 0.99, 100);

    void setup() {
    Serial.begin(9600);
    Serial.println("=== Initialized ===");
    co2Sensor.calibrate();
    }

    void loop() {
    int val = co2Sensor.read();
    Serial.print("CO2 value: ");
    Serial.println(val);
    delay(1000);
    }
What is the meaning of (A0, 0.99, 100) in second line of code. Is any calibration needs to be done for correct value ?

body:
Your code appears to come from an example in the library you are using https://github.com/solvek/CO2Sensor/blob/master/examples/ReadCO2/ReadCO2.ino

To answer your questions:

***What is the meaning of (A0, 0.99, 100) in second line of code.***
Inspection of the library source code shows:
CO2Sensor::CO2Sensor(int analogPin, float inertia, int tries)

Of course, if you don't understand how the library is using the variables inertia and tries, this alone will make no sense to you.

***Is any calibration needs to be done for correct value ?***

In my opinion, the answer is YES. Furthermore, I think that calibration is necessary but not sufficient to appropriately use the sensor to the extent that you can have a good idea about what a "correct value" means.

I like that you get the fundamental idea of testing, or validating, a sensor. I like the idea that you are using another monitor (assuming it is a good one) as a "standard" and I like that you use a CO2 generator - assuming you are doing that safely.

What is lacking, again, in my opinion, is any understanding of how the sensor works. It is not that I am an expert on this particular sensor, but even a brief look at what passes as a data sheet https://sandboxelectronics.com/files/SEN-000007/MG811.pdf and the text of the library usage https://github.com/solvek/CO2Sensor and a few other sources that are freely available; makes it clear to me that you need to dig into this much more before you will have success understanding and appropriately using this sensor.

It is complicated. I hope that my response is not off putting and instead points you in the right direction.


message:
Can I power Lilygo TTGo T-display from 5v and still use USB for communication?

I have a project which needs a 7-9V power source.  I use a battery, and plan to use a small regulator to supply 5V to a Lilygo TTGO T-Display V1.1 (1.14 inch display) via the 5V and GND pins.

I need to connect the Lilygo to USB from time-to-time to upload data.  *Will there be any conflict between the USB power and the 5V supply ?*

I have peered for a long time at the schematic, and I see that there are MOSFETs doing some kind of protection, but I do not understand it well enough to be sure.
**Schematic**: [here][1]

 1. Q5 appears to disconnect the battery (VBAT) from +5V when the USB is
    connected.
 2. Q4 also seems to disconnect the battery (BAT) from +5V when the USB
    is connected.  *What is the difference between VBAT and BAT ?*
 3. VBUS (the USB power) is connected to +5V via a Zener diode.  This
    appears to allow the USB to supply 5V, but prevent current flowing
    back to the PC.  I think there could be an issue with high current
    through the Zener if my 5V regulator gave a voltage that was lower
    than the USB.

  [1]: https://raw.githubusercontent.com/Xinyuan-LilyGO/TTGO-T-Display/master/schematic/ESP32-TFT(6-26).pdf

body:
What are you trying to achieve? For how long is the board supposed to function? The simplest solution in this case is to simply get a 4.2V battery for the LilyGO board itself, most likely not just in terms of effort, but economically.

From your edits, I (now) assume you want to use the 5V pin on the board? I don't think that'll work the way you'd want it to, as it doesn't seem that it was intended for that (if it was, the VIN pin would've been brought out).

 1. > Q5 appears to disconnect the battery (VBAT) from +5V when the USB is connected.

Yeah, that makes sense to me as well.

 2. > Q4 also seems to disconnect the battery (BAT) from +5V when the USB is connected. What is the difference between VBAT and BAT ?

Yes, looking at the datasheet for the battery charger and the schematic for the LilyGO board, VBAT is the batteries voltage, while the BAT terminal is the one coming out of the charger and the one that usually supplies the current to both charge the battery and to possibly drive the system load.

 3. > VBUS (the USB power) is connected to +5V via a Zener diode. This appears to allow the USB to supply 5V, but prevent current flowing back to the PC. I think there could be an issue with high current through the Zener if my 5V regulator gave a voltage that was lower than the USB.

Yeah, it prevents the current going back into the USB port if you have the battery connected. You need a pretty substantial voltage to overcome that Schottky* barrier.

One issue you'll probably encounter is that if you connect a 5V source to that pin, the system will think it's powered on by a battery and you can damage the BAT terminal. If you have more than 1 of those boards and you're willing to experiment, you could try cutting the trace to BAT terminal altogether and connecting the 5V source and seeing if that works.

Another issue is that for safety reasons, it'd be prudent to switch that source off when you're connecting the USB; you'd also want to protect that 5V source from being damaged by the VUSB once it's on. There are probably ways you could keep the 5V on if you desolder the USBC connector and try to manually attach a probe to the datalines and ground the two together, but dealing with USBC is not easy and you're rapidly venturing into territory where it's just easier to get a different board and the screen separately or just use a LiPo battery to power the board in the first place (you could probably find a way to use multiple LiPo packs if you need your application to last longer as well).

Note: I didn't spend too much time looking at the schematic and it is a bit confusing, so a possible good exercise would be to simulate those two circuits in a SPICE program. And again, these types of questions are covered more-so by the EE SE. If you'd have posted it there, I'm sure you'd get more (and most likely, better) answers.


message:
Arduino Timer Drift Issue

I have two Arduinos that communicate over serial. Each arduino runs a TDMA algorithm where each arduino is assigned one timeslot. The arduinos should transmit during their timeslot, which does work fine. However, over time, say 10-15 minutes the arduinos start to overlap their timeslots. To keep time I am using the millis() function to determine when to send a message. I have tried both delay() and manually setting up counters but getting the same drifting behavior. On one of the iterations of the code I had a Serial.readStringUntil() function that was being called during every timeslot and the arduinos stayed in sync for over 13 hours with no detected drift, with an exact timeslot of 1000ms. I now am aware that the delay I was seeing is caused by the timeout parameter, which defaults to 1000ms, in the readStringUntil function, but it does not make sense that there would be no drift when the arduino was delayed in this way. I know that the stability of the ceramic resonator on each arduino would cause drift.

Why would delay(), millis(), and manually configuring timer1 cause drift, but the timeout functionality of the readStringUntil function seemingly does not drift?

Also, is there a better way to setup the timing functionality, the goal is to have the nodes go as long as possible without needing a resync?

The following psuedo is how the timing is currently setup.

```
count = 0;

if(millis() - previous_action >= TIME_SLOT) {
   count++;
   if(correct timeslot) {
       TRANSMIT();
   }
   previous_action = millis();
   loop_back_to_check;
}
```

EDIT:
RTC and other devices that can keep the devices sync'd are not in the scope of the project.

body: You can use one of the many RTC (Real Time Clock) modules, they are crystal controlled where your Arduino is not. There are several varieties, pick the one you like. There is a large difference in stability between the Arduino timing and the RTC timing. You can update the clocks on a regular basis. Using NTP (Network Time Protocol) which would be very accurate and reliable. You can do the NTP on a regular basis on one unit and have it update the others. Side benefit they will not drift much as the temperature changes.


body:
Any fee-running clock will drift. Worse yet: its drift rate will not be
constant. This is a fact of life, and there is nothing you can do about
it. There is no software solution, although your software can certainly
make things _worse_. What you can do is:

1. Synchronize the clocks of both Arduinos to an external time source.
   The time source doesn't have be accurate if you only care about the
   relative drift between the Arduinos. This could be the receiver of
   the messages sending an acknowledgement at a specific time, or the
   same receiver sending a pulse on a dedicated line, or an NTP server
   if your Arduinos are networked, or a radio-broadcast time signal, or
   a GPS receiver...

2. Use clocks that are so good that their drift becomes irrelevant. The
   drift rate has to be less than the timing tolerance of your TDMA
   protocol divided by the expected service life of your devices. A good
   RTC can give you a drift rate less than about 2 ppm (i.e.
   2×10<sup>−6</sup>). If that is not good enough, you may consider an
   OCXO (oven-controlled crystal oscillator) or an atomic clock (the
   rubidium-based ones are the most affordable).

3. Calibrate your clocks. As the variations of the drift rate are
   typically much less than the average drift rate, you can remove most
   of the drift by first measuring it and then removing in software the
   value you measured. You are then left with the random variations of
   the drift rate (“frequency wander”). I suggest you read [Arduino
   clock frequency accuracy][joris] to get an idea of the kind of
   accuracy you can expect.

4. Use temperature control: keep you clocks at constant temperature, as
   temperature variations are often the main cause of frequency wander.
   Alternatively, use temperature compensation: measure the drift rate
   at multiple temperatures, fit a continuous curve through these
   measurements and use this curve (and continuous temperature
   measurements) to correct the drift in software.

5. Avoid making things worse with your software: update
   `previous_action` with
   ```c++
   previous_action += TIME_SLOT;
   ```
   rather than assigning `millis()` to it, as this approach is
   _guaranteed_ to cause drift.

> Why [...] the timeout functionality of the readStringUntil function
> seemingly does not drift?

Nobody can answer this question without a careful examination of both
the specific version of the software you used and the physical setup. It
could be that you accidentally implemented a synchronization mechanism.
It could be that your measurements were not accurate enough to reveal
the drift.

[joris]: http://jorisvr.nl/article/arduino-frequency


body:
According to my experience, they are the clients that should follow the server's timing.
On the client side:
1. On each server transmission, calculate the ETA (Estimated Time of Arrival and ATA (Actual Time of Arrival) of the message, based on your time slot scheduling and adjust your local clock accordingly.
2. It would be nice to treat all transmissions as timing messages, no matter the destination, just ignore the payload.
3. It is obvious that the client should be a little overhead timed, in case the server's clock is a little faster.
4. For long inactive periods, the server should broadcast a periodic timing message, so that the error will be kept to a minimum.
5. It would be convenient to add a "timing preamble" in each transmission.

With all that in mind, the readStringUntil function is your friend in many ways. By waiting for the timing preamble, you can determine easily the timing error. By waiting for a known postamble, you read "late" messages (don't forget the timeout value!).

Use a bi-numbering scheme for each transmission, one for each client's message and one for each broadcast (total transmissions). Calculate the minimum convenient modulo (overflow) values. Each client will know if there's something missing. (usually, a too-early transmission or a collision)

Although it is communications-medium agile, I would recommend a preamble like:
```
$FF $00 $FF $00 AA BB CC DD EE $FF $FF FF with PAYLOAD following, where:

AA = 1 byte, the destination addr, $00 = Broadcast

BB = 1 byte, message type (optional, $00 for timing msg)

CC = 1..2 bytes, msg no. to this dest.

DD = 1..2 (3?) bytes, total msg no., no matter the dest.

EE = 1 byte, payload length, if variable. (EE<$FF, $00 for timing msg)

FF = 1 byte checksum (optional). (Why should you place it AFTER the "$FF
$FF" combination?)
```
Use the time you receive the "$FF $FF" combination as a time-mark to calculate ATA & ETA. (It is common sense to treat your values so that this combination cannot show before the end of the preamble)

Consider using a postamble, with redundant info & End-Of-Message mark.


message:
DS3231 with Arduino Nano for Timing precision

I am in need to synchronize two separate circuit boards working with Arduino nano. The need is to activate one relay using Arduino-1 after 45 min and another relay using Arduino-2 after 45.36 seconds. The time starts from the point of reception of input from an external switch common to both.

with ref to [This question][1] and from the advice of [edgar-bonet][2] I have used one temperature-compensated RTC for timing the Arduino s externally **(DS3231)**. I am using its 32kHz pin from the chip for counting the ticks and in the Arduino using the interrupt to count the ticks.

The program is shown below.

```

float _sec = 1;

float secTime =  _sec * 1000UL; // second->millis
uint32_t coilTime = 5 * 1000UL; // second->millis

volatile uint32_t count = 0;
/*
 * 32768 ticks in 1 sec
 * 0.032768 tick in 1 us
 */

float _multiplier = 0.032768; // 32768 Hz

uint32_t _delay = secTime * _multiplier * 1000UL ;

volatile bool onFlag = false;

ISR(INT1_vect, ISR_NOBLOCK) {
  count = count + 1UL;
  if (_delay == count) {
    PORTC |= (1 << 5);
    onFlag = true;
    EIMSK = 0;
  }
}

ISR(INT0_vect) {
  /* INTERRUPT re-initalization */
  EIMSK = 0;
  EICRA = B00001100; // INT0 - clear ; INT1 -  set
  EIFR  = 0;
  PORTB ^=  (1 << 0) | (1 << 1); // setting Green off and red on
  count = 0;
  EIMSK = B00000010; // INT0 - inactive ; INT1 - active
}

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

  /* PIN initialization */
  DDRB |= (1 << 0) | (1 << 1); // red led and green led

  pinMode(3, INPUT_PULLUP); // timer unit
  pinMode(2, INPUT); // interrupt unit

  DDRC |= (1 << 3) | (1 << 4) | (1 << 5); // relay, OUT_1, OUT_2

  /* LEDs state update */
  PORTB &=  ~(1 << 1); // red off.
  PORTB |= (1 << 0); // green on.

  PORTC &= ~(1 << 3); // A3-off

  /* INTERRUPT initalization */
  EICRA = B00000011; // INT0 - set ; INT1 - not set
  EIMSK = B00000001; // INT0 - active ; INT1 - inactive
  EIFR  = 0;
}

void loop() {

  if (onFlag) {

    PORTB |= (1 << 0); // setting green on

    delay(500);
    PORTC ^= (1 << 5);
    //    PORTB ^= (1 << 0) | (1 << 1);
    PORTB ^= (1 << 1); // setting red off
    while (true) {
      TCCR2B = 0;
      count = 0;
      PORTB ^= (1 << 0);
      delay(500);
    }
  }
}
```

when running the program The result I am expecting the accuracy of microseconds
but

for
input -> Measured value
1 sec -> 1.000387792
2 sec -> 2.000784208
50 sec -> 50.020926833
250 sec -> 250.104557792

How to make the clock more precise, In the datasheet it is said that the clock is accurate to +- 2ppm.

[datasheet-ds3231][3]

  [1]: https://arduino.stackexchange.com/questions/91915/arduino-nano-timing-precision
  [2]: https://arduino.stackexchange.com/users/7508/edgar-bonet
  [3]: https://www.analog.com/media/en/technical-documentation/data-sheets/DS3231.pdf

body:
This may not be a proper answer to your question. Instead of telling you
how to improve the accuracy, I will show you how to measure it. The
issue is that the code you posted is doing too much stuff, and it is not
clear how it could be measuring the clock accuracy. So, instead I
suggest you try the code below:

 * connect a push button between pin 2 and GND
 * connect the 32768 Hz signal to pin 5
 * watch the built-in LED blink

```c++
const uint8_t input_pin = 5;  // 32768 Hz on digital 5 = T1
const uint8_t clear_pin = 2;  // button to clear timer

void setup() {
    pinMode(input_pin, INPUT_PULLUP);
    pinMode(clear_pin, INPUT_PULLUP);
    pinMode(LED_BUILTIN, OUTPUT);

    // Configure Timer 1 as a counter.
    TCCR1A = 0;
    TCCR1B = _BV(CS11) | _BV(CS12);  // count falling edges of T1
}

void loop() {
    // Display bit 14 of the counter on the builtin LED.
    if (TCNT1 & (1 << 14)) {
        digitalWrite(LED_BUILTIN, HIGH);
    } else {
        digitalWrite(LED_BUILTIN, LOW);
    }

    // Clear the counter on button press.
    if (digitalRead(clear_pin) == LOW) {
        TCNT1 = 0;
    }
}
```

What this sketch does is use Timer/counter 1 as a counter in order to
count the falling edges of the 32768 Hz signal. Bit 14 of the counter
should then toggle at 1 Hz. This bit is output on the built-in LED to
let you check its frequency. You can use the push button to reset the
phase of the blinks.

If you have a very accurate clock at hand, you can use the push button
to synchronize the blinks with the ticks of that clock, and then see how
long it takes to get visibly out of phase. You can also synchronise the
blinks of two Arduinos and see for how long they stay in sync. If you
have a scope, you could measure a tiny offset between the edges of the
two Arduino's LEDs, then see how this offset evolves with time.


message:
Is ESP8266 dropping an interrupt?

I want to use interrupts on my ESP 8266 to monitor the digital outputs of a power meter and water meter.

The idea is to increment a counter in the ISRs and at some point to take the value of the counter and to set the counter back to 0 in the loop() function.
I've red about critical sections, noInterrupts() and interrupts() and then I started to wonder if an ISR will be executed while the code is between noInterrupts() and interrupts(). On theory it should be because the interrupt flag in the chip will be raised and the ISR will be invoked after the code exits the critical section. I wrote a program to test it, but my findings prove the opposite.

```
#include <Arduino.h>

#define REPORT_TIME 5000
#define INTERRUPT_PIN D1

unsigned long base_time;

volatile unsigned int interrupt_counter = 0;

void IRAM_ATTR isr() {
  interrupt_counter++;
}

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

  // The interrupt will be FALLING EDGE
  pinMode(INTERRUPT_PIN, INPUT_PULLUP);
  pinMode(LED_BUILTIN_AUX, OUTPUT);
  digitalWrite(LED_BUILTIN_AUX, HIGH);
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isr, FALLING);

  base_time = millis();
}

bool written = false;

void loop() {

  if (!written)
  {
    written = true;
    for (int i = 0; i < 100; i++)
    {
      digitalWrite(LED_BUILTIN_AUX, LOW);
      digitalWrite(LED_BUILTIN_AUX, HIGH);
    }
  }

  unsigned long time_now = millis();
  if (time_now - base_time >= REPORT_TIME)
  {

    written = false;

    base_time = time_now;

    unsigned int interrupt_counter_local;

    //Guard the critical section
    noInterrupts();
    interrupt_counter_local = interrupt_counter;
    interrupts();

    digitalWrite(LED_BUILTIN_AUX, LOW);
    digitalWrite(LED_BUILTIN_AUX, HIGH);

    Serial.print("counter ");
    Serial.println(interrupt_counter_local);
    Serial.println();
  }
}
```
Using a wire I attached the pin of the builtin led to the interrupt pin and in the serial monitor I could see the values are:
```
counter 100
counter 201
counter 302
```
When I modify the critical section to be like:
```
noInterrupts();
interrupt_counter_local = interrupt_counter;
digitalWrite(LED_BUILTIN_AUX, LOW);
digitalWrite(LED_BUILTIN_AUX, HIGH);
interrupts();
```
I expect the same output as above but the values are:
```
counter 100
counter 200
counter 300
```

Am I missing something or the interrupts doesn't work as I expect?

body:
After some additional experiments I found that moving
```
digitalWrite(LED_BUILTIN_AUX, HIGH);
```
utside the critical section gives me the expected result, so I'm not blocked anymore and **more importantly the chip will not drop an interrupt**.
If someone knows why it doesn't work with my initial version I will be happy to hear the answer.


message:
UDPSendReceiveString example using Arduino Due with ENC28J60 Ethernet Module

I was trying to learn how to use UDP protocol to use in my automation project to send commands to an Arduino Due on ethernet with an ENC28J60 breakout board which I have connected to the Due from SPI pins. I had to use another library called EthernetENC.h to use this module with the Due.
Arduino Code:

```
#include <EthernetENC.h>
#include <EthernetUdp.h>

#define UDP_TX_PACKET_MAX_SIZE 256

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xA0, 0x36, 0xBC, 0x30, 0xC1, 0x16
};
IPAddress ip(192, 168, 137, 205);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";        // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  // You can use Ethernet.init(pin) to configure the CS pin
Ethernet.init(10);  // Most Arduino shields
  //Ethernet.init(5);   // MKR ETH Shield
  //Ethernet.init(0);   // Teensy 2.0
  //Ethernet.init(20);  // Teensy++ 2.0
  //Ethernet.init(15);  // ESP8266 with Adafruit FeatherWing Ethernet
  //Ethernet.init(33);  // ESP32 with Adafruit FeatherWing Ethernet

  // start the Ethernet
  Ethernet.begin(mac, ip);

  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }

  // start UDP
  Udp.begin(localPort);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBuffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}
```
Processing 3 Code:
```
 import hypermedia.net.*;

 UDP udp;  // define the UDP object

 void setup() {
 udp = new UDP( this, 6000 );  // create a new datagram connection on port 6000
 //udp.log( true );     // <-- printout the connection activity
 udp.listen( true );           // and wait for incoming message
 }

 void draw()
 {
 }

 void keyPressed() {
 String ip       = "192, 168, 137, 205";  // the remote IP address
 int port        = 8888;    // the destination port

 udp.send("Hello World", ip, port );   // the message to send

 }

 void receive( byte[] data ) {       // <-- default handler
 //void receive( byte[] data, String ip, int port ) {  // <-- extended handler

 for(int i=0; i < data.length; i++)
 print(char(data[i]));
 println();
 }
```
And this is my test setup:
[![enter image description here][1]][1]

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

After I upload the code to the Due the LinkOFF command immediately triggers and Serial.print() prints that "Ethernet cable is not connected." but this is indeed incorrect since this setup worked in other ethernet examples. But other than this message there is nothing on the Serial monitor. On the processing side, the story is even more depressing because simply nothing happens. There is just a small window opening and no matter where a click or press any key on my keyboard no string is being sent or received. I seriously don't know what to do I don't have much experience with UDP and I am trying to learn but the only responsive example in the Arduino library isn't working.

Edit:
I have connected the ENC28J60 directly to my laptop ethernet port and I chose the IP from there which was IPv4 Adress = 192.168.137.1
I also remove the linkOFF() from the original example since it was just using serial monitor for no good.

body:
from https://github.com/JAndrassy/EthernetENC/wiki/Examples

> If the `Ethernet.linkStatus()` is invoked too soon, it may return `LinkOFF`. You can do the check in setup() this way:

```
  if (Ethernet.linkStatus() == LinkOFF) {
    delay(500);
    if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
  }
```


message:
Arduino Nano R3 & Deek-Robot datalogging shield

Whilst I am much more at home programming PIC ISR's in assembler, I am building a data logger using a DS1307 to interrupt every second to write data to a USB SD card.

There does not appear to be a connection or even a pad from the DS1307 SQW for interrupts and feel I must be missing something, as this would be a remarkable designer/manufacturer oversight?

body:
I can't find any official source for information about "Deek-Robot datalogging shield" but what I do find indicates it is the same or similar design as an [Adafruit Datalogging shield][1]. The DS1307 (or other RTC) square wave out signal is routed to a through-hole on the interior of the board indicated in this image:

[![SQ pin indicated][2]][2]

It does not appear to be routed anywhere else an any of these boards. Note: the picture here is of a board (Current Adafruit logging shield apparently) that uses an NXP RTC that has the same pinout as the DS1307, but uses a different register layout. But in any case places the SQ output on a header in the same basic location. So you would need to solder a header to accept a jumper. Or solder a wire from there to one of the through holes for a digital pin, probably pin 2 or 3 if you're on an UNO (you have tagged) since those are the pins compatible with `attachInterrupt()`

  [1]: https://learn.adafruit.com/adafruit-data-logger-shield/
  [2]: https://i.stack.imgur.com/qRqkO.jpg