I2C slave read loop

yesterday, i was experimenting with a FRC Roborio and an arduino mega on the I2C bus as a slave reader. the master device (roborio) is configured to send six messages in a specified order over I2C. after which the arduino reads this and is supposed to write these six integers. however something in the read function is causing the integer to increment incorrectly skipping from the first if statement to the code outside all of the if, else if and else statements. I’m going crazy trying to figure out why it is doing this. The way it should be behaving is every time the arduino receives a message it should go to the next version of the read until it hits the sixth if. It should never hit the else. if anyone has some insight or idea of why this would be happening and how to fix it, I would most definitely appreciate it.

Attached is the current version of the sketch.

i2canalogwrite_frimware2.ino (2.2 KB)

Coalman321:
yesterday, i was experimenting with a FRC Roborio and an arduino mega on the I2C bus as a slave reader. the master device (roborio) is configured to send six messages in a specified order over I2C. after which the arduino reads this and is supposed to write these six integers. however something in the read function is causing the integer to increment incorrectly skipping from the first if statement to the code outside all of the if, else if and else statements. I’m going crazy trying to figure out why it is doing this. The way it should be behaving is every time the arduino receives a message it should go to the next version of the read until it hits the sixth if. It should never hit the else. if anyone has some insight or idea of why this would be happening and how to fix it, I would most definitely appreciate it.

Attached is the current version of the sketch.

Your code has many errors:

  • First, you should mark all global variables used in the ISR(interrupt service Routine, receiveEvent()) as volatile.
  • Second, you are NOT incrementing your index variable.
  • iter+1;* just temporarily calculates what iter plus 1 is, then discards the result.
  • Third, Wire.read() returns ONE byte at a time, Just because specify an Integer as the storage location, Wire.read() will only return a value from 0 to 255.
  • Fourth, you have no synchronization event. How do you know your iter stage value matches the I2C master’s stage?
  • Fifth, why do you set iter to zero after the 6th stage, then any time iter is not between 1 and 6 you print How??? then set iter back to zero?

Instead of sending one integer at a time, I would send all six in one 12byte block.

My example code to read integers from Wire:

void receiveEvent(int howmany){
uint8_t a=0;  // index variable
while(howmany=>2){ //will be working with two bytes at a time. throw away any odd bytes
  int x = Wire.read(); // first byte, high byte
  x = x<<8;  //move it from low byte to high byte
  x = x + Wire.read(); // merge in low byte
  howmany = howmany -2;
  a++;  
  switch(a){
    case 1 : ;  // do something with first integer
       break;
    case 2 : ;  // do something with second integer
       break;
    case 3 : ;  
       break;
    case 4 : ;  
       break;
    case 5 : ;  
       break;
    case 6 : ;  
       break;
   default : ; // too many integers
  }
}

// code to send integer

void sendBlock(){
Wire.beginTransmission(84);

Wire.write(highByte(integer1));
Wire.write(lowByte(integer1));

Wire.write(highByte(integer2));
Wire.write(lowByte(integer2));

Wire.write(highByte(integer3));
Wire.write(lowByte(integer3));

Wire.write(highByte(integer4));
Wire.write(lowByte(integer4));

Wire.write(highByte(integer5));
Wire.write(lowByte(integer5));

Wire.write(highByte(integer6));
Wire.write(lowByte(integer6));

Wire.endTransmission();
}

Chuck.

I suppose I should have started off by stating I have never worked with the wire library nor I2C communication before. The only reason I was using it was because serial failed between the two devices. I am only sending a singular byte (0 to 255) at any particular time. They also have as I said, a particular order that begins with the first I2C transmission well after both devices have successfully booted up which removes the necessity(I thought) for any synchronization event. The answer to your fifth question is that I added it to figure out if it ever got outside of where it theoretically ever could be in an attempt to get as much information as I could out of it. I am implementing the fixes along with some other stuff and will reply on its status. thanks for the pointers, Coal ----------------------Edit I tested my fixed version and there were major de-sync issues between the two. I will look into how the roborio(runs on labview) sends larger amounts of data over I2C.