user66713: How precisely can an Arduino nano be timed? The project I am working on needs two Arduino nano to work synchronously. Arduino one have to activate a relay after 2700 sec and Arduino two have to activate a second relay after 2700.360 sec (360 milli seconds after )
With the code given below the required accuracy is not achieved.
volatile uint32_t ovfCount = 0UL;
volatile uint32_t currentTime = 0UL;
volatile unsigned long time_prev = 0UL;
volatile unsigned long dT = 0UL;

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

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

volatile bool coilOn_flag = false;

ISR(INT0_vect) {
  
  EIMSK = 0b00000000;
  
  TCCR1B = B00011100;
  PORTB ^= (1<<0);
  ovfCount = 0;
  TIFR2 = 0;
  TCNT2 = 0;
  
}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(TIMER1_OVF_vect) {
  //pass
}

ISR(TIMER1_COMPA_vect) {
  //pass
}

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

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

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

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

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

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


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

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

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

  PORTB ^= (1<<0);
}

void loop() {
  
}

How to correct the code.?

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

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

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

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



66713: <p>How precisely can an Arduino nano be timed? The project I am working on needs two Arduino nano to work synchronously. Arduino one have to activate a relay after 2700 sec and Arduino two have to activate a second relay after 2700.360 sec (360 milli seconds after )</p>
<p>With the code given below the required accuracy is not achieved.</p>
<pre><code>volatile uint32_t ovfCount = 0UL;
volatile uint32_t currentTime = 0UL;
volatile unsigned long time_prev = 0UL;
volatile unsigned long dT = 0UL;

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

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

volatile bool coilOn_flag = false;

ISR(INT0_vect) {
  
  EIMSK = 0b00000000;
  
  TCCR1B = B00011100;
  PORTB ^= (1&lt;&lt;0);
  ovfCount = 0;
  TIFR2 = 0;
  TCNT2 = 0;
  
}

ISR(TIMER2_OVF_vect) {
  ovfCount++;
}

ISR(TIMER1_OVF_vect) {
  //pass
}

ISR(TIMER1_COMPA_vect) {
  //pass
}

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

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

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

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

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

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


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

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

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

  PORTB ^= (1&lt;&lt;0);
}

void loop() {
  
}
</code></pre>
<p>How to correct the code.?</p>
 7508: <p>The Arduino Nano is nowhere accurate enough for your application, and
this has nothing to do with your code: it is a hardware limitation. 360
extra milliseconds after 2,700 seconds is a difference of only
133 ppm (parts per million). The Arduino Nano is clocked off a
ceramic resonator, and these time sources carry a typical error of the
order of 1,000 ppm. The best thing the code can do is count the
clock cycles with perfect accuracy, which makes the software timing as
good as the underlying hardware, but never better.</p>
<p>Some options you may try:</p>
<ol>
<li><p>The one that seems most obvious is to have the first Arduino somehow
send a trigger signal to the second one when it activates the first
relay. Or have the second Arduino sense the state of that relay.
Then, all the second Arduino has to do is wait for 360 ms, which
it can easily do with reasonable accuracy.</p>
</li>
<li><p>If there is no way the Arduinos can communicate, then you could try
to add external time sources to the Arduinos. Some RTC modules can
output a 32,768 Hz signal that could be accurate enough for your
needs. Look for a temperature-compensated RTC, as those are more
accurate.</p>
</li>
<li><p>If you cannot add extra hardware, you could try to calibrate the
clocks of your Arduinos in order to compensate for their relative
drift. Keep in mind though that the drift rate is
temperature-dependent, and wanders randomly even at constant
temperature. First read the article <a href="http://jorisvr.nl/article/arduino-frequency" rel="nofollow noreferrer">Arduino clock frequency
accuracy</a>, by Joris_VR, to get an idea of the accuracy you
could expect from such calibration.</p>
</li>
</ol>
