Time Synchronization between 2 Arduino Uno while SPI Communication

Hello guys. I have a problem with time synchronization.

Situation
My goal is to get data transfer time between 2 Arduino Uno.
For this, I used time stamp method just like picture below;
image

Problem
I used the code that master send "K" and slave send ASCII code of count.
My code was running very well, but the time (I used micros() function) between master and slave was not synchronize.

// Master Result //
16:27:23.512 -> Master sent at: 3946640
16:27:23.543 -> Received data: :
16:27:23.543 -> Master received at: 3946656
16:27:23.579 -> Total time: 16

// Slave Result //
16:27:23.511 -> Slave received at: 3301460
16:27:23.544 -> Slave sent at: 3301464

Question
So, is there any solution for synchronize hardware clock between 2 Arudino Uno?
Especially, using only software not additional devices (etc. GPS, RTC, NTP).

Code

// Master Arudino

#include <SPI.h>
void setup (void)
{
  SPI.begin (); 
  digitalWrite(SS, HIGH);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  Serial.begin(9600);
}
void loop (void)
{
  if(Serial.available()){
    char data = Serial.read();
    if(data == 'K'){
      unsigned long masterSend = micros();
      digitalWrite(SS, LOW); 
      char received = SPI.transfer(0);
      unsigned long masterReceive = micros();
      digitalWrite(SS, HIGH); 

      Serial.print("Master sent at: ");
      Serial.println(masterSend);
      Serial.print("Received data: ");
      Serial.println(received);
      Serial.print("Master received at: ");
      Serial.println(masterReceive);

      Serial.print("Total time: ");
      Serial.println(masterReceive - masterSend);
    }
  }
}
// Slave Arduino

#include <SPI.h>
byte count;

void setup (void)
{
  Serial.begin(9600);
  pinMode(MISO, OUTPUT);
  pinMode(MOSI, INPUT);
  pinMode(SCK, INPUT);
  pinMode(SS, INPUT);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  SPCR |= _BV(SPE); 
  SPCR &= ~_BV(MSTR); 
  SPCR |= _BV(SPIE); 
  count = '0'; 
}
ISR (SPI_STC_vect)
{
  unsigned long slaveReceive = micros();
  SPDR = count;  
  unsigned long slaveSend = micros();

  Serial.print("Slave received at: ");
  Serial.println(slaveReceive);
  Serial.print("Slave sent at: ");
  Serial.println(slaveSend);
}
void loop (void)
{
  count = (count + 1) ; 
  delay(1000);
}

Welcome to the forum

Why not pass the time with the data ?

Why do you need o use 2 Arduinos ?

Thank you for your reply.

What do you mean about "pass the time"?
You mean transfer time stamp with data?

I was trying to use SPI between Nvidia Jetson Nano & Arduino, but I don't have any level shifters.
So before this, I was using 2 Arduinos check SPI communication.

My final goal is to transfer float type data from Arduino to Jetson Nano using SPI under 10ms. So I asked the solution for software not additional hardware.

You have messed up SPI and UART communications.

You are transmitting data to Slave over SPI Port and you should expect the response from the Slave over the same SPI Port. You may study the following diagram (Fig-1) to implement the SPI's back-to-back communication.


Figure-1:

What do you mean about this?
I used serial for serial monitor, not the communication.
I only used SPI for data transfer.

Yes

If the Jetson Nano uses 3.3V on its inputs than you will need hardware to convert between the 5V output of the Nano and the 3.3V inputs

Ok!
Sorry! I did not notice the code: SPDR = count; in the Slave sketch.

1 Like

It's okay! :smile:

Is this --?

count = 0;
or
count = 48;

My mistake;;
It is `count = 0;

`

1 Like

what do you call the "hardware clock" ? There is a timer that counts the time since the arduino booted up, so if they were not started at the exact same microsecond you can expect the count won't match

Does it matter to have such synchronisation? Not sure I understand the use case.

But what about next?
I don't know the next process after sending data with time stamp...

Thanks for your reply.

I can use "Round-trip time (RTT)" method to check the data transfer time between devices.
But, RTT is not very exact if the network is asymmetric...
So I have to check using time stamp if RTT is exact or not.

but what are you using this for? why do you need the "data transfer time between devices"?

(the SPI exchange happens through an interrupt and millis() will be blocked and micros() can be wrong if the timer rolls over as the associated iSR won't be called)

Well, as I mentioned above, my final goal is to transfer "float type" data from arduino to Jetson Nano under 5~10ms.

So, I need to check the time if data transfer in time or not.

What do you want to do with the timestamp ?

Do you want to know when the data was read and sent or do you want to know how long it took to send and receive the data ?

I'm not that familiar with SPI but did you do the theoretical calculation? Let's say that you transfer a float (4 bytes) at 100kBits/second. That will take 32/100000 = 320 microseconds; there might be a bit of overhead but it's far from your 5-10 milliseconds.

1 Like

Want to know how long it took to send and receive the data maybe correct for me.

Well, I'm actually planning about sending 30 float type data in a list from arduino & receive it with list in Jetson Nano.

So I tried UART to USB connection before which takes about 10ms with round-trip time.
But I need to stack that data list about 50, so I need to check the fastest way to communicate.

The result was SPI which is about 2Mbps (max) while using level shifter and Analog kit for Jetson Nano use SPI.

For these reasons, I take the SPI.

Sorry for bad english...

At 100kBits/second, transferring 30 floats = 120 bytes = 960 bits will take roughly 1ms

5 to 10ms is plenty.

Did you try at 9600 bauds ? try at 500k or 1m Bauds with a hardware serial.

1 Like