body:
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!

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

Answers: 3

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


body:
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).

title: Can an ethernet shield function as an adapter?

Answers: 1

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).


body: 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?

title: Using multiple ultrasonic sensors simultanously with the same trigger

Answers: 1

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 :)


body:
I am trying to use an edited version of waterproof depth sensor code from the Arduino blog. It works well on my Arduino Uno board; however, it doesn't work with my ESP8266 board. Is there a way to adjust it? I understand that the problem is with Arduino clock module and time interrupts. On the other hand, I can't know where to find their counterparts in the ESP libraries.
Code is here:

    #include <SPI.h>
    const int clock = 4;
    float initial = 0;
    void resetsensor()
    {
      SPI.setDataMode(SPI_MODE0);
      SPI.transfer(0x15);
      SPI.transfer(0x55);
      SPI.transfer(0x40);
    }
    float read_pressure(){
      TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
      analogWrite (clock, 128) ;
      resetsensor();
      unsigned int result1 = 0;
      unsigned int inbyte1 = 0;
      SPI.transfer(0x1D);
      SPI.transfer(0x50);
      SPI.setDataMode(SPI_MODE1);
      result1 = SPI.transfer(0x00);
      result1 = result1 << 8;
      inbyte1 = SPI.transfer(0x00);
      result1 = result1 | inbyte1;
      resetsensor();
      unsigned int result2 = 0;
      byte inbyte2 = 0;
      SPI.transfer(0x1D);
      SPI.transfer(0x60);
      SPI.setDataMode(SPI_MODE1);
      result2 = SPI.transfer(0x00);
      result2 = result2 <<8;
      inbyte2 = SPI.transfer(0x00);
      result2 = result2 | inbyte2;
      resetsensor();
      unsigned int result3 = 0;
      byte inbyte3 = 0;
      SPI.transfer(0x1D);
      SPI.transfer(0x90);
      SPI.setDataMode(SPI_MODE1);
      result3 = SPI.transfer(0x00);
      result3 = result3 <<8;
      inbyte3 = SPI.transfer(0x00);
      result3 = result3 | inbyte3;
      resetsensor();
      unsigned int result4 = 0;
      byte inbyte4 = 0;
      SPI.transfer(0x1D);
      SPI.transfer(0xA0);
      SPI.setDataMode(SPI_MODE1);
      result4 = SPI.transfer(0x00);
      result4 = result4 <<8;
      inbyte4 = SPI.transfer(0x00);
      result4 = result4 | inbyte4;
      long c1 = (result1 >> 1) & 0x7FFF;
      long c2 = ((result3 & 0x003F) << 6) | (result4 & 0x003F);
      long c3 = (result4 >> 6) & 0x03FF;
      long c4 = (result3 >> 6) & 0x03FF;
      long c5 = ((result1 & 0x0001) << 10) | ((result2 >> 6) & 0x03FF);
      long c6 = result2 & 0x003F;
      resetsensor();
      unsigned int presMSB = 0; //first byte of value
      unsigned int presLSB = 0; //last byte of value
      unsigned int D1 = 0;
      SPI.transfer(0x0F); //send first byte of command to get pressure value
      SPI.transfer(0x40); //send second byte of command to get pressure value
      delay(35); //wait for conversion end
      SPI.setDataMode(SPI_MODE1); //change mode in order to listen
      presMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
      presMSB = presMSB << 8; //shift first byte
      presLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
      D1 = presMSB | presLSB; //combine first and second byte of value
      resetsensor(); //resets the sensor
      unsigned int tempMSB = 0; //first byte of value
      unsigned int tempLSB = 0; //last byte of value
      unsigned int D2 = 0;
      SPI.transfer(0x0F); //send first byte of command to get temperature value
      SPI.transfer(0x20); //send second byte of command to get temperature value
      delay(35); //wait for conversion end
      SPI.setDataMode(SPI_MODE1); //change mode in order to listen
      tempMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
      tempMSB = tempMSB << 8; //shift first byte
      tempLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
      D2 = tempMSB | tempLSB; //combine first and second byte of value
      const long UT1 = (c5 << 3) + 20224;
      const long dT = D2 - UT1;
      const long TEMP = 200 + ((dT * (c6 + 50)) >> 10);
      const long OFF  = (c2 * 4) + (((c4 - 512) * dT) >> 12);
      const long SENS = c1 + ((c3 * dT) >> 10) + 24576;
      const long X = (SENS * (D1 - 7168) >> 14) - OFF;
      long PCOMP = ((X * 10) >> 5) + 2500;
      float TEMPREAL = TEMP/10;
      float PCOMPHG = PCOMP * 750.06 / 10000; // mbar*10 -> mmHg === ((mbar/10)/1000)*750/06
      long T2 = 0;
      float P2 = 0;
      if (TEMP < 200)
        {
          T2 = (11 * (c6 + 24) * (200 - TEMP) * (200 - TEMP) ) >> 20;
          P2 = (3 * T2 * (PCOMP - 3500) ) >> 14;
        }
      else if (TEMP > 450)
        {
          T2 = (3 * (c6 + 24) * (450 - TEMP) * (450 - TEMP) ) >> 20;
          P2 = (T2 * (PCOMP - 10000) ) >> 13;
        }
      if ((TEMP < 200) || (TEMP > 450))
      {
        const float TEMP2 = TEMP - T2;
        const float PCOMP2 = PCOMP - P2;
        float TEMPREAL2 = TEMP2/10;
        float PCOMPHG2 = PCOMP2 * 750.06 / 10000; // mbar*10 -> mmHg === ((mbar/10)/1000)*750/06
        return PCOMPHG2;
      }
    }
    void initialialize()
    {
      Serial.print("Setting initial");
      for (int i = 0; i < 10; i++)
      {
        initial += read_pressure();
        Serial.print(".");
        delay(1000);
      }
      initial /= 10;
      Serial.println();
      Serial.print("initialial Pressure: ");
      Serial.println(initial);
    }
    void setup() {
      Serial.begin(9600);
      SPI.begin();
      SPI.setBitOrder(MSBFIRST);
      SPI.setClockDivider(SPI_CLOCK_DIV32);
      pinMode(clock, OUTPUT);
      delay(100);
      initialialize();
      delay(5000);
    }
    void loop()
    {
      float reading = (read_pressure() - initial) * 1.3595474315191;
      Serial.print("Water is: ");
      Serial.print(reading);
      Serial.println("cm");
      delay(500);
    }

