0

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 toThis question, and from the advice ofedgar-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->millisuint32_t coilTime = 5 * 1000UL; // second->millisvolatile uint32_t count = 0;/* * 32768 ticks in 1 sec * 0.032768 tick in 1 us */float _multiplier = 0.032768; // 32768 Hzuint32_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 value1 sec -> 1.0003877922 sec -> 2.00078420850 sec -> 50.020926833250 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.

datasheet-ds3231

Gil Sven's user avatar
Gil Sven
1711 silver badge9 bronze badges
askedJan 26, 2023 at 6:57
Lawliet's user avatar
7
  • I'm not completely sure I understand your use case because, at least for the initial synchronisation, there is a connection between the 2 devices.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.CommentedJan 26, 2023 at 12:24
  • Can you please advise me on the correct variables to be used? In the initial case, I have a common switch connected to my devices and I use that as the interrupt signal.CommentedJan 26, 2023 at 15:36
  • 1.0000000 / (1.000387792 / 32768 ) = 32755.29776 .... that makes 32755 ticks in 1 secondCommentedJan 26, 2023 at 17:04
  • 1
    after 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...CommentedJan 26, 2023 at 17:17
  • 1
    Instead of using floats to specify the time interval, why not specify say 1 second as 32768? At a quick glance, the loss of ticks (in comparison to your reference) seems linear at around 13 per second. Maybe try switching off timer 0 to inhibit its possibly clashing interrupts and then you'll have to find another solution for delay().CommentedJan 27, 2023 at 6:58

2 Answers2

1

This may not be a proper answer to your question. Instead of telling youhow to improve the accuracy, I will show you how to measure it. Theissue is that the code you posted is doing too much stuff, and it is notclear how it could be measuring the clock accuracy. So, instead Isuggest 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
const uint8_t input_pin = 5;  // 32768 Hz on digital 5 = T1const uint8_t clear_pin = 2;  // button to clear timervoid 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 tocount the falling edges of the 32768 Hz signal. Bit 14 of the countershould then toggle at 1 Hz. This bit is output on the built-in LED tolet you check its frequency. You can use the push button to reset thephase of the blinks.

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

answeredJan 29, 2023 at 21:01
Edgar Bonet's user avatar
0

It looks like you have a drift problem (?) Some of the DS3231 RTC modules on the market have significantly more drift than the datasheet spec and the only way to know if you have one of those is to tune the aging register and test it. In a stable temperature environment you can usually get a -SN to a millisecond per day of clock drift.

This can be done with an Uno and a cheap GPS module:https://thecavepearlproject.org/2024/10/22/setting-accurate-rtc-time-with-a-gps-the-ds3231-aging-offset-to-reduce-drift/

answeredNov 11, 2024 at 16:57
Ed Mallon's user avatar

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.