Reading SDA/SCL data using Wire

Hi, I've just started a quadcopter project and I've recently purchased an Arduino that I hope to control it with.

I've also recently bought a 6DOF sensor and have got it to work with the FreeIMU library, but just using someone elses code isn't very appealing to me and doesn't teach me much.

I'm hoping to use MATLAB to look at the data I get and transform it and such, which brings me to the point, I'm having issues capturing the data from the SDA/SCL.

The code i'm using is from here Live Fast - Code Young: ADXL345 accelerometer breakout board + Arduino and Processing

#include <Wire.h>

#define DEVICE (0x53)    //ADXL345 device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  
  //Turning on the ADXL345
  Wire.write(DEVICE, 0x2D, 0);      
  Wire.write(DEVICE, 0x2D, 16);
  Wire.write(DEVICE, 0x2D, 8);
}

void loop()
{
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345
  int x, y, z;
  
  Wire.requestFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
  
   //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
   //thus we are converting both bytes in to one int
  x = (((int)buff[1]) << 8) | buff[0];   
  y = (((int)buff[3])<< 8) | buff[2];
  z = (((int)buff[5]) << 8) | buff[4];
  
  //we send the x y z values as a string to the serial port
  sprintf(str, "%d %d %d", x, y, z);  
  Serial.write(str);
  Serial.write(byte(10));
  
  //It appears that delay is needed in order not to clog the port
  delay(15);
}

I've 'updated' it to use Serial.write(byte(10)) instead of what appears to be the old syntax, but I still seem to be getting an error, which I believe is due to Wire.write and Wire.requestFrom; what is the correct syntax for this?

Thanks :slight_smile:

Huh?

  //Turning on the ADXL345
  Wire.write(DEVICE, 0x2D, 0);      
  Wire.write(DEVICE, 0x2D, 16);
  Wire.write(DEVICE, 0x2D, 8);

There should be a beginTransmission and endTransmission there. Plus you don't put the device number in the Wire.write.

#define DEVICE (0x53)    //ADXL345 device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

Why do the values contain parentheses?

I've 'updated' it to use Serial.write(byte(10)) instead of what appears to be the old syntax

As opposed to the recommended

Serial.write((byte)10);

Why? Are you that scared of casts?

but I still seem to be getting an error, which I believe is due to Wire.write and Wire.requestFrom

Share them. we'll help you straighten out the issues. Keep them to yourself. you are on your own.

On the linked page he had:

void writeTo(int device, byte address, byte val) {
    Wire.beginTransmission(device); //start transmission to device 
    Wire.send(address);        // send register address
    Wire.send(val);        // send value to write
    Wire.endTransmission(); //end transmission
 }

Did you decide the throw writeTo out the window?

Looks like you did something similar to readFrom:

void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.send(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.beginTransmission(device); //start transmission to device (initiate again)
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.receive(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}

I've 'updated' it ...

You have introduced a lot of errors. You can't just replace a function he had (readFrom) with something completely different without a good reason.

Besides, the original code is wrong:

 Wire.beginTransmission(device); //start transmission to device (initiate again)
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.receive(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission

You don't put Wire.beginTransmission and Wire.endTransmission around Wire.requestFrom. So that should just read:

  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.receive(); // receive a byte
    i++;
  }

To summarize, this compiles. Whether it works or not I'll let you experiment with:

#include <Wire.h>

#define DEVICE (0x53)    //ADXL345 device address
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)

byte buff[TO_READ] ;    //6 bytes buffer for saving data read from the device
char str[512];                      //string buffer to transform data before sending it to the serial port

void writeTo(int device, byte address, byte val) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        // send register address
  Wire.write(val);        // send value to write
  Wire.endTransmission(); //end transmission
  } // end of writeTo
 
void readFrom(int device, byte address, int num, byte buff[]) 
  {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
    { 
    buff[i] = Wire.read(); // receive a byte
    i++;
    }
  }  // end of readFrom

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  
  //Turning on the ADXL345
  writeTo(DEVICE, 0x2D, 0);      
  writeTo(DEVICE, 0x2D, 16);
  writeTo(DEVICE, 0x2D, 8);
}  // end of setup

void loop()
{
  int regAddress = 0x32;    //first axis-acceleration-data register on the ADXL345
  int x, y, z;
  
  readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
  
   //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
   //thus we are converting both bytes in to one int
  x = (((int)buff[1]) << 8) | buff[0];   
  y = (((int)buff[3])<< 8) | buff[2];
  z = (((int)buff[5]) << 8) | buff[4];
  
  //we send the x y z values as a string to the serial port
  sprintf(str, "%d %d %d", x, y, z);  
  Serial.write(str);
  Serial.write(byte(10));
  
  //It appears that delay is needed in order not to clog the port
  delay(15);
}  // end of loop

I love the comment "It appears that delay is needed in order not to clog the port" ... nothing worse than clogged ports!

Ok, I meant that the function I updated was the Serial.print(10, BYTE) to Serial.write(byte(10)) because apparently the .print was outdated.

I didn't understand before you pointed it out that the code on that website defines the functions writeTo and readFrom. It's starting to make a bit more sense now.

Thank you for the summary Nick, that compiles for me :slight_smile:

Sorry, I'm a bit of a noob with programming in this language, the last few days have been quite a steep learning curve.

Out of interest, is this a fairly efficient way to request information from the device?

No is not. Pretty much anything done with Wire is slow. Try this: Google Code Archive - Long-term storage for Google Code Project Hosting.

Whitworth:
Out of interest, is this a fairly efficient way to request information from the device?

Well, what do you mean by "efficient"? Normal I2C takes around 75 uS per byte, although it is more efficient to do "batches" because sending the address takes the first byte.

If you add a line after Wire.begin:

Wire.begin ();
TWBR = 12;

... then one byte takes around 28 uS. That's not too shabby. It would depend on whether the target device supported it.