I get errors with both the *clock variable* and *TCCR1B*.

title: Problem with Time Interrupts in ESP8266 with water proof depth sensor

Answers: 0


body:
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!
```

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

Answers: 2

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 ***
}
```


body:
I am new to this and I have purchased the Lilygo T-Wristband to prototype a watch that will vibrate upon receiving a 1-bit bluetooth signal from an android app. The goal is to allow the user to set the intensity of vibration (hence i am using the Real Time Playback, RTP, mode) that varies from 0-255. My device seems to not be working whenever i have the Wire1 code and I really am stuck at this point trying to make the motor work. I have attached the code below

    #include <pcf8563.h>
    #include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
    #include <SPI.h>
    #include <Time.h>
    #include <Wire.h>
    #include <WiFi.h>
    #include "sensor.h"
    #include "esp_adc_cal.h"
    #include "avas.h.c"
    #include "charge.h"
    #include "BluetoothSerial.h"
    #include <Adafruit_DRV2605.h>
    // init Class:
    BluetoothSerial ESP_BT;
    Adafruit_DRV2605 drv;

    #define TP_PIN_PIN          33
    #define I2C_SDA_PIN         21
    #define I2C_SCL_PIN         22
    #define RTC_INT_PIN         34
    #define BATT_ADC_PIN        35
    #define VBUS_PIN            36
    #define TP_PWR_PIN          25
    #define LED_PIN             4
    #define CHARGE_PIN          32
    #define DRV_SDA             15
    #define DRV_SCL             13

    TFT_eSPI tft = TFT_eSPI();  // Invoke library, pins defined in User_Setup.h
    PCF8563_Class rtc;

    char buff[256];
    bool rtcIrq = false;
    bool initial = 1;
    bool otaStart = false;
    RTC_DATA_ATTR int boots = 0;

    uint8_t func_select = 0;
    uint8_t omm = 99;
    uint8_t xcolon = 0;
    uint32_t targetTime = 0;       // for next 1 second timeout
    uint32_t colour = 0;
    int vref = 1100;

    bool pressed = false;
    uint32_t pressedTime = 0;
    bool charge_indication = false;
    uint8_t hh, mm, ss ;

    void setupWire() {
      tft.init();
        tft.setRotation(1);
        tft.setSwapBytes(true);
        tft.pushImage(0, 0,  160, 80, avas);
        delay(2000);
      Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
      Wire.setClock(400000);
    }
    void setupPins() {
      pinMode(TP_PIN_PIN, INPUT);
      pinMode(TP_PWR_PIN, PULLUP);
      //! Must be set to pull-up output mode in order to wake up in deep sleep mode
      digitalWrite(TP_PWR_PIN, HIGH);
      pinMode(LED_PIN, OUTPUT);
      pinMode(CHARGE_PIN, INPUT_PULLUP);
      attachInterrupt(CHARGE_PIN, [] {
          charge_indication = true;
      }, CHANGE);
      if (digitalRead(CHARGE_PIN) == LOW) {
          charge_indication = true;
      }

    }
    void setupTFT() { //set-up fonts
      tft.init();
      tft.setRotation(1);
      tft.setSwapBytes(true);
      tft.fillScreen(TFT_WHITE);
      tft.setTextColor(TFT_YELLOW, TFT_WHITE); // Note: the new fonts do not draw the background color
    }
    void setupVolt() { //set-up battery monitoring
        esp_adc_cal_characteristics_t adc_chars;
        esp_adc_cal_value_t val_type = esp_adc_cal_characterize((adc_unit_t)ADC_UNIT_1, (adc_atten_t)ADC1_CHANNEL_6, (adc_bits_width_t)ADC_WIDTH_BIT_12, 1100, &adc_chars);
        //Check type of calibration value used to characterize ADC
        if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
    //        Serial.printf("eFuse Vref:%u mV", adc_chars.vref);
            vref = adc_chars.vref;
        } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
    //        Serial.printf("Two Point --> coeff_a:%umV coeff_b:%umV\n", adc_chars.coeff_a, adc_chars.coeff_b);
        } else {
    //        Serial.println("Default Vref: 1100mV");
        }
    }
    void setupRTC() { //set-up RTC for time
        rtc.begin(Wire);
        //Check if the RTC clock matches, if not, use compile time
        rtc.check();
        RTC_Date datetime = rtc.getDateTime();
        hh = datetime.hour;
        mm = datetime.minute;
        ss = datetime.second;
    }
    void setupDRV(){

       Wire1.begin(DRV_SDA, DRV_SCL);
        Wire1.beginTransmission(DRV2605_ADDR);
        if (Wire1.endTransmission() != 0) {
            tft.setTextColor(TFT_RED, TFT_WHITE);
            tft.fillScreen(TFT_WHITE);
            tft.setCursor(0, 0);
            tft.println("Failed to connect DRV2605");
            delay(5000);
            esp_restart();
        }
        drv.begin(&Wire1);
        drv.setMode(DRV2605_MODE_REALTIME);

    }
    void setup(void) {
      // WiFi.mode(WIFI_OFF);

      Serial.begin(9600);
      setCpuFrequencyMhz(80);         // scaling it back saves so much of the precious battery life
      btStop();
      ESP_BT.begin("AVAS");
      setupDRV();
      setupWire();
      setupTFT();
      setupRTC();
      setupVolt();
      while (ESP_BT.available() == false)
            {
              tft.setTextColor(TFT_BLUE, TFT_WHITE);
              tft.fillScreen(TFT_WHITE);
              tft.setCursor(0, 0);
              tft.println("Bluetooth not connected");
              delay(3000);
            }

      while (ESP_BT.available() == true){
              tft.setTextColor(TFT_RED, TFT_WHITE);
              tft.fillScreen(TFT_WHITE);
              tft.setCursor(0, 0);
              tft.println("Bluetooth connected");
              delay(5000);
              break;
      }

      if(boots == 0) //Run this only the first time
      {
        targetTime = millis() + 1000 ;  //adds 1 min to compiler time
        boots ++;
      }
      setupPins();
    }
    String Volt() {
        uint16_t v = analogRead(BATT_ADC_PIN);
        float battery_voltage = ((float)v / 4095.0) * 2.0 * 3.3 * (vref / 1000.0);
        return String(battery_voltage) + "V";
    }
    void RTC() {

        if (targetTime < millis()) {
            RTC_Date datetime = rtc.getDateTime();
            hh = 11;
            mm = datetime.minute;
            ss = datetime.second;
            // Serial.printf("hh:%d mm:%d ss:%d\n", hh, mm, ss);
            targetTime = millis() + 1000;
            if (ss == 0 || initial) {
                initial = 0;
                tft.setTextColor(TFT_GREEN, TFT_WHITE);
                tft.setCursor (8, 60);
                tft.print(__DATE__); // This uses the standard ADAFruit small font
            }
            tft.setTextColor(TFT_BLUE, TFT_WHITE);
            tft.drawCentreString(Volt(), 120, 60, 1); // Next size up font 2
            // Update digital time
            uint8_t xpos = 6;
            uint8_t ypos = 0;
            if (omm != mm) { // Only redraw every minute to minimise flicker
                // Uncomment ONE of the next 2 lines, using the ghost image demonstrates text overlay as time is drawn over it
                tft.setTextColor(0x39C4, TFT_WHITE);  // Leave a 7 segment ghost image, comment out next line!
                //tft.setTextColor(TFT_BLACK, TFT_BLACK); // Set font colour to black to wipe image
                // Font 7 is to show a pseudo 7 segment display.
                // Font 7 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : .
                tft.drawString("88:88", xpos, ypos, 7); // Overwrite the text to clear it
                tft.setTextColor(0xFBE0, TFT_WHITE); // Orange
                omm = mm;

                if (hh < 10) xpos += tft.drawChar('0', xpos, ypos, 7);
                xpos += tft.drawNumber(hh, xpos, ypos, 7);
                xcolon = xpos;
                xpos += tft.drawChar(':', xpos, ypos, 7);
                if (mm < 10) xpos += tft.drawChar('0', xpos, ypos, 7);
                tft.drawNumber(mm, xpos, ypos, 7);
            }

            if (ss % 2) { // Flash the colon
                tft.setTextColor(0x39C4, TFT_WHITE);
                xpos += tft.drawChar(':', xcolon, ypos, 7);
                tft.setTextColor(0xFBE0, TFT_WHITE);
            } else {
                tft.drawChar(':', xcolon, ypos, 7);
            }
        }
    }

    void loop() {
      if (charge_indication) {
          charge_indication = false;
          if (digitalRead(CHARGE_PIN) == LOW) {
              tft.pushImage(140, 55, 16, 16, charge);
          } else {
              tft.fillRect(140, 55, 16, 16, TFT_WHITE);
          }
      }
      if (digitalRead(TP_PIN_PIN) == HIGH) {
          if (!pressed) {
              initial = 1;
              targetTime = millis() + 1000;
              tft.fillScreen(TFT_WHITE);
              omm = 99;
              func_select = func_select + 1 > 2 ? 0 : func_select + 1;
              pressed = true;
              pressedTime = millis();
          } else {
              if (millis() - pressedTime > 3000) {
                  esp_restart();
              }
          }
      } else {
          pressed = false;
      }
            RTC();
       if (ESP_BT.available())
            {
              byte pwm = ESP_BT.read(); //Read what we receive
              // drv.setRealtimeValue(pwm);
              // drv.go();
              tft.setTextColor(TFT_RED, TFT_WHITE);
              tft.fillScreen(TFT_WHITE);
               tft.setCursor(0, 0);
              tft.println(pwm);
            }
      }

