Arduino 1.0 with WIRE (I2C) help

Hi,

I can’t seem to get the pre-arduino 1.0 code below to work in 1.0 - just returns a value of -1.00. Works fine in Arduino 22 so it is of course user error - any eagle eyes spot my blunder?.. I’m slowly learning Arduino 1.0, wondering if any good tutorials which cover the changes have been published online?

 float value;
 int valuebuffer;
 const int data_bytes = 7;
 byte data_buffer [data_bytes];

  Wire.beginTransmission(0x31); //also tried Wire.beginTransmission((byte)0x31);  with no joy
  Wire.write(0x52); //also tried Wire.write((byte)0x52); with no joy
  Wire.endTransmission();
  
  delay(100);
  Wire.requestFrom(0x31, data_bytes);
  delay(100);
  while (!Wire.available ());
  for (int i = 0; i < data_bytes; ++i)
  {data_buffer [i] = Wire.read();
  delay(100);
  }
  
  for (int i=0;i<7;i++)
  {
   byte c = data_buffer [i];
   if (i==1) valuebuffer = c;
   if (i==2) valuebuffer = (co2buffer << 8) | c;
  }
  value = valuebuffer;

That code won't even compile in Arduino 1.0 -- the Wire.send function is now named Wire.write; and the same goes for Wire.receive / Wire.read

Hi Aeturnalus,

I think I have picked up that change - the code compiles fine so it must be something else?

You assume that the bytes will be available when they might not be: though you do busy-wait until the first byte has come in, for subsequent bytes, you just delay(100), which does not guarantee that the data has been transmitted. Remember that I2C allows slaves to clock stretch and thus not transmit data until later.

Hi Aeturnalus,

Thanks for the info, the problem I am having is that this code works perfectly in OLD Arduino but not in Arduino 1.0 - there must be something subtle I have missed in the conversion I think. Cheers.

  delay(100);   // <-- don't need this
  Wire.requestFrom(0x31, data_bytes);
  delay(100);   // <-- don't need this
  while (!Wire.available ());   // <-- don't need this - after the requestFrom 
               // you either have data or you don't
  for (int i = 0; i < data_bytes; ++i)  // <-- wire.requestFrom returns the number of bytes you got

Hi Nick,

Thanks for the info, much appreciated. Sorry - you are speaking with a bit of a noob here.....

I have tried a more conventional approach to getting the data in the past without success.... would you be able to show me how I use your method please?

Cheers :-)

Things have changed in version 1.0 to be sure, but this code is dodgy at best:

while (!Wire.available ());
  for (int i = 0; i < data_bytes; ++i)
  {data_buffer [i] = Wire.read();
  delay(100);
  }

Wire.available() returns true if you have one byte but you are reading 7. If they are not there you will get -1.

I suggest you restructure a bit. For example (but untested):

  Wire.beginTransmission(0x31); 
  Wire.write(0x52); 
  if (Wire.endTransmission() != 0)
    return;  // could not send
  
  if (Wire.requestFrom(0x31, data_bytes) != data_bytes)
    return;  // didn't get full response

  for (int i = 0; i < data_bytes; ++i)
    {
    data_buffer [i] = Wire.read();
    }

I have examples here:

http://gammon.com.au/i2c

If you want more help post your whole sketch and not just snippets.

Cheers Nick - still no joy… If I could get the original code working in 1.0 I would then be able to refine the code to a more elegant solution :slight_smile:

The full code is:

#include <Wire.h>
#define address 0x31
#define delayC 3000
#define baudrate 57600
char val_str[10];
char sam_str[10];
int sam;
int val;
const int data_bytes = 7;
byte data_buffer [data_bytes];

void setup()
{
  Wire.begin();
  Serial.begin(baudrate);
}

void loop()
{ 
  Wire.beginTransmission(address);
  Wire.write('R');
  Wire.endTransmission();
  
  delay(100);
  Wire.requestFrom(address, data_bytes);
  while (!Wire.available ());
  for (int i = 0; i < data_bytes; ++i)
  data_buffer [i] = Wire.read();
  
  for (int i=0;i<7;i++)
  {
    byte c = data_buffer [i];
    if (i==1) val = c;
    if (i==2) val = (val << 8) | c;
  }
  
  Serial.print(itoa(val,val_str,10));
  Serial.print(" ");
  Serial.println("ppm");
  sam = (sam++);
  Serial.println(itoa(sam,sam_str,10));
  delay(delayC);
}

OK, I gather this is an I2C master. To test I would need to see the code for the slave (or know what device it is). It could be a timing issue. I know they renamed Wire.receive to Wire.read but I'm not sure exactly what underlying functionality changed as well.