Sending Time variable as Unsigned long trough I2C

Hey to all :slight_smile:
We have a problem using time related variables and i2c communication, and we hoped you could help. We use 2 arduino mega256 bords with shields for DC motor control. We use code for master writer and slave receiver. Master arduino control main motor and sends informations about digital input which control side motor connected on slave arduino. We need to make this main and side motors time sync.
Sending integers trough i2c works normally, but when we try to make delay()( for speeding motor up) in slave code it dosn’t work. So we tried using ellapsedTime and millis() to transfer information about elapsed time from master to slave, but when we try to check communication using serial.print of variables we get different results. Maybe problem is in sending unsigned long trough i2c? Is it even possible to do that ? Maybe it’s not possible to send more then 1 byte at a time. We would be very grateful for any advice about sending time related variables trough i2c and time synchronization :smiley:

Code for master:

#include <Wire.h>
#include <AFMotor.h>
const int B_Pin=53;
int B_State=LOW;
AF_DCMotor M(1);
void setup()
{
  Wire.begin(); 
  Serial.begin(9600);
  pinMode(B_Pin, INPUT);
}
void loop()
{ 
  B_State= digitalRead(B_Pin);
  unsigned long motor_timer=millis();
  while ( millis()-motor_timer<1000){
  // start main DC motor on Master Arduino in 1 sec
  }
  unsigned long motor_elapsed=millis();
  Serial.print ( motor_elapsed);
  Wire.beginTransmission(2); 
  Wire.write(B_State); // sends command for starting side motor on Arduino Slave 
  Wire.write (motor_elapsed); // sends time that is passed during start-up of main code
  Wire.endTransmission();    
 // stop main DC motor on Master Arduino
}

Code for slave:

#include <Wire.h>
#include <AFMotor.h>
int State_B;
unsigned long m_elapsed;
AF_DCMotor M1(1);
void setup()
{  Wire.begin(2);                
  Wire.onReceive(receiveEvent); 
  Serial.begin(9600);          
}
void loop()
{    unsigned long loop_slave=millis();
          while ( millis()-loop_slave<10){
            Serial.print("Loop Slave ");
          }
}

void receiveEvent(int howMany)
{
       State_B=Wire.read(); // receive byte as integer
       m_elapsed= Wire.read();
       Serial.print(m_elapsed); // different number from the one send from Mster
      unsigned long s_begin=millis();
      while ( millis() - s_begin< 100+m_elapsed){
        // starts and stops side motor on Slave Arduino 
      }
}

Please read the reference : http://arduino.cc/en/Reference/WireWrite It transmits a byte. In your code you transmit a byte for "B_State" and a byte for "motor_elapsed". That are two bytes. In the slave, the "howMany" parameter should be 2. You could check for 2 and read the two bytes.

You can create a package of data with a structure. Or transmit an integer with : Wire.write(&B_State,2); In the receiver, you have to glue those two bytes into an integer: http://arduino.cc/en/Reference/WordCast With a structure, you don't have to use glue.

(I'm not sure this is okay, the type definition was update for structures...)

// Be sure that the master and slave use the stame structure.
struct mydataStruct 
{
  int B_State; 
  unsigned long motor_elapsed; 
} myData;
...
myData.motor_elapsed = 1000UL;
...
Wire.write (&myData, sizeof(myData));

In the slave, you can't read multiple bytes with the Wire.read() function. You have to Wire.read() bytes into the structure. You can use a pointer for that or a char array, or a union.

The receiveEvent() is run from the Wire library in an interrupt. That means that the receiveEvent() should be very short. No while-loops, no delays, an no use of Serial at all. The Serial library uses buffers and interrupts and that can not be done from within the receiveEvent()