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.
#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?
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
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?
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.