I2C : size of the request and size of the answer

Hi everyone,

Yesterday on the field I changed some parts of my sketch and encountered a problem when I wanted to send more informations through I2C than before.

So before I had this on the master arduino :

void I2C()     

{
  if(millis()>TKperiod)
  {
    TKperiod=TKperiod+100;

    Wire.requestFrom(0x47, 3);

    while(Wire.available()>0)
    {

      l=(Wire.read());
      h=Wire.read();
      j=Wire.read();
      
      }

  }
}

And on the slave sender :

void I2Csend()
{    
if(k<2) k++;
else k=0;
buffer[0]=highByte(T[k]);
buffer[1]=lowByte(T[k]):
buffer[2]=k;
Wire.write(buffer, 3);
}

And everything was great, I was getting all 3 bytes and decoded it fine.

Now I wanted to send 11 bytes through I2C so I made this on the Master Receiver :

void I2C()     

{
  if(millis()>TKperiod)
  {
    TKperiod=TKperiod+100;

    Wire.requestFrom(0x47, 11);

    while(Wire.available()>0)
    {
      
      for(z=0; z<10; z++)
      {
        buffer[z]=Wire.read();
      }

      T[buffer[2]]=word(buffer[0],buffer[1]);
      P1=word(buffer[3],buffer[4]);
      P2=word(buffer[5],buffer[6]);
      P3=word(buffer[7],buffer[8]);
      Cdata=word(buffer[9],buffer[10]);

    }
  }
}

And on the Slave Sender :

void I2Csend()
{    

  P[0]=analogRead(A0);
  P[1]=analogRead(A1);
  P[2]=analogRead(A2);
  Cdata=analogRead(A3);

  if(k<2) k++;
  else k=0;
  buffer[0]=highByte(T[k]);
  buffer[1]=lowByte(T[k]);
  buffer[2]=k;
  buffer[3]=highByte(P[0]);
  buffer[4]=lowByte(P[0]);
  buffer[5]=highByte(P[1]);
  buffer[6]=lowByte(P[1]);
  buffer[7]=highByte(P[2]);
  buffer[8]=lowByte(P[2]);
  buffer[9]=highByte(Cdata);
  buffer[10]=lowByte(Cdata);
  Wire.write(buffer, 11);

}

But now it outputs the right values once and then only -1(11 times) and then the right values and then only -1(11 times)

I have no idea why!!!

So I tried different possibilities and found out that if I put an additional buffer[11]=0 and wire.write(buffer,12) but still only request 11 (from the Arduino Master Receiver), it works perfectly.

So I had it working like this BUT WHY?!!

Thanks for the input!

Marc

Hi Marc

   Wire.requestFrom(0x47, 11);

    while(Wire.available()>0)
    {
      
      for(z=0; z<10; z++)
      {
        buffer[z]=Wire.read();
      }

Looks like you are requesting 11 bytes but only reading 10 of them. So after the first time the for loop executes, there will be one byte left in the Wire receive buffer. The while condition will evaluate as true, so the for loop will execute again but most of the reads will fail.

EDIT added …

As well as fixing the number of bytes, also consider adding some error handling:

   Wire.requestFrom(0x47, 10);

    if (Wire.available() == 10)
    {
      for(z = 0; z < 10; z++)
      {
        buffer[z] = Wire.read();
      }
    }
    else
    {
      // Handle error condition: incorrect number of bytes received
    }

Regards

Ray

That can be shorter :stuck_out_tongue:

    int n = Wire.requestFrom(0x47, 10);
    if ( n == 10)
    {
      for(z = 0; z < 10; z++)
      {
        buffer[z] = Wire.read();
      }
    }
    else
    {
      // Handle error condition: incorrect number of bytes received
    }

The data is 11 bytes, not 10, so:

  Wire.requestFrom(0x47, 11);

   if (Wire.available() == 11) {
     for(z = 0; z < 11; z++)
       buffer[z] = Wire.read();
   }