title: Lilygo T-Wristband code not working (DRV2605 Motor version)

Answers: 0


body:
I am currently working on an SPI interface to measure the voltage of an amplified sensor bridge signal. I am using an ESP32 module to control the device. Since I am logging the data to an SD card, I chose to connect the ADS8698  ([Datasheet](https://www.ti.com/lit/ds/symlink/ads8698.pdf?ts=1674215434741&ref_url=https%3A%2F%2Fwww.ti.com%2Fproduct%2FADS8698)) via the default HSPI interface (see below). Unfortunately I am receiving zero readings only - no matter what commands I send. I tried to illustrate my setup as detailled as possible down below - if you think that I am missing something, do not hesitate to remind me ;).

My Question is: Do you have any ideas on things that I missed facing this issue? - Thanks in advance!

**Related Topics**\
I know that there are related topics in [Source A](https://www.mikrocontroller.net/topic/398157), [Source B](https://e2e.ti.com/support/data-converters-group/data-converters/f/data-converters-forum/596887/ads8698-exemple-code) and [Source C](https://arduino.stackexchange.com/questions/30137/talking-to-ads8698-18-bit-adc-over-spi), from which however none does lead to a final answer. My research in the last couple of days showed, that several people face issues with this ADC, which lead me to start a new thread to reactive this topic and collect all referenced ressources without creating a duplicate.

**Research** \
One possible reason for the communication problem could be, that I am not using DMA to interface via SPI which might lead to timing problems. I wasn't able to test any ESP32 spi dma library, since the only library I found (https://github.com/hideakitai/ESP32DMASPI) does not compile. Furthermore I found discussions, whether DMA is actually more precise with respect to timing or not, which did not lead to a verified result (the multi-core structure of the ESP32 might even be faster).

**Hardware Setup & Wiring**

![ADS8689 Schematic](https://i.stack.imgur.com/ovvTs.png)

The ADS8698 circuit is shown above, it is connected to the ESP32 as follows:
| ESP32DevKitCV4 | ADS8698IDBT|
| -------- | -------------- |
| 12 (HSPI_MISO)   | SDO|
| 13 (HSPI_MOSI)   | SDI|
| 14 (HSPI_SCK)   | SCK |
| 15 (HSPI_CS)   | CS |

**Current Software State**
```
#include <Arduino.h>
#include <SPI.h>

//ADC Settings
#define CHANNEL 0
#define SCLK_SPEED 18e6
#define BUFFER_SIZE 5
#define CS_PIN 15
#define RST_PIN 32
#define SPI_MODE SPI_MODE0

//objects
SPIClass * hspi = NULL;
uint8_t receivedBytes[3];

void setup() {
  Serial.begin(115200);                 //initialize serial communication

  pinMode(CS_PIN, OUTPUT);              //set pinmode
  pinMode(RST_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);           //no communication
  digitalWrite(RST_PIN, HIGH);          //normal operation

  hspi = new SPIClass(HSPI);
  hspi->begin();
  hspi->beginTransaction(SPISettings(SCLK_SPEED,MSBFIRST, SPI_MODE));

  digitalWrite(CS_PIN,LOW);
  hspi->transfer(0xC0);                 //manual read Ch0
  hspi->transfer(0x00);
  Serial.println(hspi->transfer(0x00));
  digitalWrite(CS_PIN,HIGH);
}

void loop() {
  digitalWrite(CS_PIN,LOW);
  hspi->transfer(0);                    // wait 16 clk cycles for conversion, 0x00 = continue Operation
  hspi->transfer(0);
  receivedBytes[0] = hspi->transfer(0); //read 3 bytes
  receivedBytes[1] = hspi->transfer(0);
  receivedBytes[2] = hspi->transfer(0);
  digitalWrite(CS_PIN,HIGH);

  for(int i=0;i<3;i++)
  {
    Serial.print(receivedBytes[i],BIN);
    Serial.print(":");
  }
  Serial.println();
  delay(1000);
}```

title: ESP32DevkitC-V4 interfacing ADS8698 (18 bit ADC)

Answers: 0


body:
Background
==========
I am using an ESP32 that receives sACN/DMX512 universes from a controller and am outputting those control signals to a strip of WS2812B pixels using Adafruit's library for WS2812B and [ForkEye's E131 library](https://github.com/forkineye/ESPAsyncE131) for sACN.

Current Implementation
------------
 Currently, my code is statically assigned to UNIVERSE, starting at channel 1 and outputting to it's assigned Digital IO output 3x DMX512 channels per pixel (R, G, and B) until it gets to NUM_PIXELS. This functions as expected, but I would like it to be more configurable.

```
if (!e131.isEmpty()) {
    e131_packet_t packet;
    e131.pull(&packet);     // Pull packet from ring buffer

    if (htons(packet.universe) == UNIVERSE) {
        for (int i = 0; i < NUM_PIXELS; i++) {
            int j = i * 3 + 1;
            pixels.setPixelColor(i, packet.property_values[j], packet.property_values[j+1], packet.property_values[j+2]);
        }
        pixels.show();
    }
}
```
Goal
====
Multiple universes can come in over e131_packet_t packet. I would like to assign multiple (more than likely just 4) sequential universes to one output, continuing at the pixel number that the previous left off at. For example, UNIVERSE_1 would output 170 pixels. UNIVERSE_2 would output another 170 pixels, however picking up on pixel number 171 for the library function pixels.setPixelColor, so the whole function would iterate 340 times/pixels through.

Question
========
What do you suggest for a clean way to iterate through these options with minimal code duplication? I plan on using a static 4x universes and 4x pixel outputs.

I could hack something together with a lot of variables that would function, but I'm hoping there's a more elegant and robust suggestion from more experienced developers.

title: How can I control the assignment of DMX512 universes to WS2812B physical outputs sequentially

Answers: 0


body: 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?

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

Answers: 1

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!


body:
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

title: ESP8266 - error after board update to 3.1.1

Answers: 1

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.


body:
I'm trying to use AD7746 with an arduino board to continuously measure capacitance (I'm currently using a 2pF capacitor for testing).
Datasheet [here][1].

I managed to correctly write and read the registers of the chip, but I always get get back "11111111 11111111 11111111" when I try to read the capacitance (this happens for both channels). I tried also various settings of CAPDACA (/CAPDACB) but I always read "full scale".
There are no other components around the chip aside a 100pF and a 10uF capacitors between Vcc and ground and all the traces are very short (probably around 15mm max).
Is there something wrong I'm not seeing?

    void setup()
    {
      Wire.begin(); // sets up i2c for operation
      Serial.begin(9600); // set up baud rate for serial
      //reset the device
      Wire.beginTransmission(I2C_ADDRESS); // start i2c cycle
      Wire.write(RESET_ADDRESS); // reset the device
      Wire.endTransmission(); // ends i2c cycle
      //wait for reboot
      delay(1);
    }

    void loop()
    {
      // print out the status if data is received
      if (Serial.available() > 0) {
        // read the incoming byte:
        Serial.read();
        displayStatus(); //print the register values on the serial port
      }

      valueA = readValueA();
      Serial.print("channel A: ");
      Serial.print(valueA);
      Serial.print(" temperature: ");
      Serial.println(temperature);
      delay(1000);
    }

    long readValueA() { //channel A with EXC A
      writeRegister(REGISTER_CAP_SETUP,_BV(7)); //enables capacitive channel for single conversion, continuous conversion, or calibration - only channel A
      writeRegister(REGISTER_EXC_SETUP, _BV(6) | _BV(3) | _BV(1) | _BV(0)); // only EXC A (not EXC B) and full range 0 - VDD - excitation always on
      writeRegister(REGISTER_CONFIGURATION, _BV(7) | _BV(6) | _BV(5) | _BV(4) | _BV(3) | _BV(0)); //continuous conversion - slow

      writeRegister(REGISTER_VT_SETUP, _BV(7) | _BV(0));
      writeRegister(REGISTER_CAP_DAC_A, _BV(7) | _BV(6) | _BV(5) | _BV(4) | _BV(3) | _BV(2) | _BV(1) | _BV(0));

      long ret = 0;
      uint8_t data[3];
      char status = 0;
      //wait until a conversion is done
      while (!(status & (_BV(0) | _BV(2)))) {
        //wait for the next conversion
        status= readRegister(REGISTER_STATUS);
      }
      value =  readLong(REGISTER_CAP_DATA);
      value >>=8;
      //we have read one byte too much, now we have to get rid of it
      ret =  value;
      temperature = readLong(REGISTER_VT_DATA);
      temperature >>=8;
      return ret;
    }

    unsigned long readLong(unsigned char r) {
      union {
        char data[4];
        unsigned long value;
      }
      byteMappedLong;
      byteMappedLong.value = 0L;
      Wire.beginTransmission(I2C_ADDRESS); // begin read cycle
      Wire.write(0); //pointer to first data register
      Wire.endTransmission(); // end cycle
      //the data pointer is reset anyway - so read from 0 on
      Wire.requestFrom(I2C_ADDRESS,r+4); // reads 2 bytes plus all bytes before the register
        while (!Wire.available()==r+4) {
          ; //wait
        }
      for (int i=r+3; i>=0; i--) {
        uint8_t c = Wire.read();
        if (i<4) {
          byteMappedLong.data[i]= c;
        }
      }
      return byteMappedLong.value;
    }

This is what I obtain on the serial port (in this case I had CAPDACA set as 11111111, but with 10000000 it's the same):

    AD7746 Registers:
    Status (0x0): 100
    Cap Data (0x1-0x3): 11111111.11111111.11111111
    VT Data (0x4-0x6): 10000000.11110111.1000001
    Cap Setup (0x7): 10000000
    VT Setup (0x8): 10000001
    EXC Setup (0x9): 1001011
    Configuration (0xa): 11111001
    Cap Dac A (0xb): 11111111
    Cap Dac B (0xc): 0
    Cap Offset (0xd-0xe): 10000000.0
    Cap Gain (0xf-0x10): 1100110.1111010
    Volt Gain (0x11-0x12): 1011100.0

  [1]: https://www.analog.com/media/en/technical-documentation/data-sheets/AD7745_7746.pdf

title: Capacitance from AD7746 always "saturated"

Answers: 0


body:
What is the exact meaning of the Initial Power-Up Section of the MAX7219 data sheet to be found on Page 7?

It says:

> On initial power-up, all control registers are reset, the display is blanked, and the MAX7219/MAX7221 enter shutdown mode. Program the display driver prior to display use. Otherwise, it will initially be set to scan one digit, it will not decode data in the data registers, and the intensity register will be set to its minimum value.

Most of this is clear. But specifically, what does the "the display is blanked" mean? Does it mean that the MAX7219 internal SRAM is cleared as part of the power-up sequence or does it mean that because the display is set to shutdown mode by power-up the display will be blank.

I have sought widely and cannot find a definitive statement. Which of these interpretations is correct, or perhaps is there another interpretation?

Why does it matter? Idle curiosity really. My read of the datasheet was that the RAM was cleared and hence did not expect to have to manually clear it.

So I didn't, and was wondering where the flash of random data at power up in my bank of displays was coming from, prior to the first display data write. And I was a bit too slow in accepting I got reading the datasheet wrong, or the datasheet didn't apply to the clone I was using.

I was wondering if someone had a definitive answer from some deep investigation or perhaps insider information. It seems not, and it may not be consistent anyway.

For the clone MAX7219s in my collection, the SRAM is not cleared on power-up. I don't know if that is the case for genuine MAX7219 or for different clones for that matter. In future, I will just assume not and zero out the SRAM manually.

That point about a pull-up resistor on the chip select(CS) line to mitigate erratic behaviour is an excellent one. Random noise here can easily generate unexpected results.

It should be noted though that if the CS line is not the default Slave Select (SS) of the SPI pin group, it is not enough to use a pull-up resistor alone.

The SPI begin function takes care of the case that the default SS pin will glitch low as it is made an output if the corresponding bit in the output register is not set to 1 prior to setting the pin to output mode.

For the default SS pin, begin() does a digitalWrite HIGH first, setting the internal pullup resistor on (and the output register bit to 1) then a pinMode to OUTPUT, thus if the SS pin is already pulled high by a resistor there are no glitches.

However, if the CS pin is a pin other than the designated SS, then the same process must be undertaken by user code. If forgotten, even a pulled up pin will glitch low as the output register, with the bit set to 0, is transferred through to the pin when it is configured as output.

It is easily fixed using the same method as the SPI library uses, digitalWrite a HIGH to the CS pin, then set that pin to OUTPUT. And pull it up, of course.

title: Clarification of power-up behaviour of MAX7219 display driver

Answers: 1

body:
I think it's pretty clear from the datasheet.

> all control registers are reset

The digit displays are registers, and therefore they will contain zeroes.

Displaying one digit, being in shutdown mode, and minimum intensity are all what would happen if all registers were set to zero.

> I have sought widely and cannot find a definitive statement.

Why is this important to know? When powered on it will be blank, as stated. Presumably you will configure it to the way you want it before leaving shutdown mode.


body:
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

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

Answers: 1

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));
    }
}
```


body:
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

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

Answers: 1

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()`.


