syncing multiple Arduino based sequencers

Hello,

I'm working on a project - building several sequencers - and I'm having some trouble keeping the Arduinos synced.

I read some topics about Arduino clock syncing, but I'm not sure if those solutions serve my purpose.

I want to upload the same code to every Arduino and later decide - using an on/ off switch - which one will be the master and which one(s) will be the slave(s).

The slaves are initialized first and then they wait - while loop - until the "syncPin" gets HIGH.

The first sync stage works great but after some time, after entering the loop function, everything starts to get ou of sync.

At the moment I'm using one Arduino Uno and one Arduino Mega, would be enough to use two similar boards, like two Mega's?

//analog pin - will read pot "tempo"
int const analogInMaster=0;

//analog pin - will receive master voltage "tempo"
int const analogInSlave=1;

int pinTempo;
int tempo;

//review pins
int pinTestMaster;
int const pinSync=3;

bool IamMaster;
bool doneSync=0;

int const pinLed=5;

void setup() {
  Serial.begin(9600);

  //debug
  //master
  pinTestMaster=HIGH;

  //debug
  //slave
  //pinTestMaster=LOW;

  pinMode(pinLed,OUTPUT);
  //pinMode(pinTestMaster,INPUT);
  
  if(pinTestMaster==HIGH){
    //Serial.println("teste");
    IamMaster=1;
  }
  else if(pinTestMaster==LOW){
    //Serial.println("teste");
    IamMaster=0;  
  }
  
  if(IamMaster==1){
    //Serial.println("teste");
    pinTempo=analogInMaster;
    pinMode(pinSync,OUTPUT);
    digitalWrite(pinSync,HIGH);
    delay(100);
    digitalWrite(pinSync,LOW);
  }
  else if(IamMaster==0){
    //Serial.println("teste");
    pinTempo=analogInSlave;
    pinMode(pinSync,INPUT);
    while(doneSync==0){
      //Serial.println(digitalRead(pinSync));
      if(digitalRead(pinSync)==HIGH){
        doneSync=1;
        break;
      }
      delay(10);
    }
    delay(100);
  }

  //testing sync
  digitalWrite(pinLed,HIGH);
  delay(500);
  digitalWrite(pinLed,LOW);
  delay(500);
  digitalWrite(pinLed,HIGH);
  delay(500);
  digitalWrite(pinLed,LOW);
  delay(1000);
}


void loop() {
  //Serial.println(analogRead(pinTempo));
  tempo=map(analogRead(pinTempo), 0 , 1023, 60, 800);
  tempo=60000/tempo;
  digitalWrite(pinLed,HIGH);
    delay(50);
    digitalWrite(pinLed,LOW);
    delay(tempo-50);
}

Thank you in advance.

Kind regards,

Marco

You need the sync signal to be continuously transmitted from the master to the slaves so they know what the master time is, not just the apparent local time which will diverge due to clock drift. This is basically how Midi Sync works.

On a practical level you could send a 1 kHz signal from the master and use an interrupt on the slaves to update a counter which is effectively a local copy of the master clock and you sync the slave activity to the value of that master clock.

The delay() function uses local time, not the master time so you'll need to replace it with a function that checks to see if the master clock has reached some predetermined or calculated value.

mikb55, thank you so much for your reply.

I changed the code based on your suggestion. It doesn't look pretty, but it's working.

I would still like to try something with the 1kHz signal that you mentioned. Can you please guide me through it? What should I do? Or where can I find more info?

void ioTempo(bool first, int tempo=0){
  if(IamMaster==1){
    if(first==1){
      delay(50);
      digitalWrite(pinSync, LOW);
    }
    else{
      delay(tempo-50);
      digitalWrite(pinSync, HIGH);
    }
  }
  else{
    if(first==1){
      while(digitalRead(pinSync)==HIGH){
      //do nothing
      //just hold
      }
    }
    else{
      while(digitalRead(pinSync)==LOW){
      //do nothing
      //just hold
      }
    }
  }
}

void loop() {
  //Serial.println(analogRead(pinTempo));
  tempo=map(analogRead(pinTempo), 0 , 1023, 60, 800);
  tempo=60000/tempo;
  //do it
  digitalWrite(pinLed,HIGH);
  if(IamMaster==1){
    ioTempo(1, tempo);
  }
  else{
    ioTempo(1);
  }
  
  digitalWrite(pinLed,LOW);
  if(IamMaster==1){
    ioTempo(0, tempo);
  }
  else{
    ioTempo(0);
  }
}