Simple way to synchronise 2 Arduinos ?

I want to keep 2 Arduino Nano's in synch, I'm not looking for super accuracy.

The same code will be running on both.

I already have an ISR that runs every 125uS, during which one of the output pins is pulsed low (A shift register "latch" bit). Or there's a longer signal from the shift register's "enable" bit.

I'm thinking I could cross-connect these outputs to inputs on each board, and somehow use them to pause the void loop until both have occurred, this should keep the two sketches pretty well synchronised ?

I'm struggling a bit with the concept - has anyone done anything similar, or could offer some advice....

I have spare outputs and inputs, so another idea I have is for each arduino to raise an output high within the void loop.

The output connected to an input on the other....

When both the output and input are high, allow the void loop to continue, immediately turning off the synchronising output.

I think I will try this method first.....

When you say "in synch" what exactly do you want to happen at the same time and how much timing error (how many microseconds) would be acceptable?

I'm not sure if it would be practical to expect the loop() function on both Arduinos to start at the same time (+/- 5 microsecs). But if, for example, you want LEDs to flash at the same time using millis() to control the flashing then I think it would possible to keep that in sync without too much trouble. A co-ordinating pulse from one Arduino to the other every 100 msecs or so would probably be sufficient.

How far apart are the two Arduinos?

Is it really necessary to use two?


Robin2: Is it really necessary to use two?


Now I feel a bit stupid.... No, it isn't necessary to use two at all.... [#bangheadmoment]

My existing project is an RGB light controller that controls 64 LED's with shift register multiplexing.

I wanted to extend that to 128 LED's so initially thought of using two of my PCBs (synchronised, hence the original post), but now realise I can just extend the shift register from one PCB to the other, it'll only be a few jumper wires to the secondary boards, arduino header pins !!!

Thanks Robin2 -

abtrain: Now I feel a bit stupid.... No, it isn't necessary to use two at all.... [#bangheadmoment]

Welcome to the club. :)

Glad to be of some use.


I actually don't need to serialise the two shift registers - one arduino can drive both of them simultaneously, since I want both LED "sets" to do the same patterns.

I just need to link my "master" OE, LE, SData, and SClk to my "slave" board. I believe the outputs will "fan-out" successfully to two boards (each output will then drive 8 "74HCxxx" inputs. If that is not successful, I can add a non-inverting buffer chip....

For what it's worth, I put together some test code to measure synchronization across two Uno boards using the approach suggested in the original post.

Using the standard Arduino digitalRead routines, synchronization was on the order of 5 uS worst case, consistent with the execution time of that function.

Using a direct register approach, the worst case I saw was about 250 nS (non rigorous testing).

 * Test synchronization of two Arduino boards
 * Boards are wired pin 8 on one to pin 9 on the other and vice versa
 * "busyPin" monitored by logic analyser to measure sync offset

# define syncInPin 8
# define syncOutPin 9
# define busyPin 10
# define notSyncIn ((PINB & 0b00000001) == 0b00000000)
# define setSyncOut PORTB |= _BV(PB1)
# define clrSyncOut PORTB &= ~_BV(PB1)

void setup() {
  digitalWrite(syncOutPin, LOW);
  pinMode(syncOutPin, OUTPUT);
  pinMode(syncInPin, INPUT);
  digitalWrite(busyPin, LOW);
  pinMode(busyPin, OUTPUT);

void loop() {
  // digitalWrite(syncOutPin, HIGH);             // Indicate ready to sync
  setSyncOut ;                                   //   Direct register version of above 
  // while (digitalRead(syncInPin) == LOW) { } ; // Block until syncIn
  while (notSyncIn) { } ;                        //   Direct register version of above 
  digitalWrite(busyPin, HIGH);                   // Indicate "task" is being done
  // digitalWrite(syncOutPin, LOW) ;             // Clear sync
  clrSyncOut ;                                   //   Direct register version of above
  delay(random(1,10)) ;                          // Variable length "task"
  digitalWrite(busyPin, LOW);                    // Done with "task"