body:
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?

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

Answers: 1

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


body:
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 ?

title: Carbon dioxide sensor MG 811

Answers: 1

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.


body:
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

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

Answers: 1

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.


body:
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.

title: Arduino Timer Drift Issue

Answers: 3

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.


body:
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

title: DS3231 with Arduino Nano for Timing precision

Answers: 1

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.


body:
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?

title: Is ESP8266 dropping an interrupt?

Answers: 1

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.


body:
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.

title: UDPSendReceiveString example using Arduino Due with ENC28J60 Ethernet Module

Answers: 1

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.");
    }
  }
```


body:
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?

title: Arduino Nano R3 & Deek-Robot datalogging shield

Answers: 1

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


body:
I have a toy that has a dc motor and is runing with 2xAA bateries ( i think it is 3v motor)

So i want to run it with 5v power supply.

First question: Can 5v damage the motor

Second question: i think i need to add diode but dont know what diode to add and how to determine what i need

Third question: is there a combination that i can add series of diode so i can drop voltage to 3v

title: Controll the dc motor that works with 2xAA bateries using 5v

Answers: 1

body:
[DC electric motors][1] are usually rated to run over a range of voltages.  If you are unsure of the specifications of the DC electric motors you have, consider buying new motors which are specified to operate in a rage that includes 5VDC.

Consider not running both the processor (Arduino) and any high current demanding device off the same power source.  Such as solenoids or motors.  This is especially true for mobile devices supplied by battery voltage.  Often is the case the processor will reset (behave unexpectedly) should the supply voltage drop because of activating a solenoid or motor.

Diodes and other components are added to suppress or mitigate undesired effects of a solenoid or motor.  Inductive loads such as solenoids or motors resist changes in current flow and can damage connected components if the undesired current flow is beyond the connected component's abilities.  Read [this stackexchange question/answer][2] for more about this.

A silicon diode has a forward bias voltage drop of about 0.6 volts.  Other diodes have different forward bias voltage drops.  [This wikipedia article lists a few different diodes][3]. It may be possible to arrange enough diodes in series to drop 5 volts to 3 volts.

Consider searching for a 5VDC controllable Arduino relay module.  There are plenty on the web.  Such a device should include the circuitry to safely control the relay and the relay should provide more than adequate isolation from the DC motor.

For a learning experience, consider following [this Arduino / Motor tutorial provided by Adafruit][4].

  [1]: https://en.wikipedia.org/wiki/DC_motor
  [2]: https://electronics.stackexchange.com/questions/95140/purpose-of-the-diode-and-capacitor-in-this-motor-circuit
  [3]: https://en.wikipedia.org/wiki/Diode#Forward_threshold_voltage_for_various_semiconductors
  [4]: https://learn.adafruit.com/adafruit-arduino-lesson-13-dc-motors


body:
```
int ledy = 5 ;
int leds = 4 ;
int ledk = 3;
int button = 2 ;
int count = 0 ;

