I need to synchronize two separate circuit boards working with Arduino Nano. The need is to activate one relay using Arduino-1 after 45 minutes, 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, and from the advice of edgar-bonet I have used one temperature-compensated RTC for timing the Arduinos externally (DS3231). I am using it's 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 is 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 do I make the clock more precise? In the data sheet it is said that the clock is accurate to +- 2ppm.
volatile uint32_t count . . . count = 0;
beware of asynchronous non-atomic operations on multi-byte variables on an 8bit MCU. For high precision calculations, float may have limitations:float _multiplier = 0.032768;
2ppm is about one second every five days.1.0000000 / (1.000387792 / 32768 ) = 32755.29776
.... that makes 32755 ticks in 1 secondafter 45 min and another relay using Arduino-2 after 45.36 seconds
does not declare the necessary precision ... for example, 45.36 can be anywhere between 44.355000... and 45.364999...