Hey there -
I have a setup with three (3) Arduino Dues where I’m trying to synchronize the microsecond timestamps between two of them. In my current setup, I have a central “time server”, which is booted up before all other Arduinos. This Arduino just responds with its own timestamp via I2C. The code is below.
The remaining two Arduinos are booted up sequentially (as not to crash on the I2C bus). Upon boot, each Arduino pings (via I2C) the time server Arduino and records the timestamp that the server reports. Then when a button is pressed on pin 10, the Arduinos will print out via Serial the [time server timestamp + micros()] (the timestamp in the reference frame of the time server…or close enough). The code is below.
In my current test rig, I have both Arduinos connected to the same button. However, the timestamps are off. Here are a few timestamps after a lot of button presses:
ARDUINO 1 ARDUINO 2
SYNCING… SYNCING…
97987306 97987360
105037345 105037442
105196726 105196824
120266032 120266224
120357427 120357620
128765414 128765659
128918271 128918517
136696763 136697058
136950139 136950435
136960594 136960890
147941940 147942305
148092120 148092486
158248603 158249032
158454726 158455157
158464636 158465067
163082746 163083206
163189754 163190214
164674937 164675406
164811519 164811989
167329300 167329786
167424599 167425085
168005684 168006174
168155157 168155623
168581157 168581652
168687951 168688445
183834746 183835336
183981555 183982146
187934177 187934792
188088331 188088948
188949054 188949676
188958589 188959870
189129449 189130072
189617876 189618502
189807592 189808219
Notice how they’re kinda close at the beginning, but as time goes on they’re way off (in terms of microseconds… )
I’m not really sure how to tackle this and would appreciate any advice.
Thanks a lot!
Aakash
Time Server code:
#include <Wire.h>
String timeValue; // Variable to hold time
void setup()
{
timeValue.reserve(10); // Reserve 10 bytes for unsigned long time
Wire.begin(0x50); // Setup I2C slave address as 0x50
Wire.onRequest(requestEvent); // Register event
}
void loop() {
// Do nothing
}
void requestEvent()
{
timeValue = String(micros()); // convert timestamp to string
volatile int timeLength = timeValue.length(); // find out how many digits are in the current time
// If not 10 digits (max digit length for unsigned long), add leading zeros
// This is to keep the time of I2C transfers consistent between subsequent read/writes
if(timeLength == 1){
timeValue = "000000000" + timeValue;
}
else if(timeLength == 2){
timeValue = "00000000" + timeValue;
}
else if(timeLength == 3){
timeValue = "0000000" + timeValue;
}
else if(timeLength == 4){
timeValue = "000000" + timeValue;
}
else if(timeLength == 5){
timeValue = "00000" + timeValue;
}
else if(timeLength == 6){
timeValue = "0000" + timeValue;
}
else if(timeLength == 7){
timeValue = "000" + timeValue;
}
else if(timeLength == 8){
timeValue = "00" + timeValue;
}
else if(timeLength == 9){
timeValue = "0" + timeValue;
}
Wire.print(timeValue); // respond with padded timestamp
}
Timer Sync code:
#include <Wire.h>
char dataFromTimeServer[10]; // char array to hold I2C data from TimeServer
unsigned long timeFromTimeServer = 0; // unsigned long to hold time from TimeServer
unsigned long currentSyncedTime = 0;
const int buttonPin = 10;
void setup() {
Serial.begin(9600);
Serial.print("SYNCING...");
syncTime(); // Sync time with TimeServer
digitalWrite(buttonPin,HIGH); // enable pull up resitor
attachInterrupt(buttonPin, buttonPress, FALLING); // register interrup on FALLING state
}
void loop() {
if(currentSyncedTime!=0){
Serial.println(currentSyncedTime);
currentSyncedTime=0;
}
}
// Run when falling
void buttonPress(){
// Record timestamp in reference frame of TimeServer
currentSyncedTime = timeFromTimeServer + micros();
}
// Method to read timestamp from central TimeServer over I2C
void syncTime(){
Wire.begin(); // Initialize I2c
Wire.requestFrom(0x50, 10); // Request 10 bytes
int index = 0; // index of char array
while(Wire.available()) // while more bytes avail
{
char c = Wire.read(); // receive a byte as character
dataFromTimeServer[index++] = c; // store byte in char array
}
timeFromTimeServer = atol(dataFromTimeServer); // convert char array to unsigned long
}