void setup()
{
  pinMode(ledy, OUTPUT);
  pinMode(leds, OUTPUT);
  pinMode(ledk, OUTPUT);
  pinMode(button,INPUT);
  randomSeed(analogRead(A0));
}

void loop()
{
  if(digitalRead(button)== HIGH)
  {
  count = count++ ;
  }
    if (count==1)
  {
    digitalWrite(ledk, HIGH);
    digitalWrite(leds, LOW);
    digitalWrite(ledy, LOW);

   }
    else if (count==2)
   {
    digitalWrite(ledk, LOW);
    digitalWrite(leds, HIGH);
    digitalWrite(ledy, LOW);

    }

   else if (count==3)
   {
    digitalWrite(ledk, LOW);
    digitalWrite(leds, LOW);
    digitalWrite(ledy, HIGH);
   }

     delay(1000);

}
```
I don't undertstand why it isn't working.
I want it three leds to light up one by one as loop. But none of them lights up.

title: I don't understand what's wrong with this code

Answers: 1

body:
One thing that jumps out to me as a possible cause of your issue here is that many push buttons require a [pull-up resistor](https://docs.arduino.cc/learn/microcontrollers/digital-pins#properties-of-pins-configured-as-input_pullup), which is provided as an internal component of most microcontrollers, but needs to be specifically requested in the `pinMode` instantiation of the button. Try changing your `setup()` function to the following:

```
void setup()
{
  pinMode(ledy, OUTPUT);
  pinMode(leds, OUTPUT);
  pinMode(ledk, OUTPUT);
  pinMode(button,INPUT_PULLUP);
  randomSeed(analogRead(A0));
}
```
however if you do this, you must also change your if statement to `if(digitalRead(button) == LOW)`, as a pullup resistor will make it so that when the button is not pressed, the pin is pulled high, and vice-versa.

Another way to troubleshoot this is to see if the LEDs light up when you remove the reliance on the button altogether by removing the
```
if(digitalRead(button)== HIGH)
  {
  count = count++ ;
  }
```
and changing it to
```
count++;
delay(1000);
```
and see if the LED changes every 1 second (delay requires a millisecond value). I agree with @StarCat that `count = count++;` possibly isn't doing what you think it is.


body:
I'm trying to creaper class wraper to use an `Stream`object but I've an error when I try to compile.
My `.h`file :
````
#include <Arduino.h>

class TestSerialListener {
public:
  TestSerialListener(Stream &serial);
  void testPrint(void);
private:
  bool _listener_start;
  Stream &_serial;

  void startListener(void);

};
````

my `cpp`file
````
#include "TestSerialListener.h"
#include <Arduino.h>

TestSerialListener::TestSerialListener(Stream &serial) : _serial(serial)
{
}

void TestSerialListener::testPrint(){
 _serial.begin(115200);      <---------- error compilation
 _serial.println("test");
}

void TestSerialListener::startListener(void)
{
 if(!_listener_start){
  _listener_start = true;
 }
}
````

And when i try to compile it I got this error : `error: 'class Stream' has no member named 'begin'`Why I can't use `begin()`in my classe ?

title: How to pass Strem object to my class

Answers: 1

body:
the `begin()` method is defined in the `HardwareSerial` class, not in `Stream`. You can look that up yourself in your Arduino installation. For me these files are placed under `~/.arduino15/packages/arduino/hardware/avr/1.8.6/cores/arduino/` and are named `Stream.h` and `HardwareSerial.h`.

And if you  think about it, this is quite logical. The `Stream` class can represent any object, that can stream data. It doesn't know anything about how exactly the data is streamed on a hardware level. It just provides the convenient functions for handling the data. The `HardwareSerial` class then derives from `Stream` to get those data handling methods and adds its own methods to handle the hardware side of the problem, including setting a baudrate.

When providing a `Stream` reference to a class constructor you want to `begin()` the corresponding object outside of the class, before you start to stream any data through it. Doing it this way makes your class widely usable, since you could use any `Stream` object, even a file on an SD card.

So move the `begin()` line from your class to the `setup()` function in your main code.

---

For reference: Juraj showed the inheritance between the classes in his answer to [this question][1]. Have a look at it, since it is quite enlightening.

  [1]: https://arduino.stackexchange.com/questions/78719/can-you-use-serial-port-as-a-variable/78725#78725


body:
I want to use a 3.3V pro mini that uses a BME 280 to take temp/pressure/humidity, and nRF24L01 module to transmit the data, at ?10 minute intervals. I want to use 1, 2,3 or 4  AA batteries to power it. I've read all about the techniques to reduce power consumption, by removing the power LED and using sleep functions.
But I would like to know the most efficient combination of batteries to use. If I can get a year out of 1 battery and a step-up converter, I would be happiest with that. But perhaps 3 duracell or 4 (rechargeable) batteries  connected directly to the Vcc pin (ie no regulator) might be better. Does anyone have first-hand experience to know what works best?

title: Arduino 3.3v pro mini, most efficient use of AA batteries for power

Answers: 1

body:
You can definitely do better with another regulator that the on-board ones, which are not energy efficient because they drop the supply voltage through a resistance, wasting the excess current as heat. An external boost regulator would waste much less current (charge, really, since we're trying to make maximum use of the battery capacity, or equivalently, trying to minimize the capacity & space needed to run your system for a year).

So you need two things:
1. The most space-efficient way (I assume...) to store a year's energy needs; and
2. A pretty good idea of what the energy requirement will be.

For (2.), you'll need an energy budget for your system:
1. How much current your system draws when it is awake;
2. How much current your system draws when it is asleep;
3. It's duty cycle (e.g.: 3% awake time, 97% sleep time), and use that to calculate the total charge in milliAmp-hours the system draws during the 1 year.

Don't forget to account for the batteries' inefficiency when they're cold, if that will be an issue, and add in a safety factor so it won't die before you arrive a year hence to change the batteries.

You'll need to consider powering down the sensor(s) and radio(s) during CPU sleep; their idle draw would make sleeping the CPU ineffective (as far as saving battery is concerned).

Once you have an energy budget, you can look at the available ways to store and deliver a year's worth - regulator type, size and efficiency; battery size and count) to see what combination will meet your needs for cost, simplicity, and space limitations.