The first thing to understand is that I2C is a completely 8-bit bus protocol, which means that all addresses and all data are 8-bit quantities (0-255). The bus consists of a single "master" with up to 112 unique "slave" devices. The limit of 112 is due to the fact that a device address is actually a 7-bit quantity (more on this later), and 16 addresses are reserved. Multiple masters are apparently possible, but aren't relevant for this project. Slave devices can't talk to other slave devices. Off-the-shelf devices, like the three on the SEN-10724 board, have pre-assigned addresses managed by a central authority.
Devices have a 7-bit address. This 7-bit address is stored in the 7 MSB (most significant bits) of an 8-bit quantity when sequenced on the bus, with the least significant bit indicating whether the operation is a read or a write (1 or set being "read"). As an example, the HMC5883L datasheet lists 8-bit addresses 0x3D for read, and 0x3C for write. Convert these to binary and you'll find a 7-bit address of 0x1E followed by a binary 1 for read or 0 for write. Some manufacturers will list only a 7-bit address in their data sheet, some will list 8-bit addresses, some will do both.
The datasheet for the Analog Devices ADXL345 lists both - 0x1D is the 7-bit address, which results in 0x3A for writes and 0x3B for reads. However, it also supports an alternate addressing of 0x53/0xA6/0xA7 if pin 12 is tied to ground. The schematic for the sparkfun board indicates that pin 12 is indeed tied to ground, so let's assume that we're going to be using alternate addressing for that device.
Each I2C device will also have a number of registers that are readable and/or writable. Table 16 on page 14 of the ADXL345 datasheet lists this device's register map. For this project, we're most interested in registers 0x32-0x37. If you look at the table, you'll see how manufacturers design for 16-bit quantities, which is (at least in this case and in the case of the HMC5883L) to have adjacent 8-bit registers containing the most significant and least significant bytes of a 16-bit quantity.
Let's start with the X axis on the accelerometer, which according to the board's silkscreen is the side-to-side direction (along the short edge of the board). The following Arduino sketch implements a simple program that prints out the X axis acceleration once a second.
#include <Wire.h> // Wire library uses 7-bit addresses and automatically // sets the r/w bit static const uint8_t ADXL345 = 0x53; static const uint8_t DATAX0 = 0x32; void setup() { Wire.begin(); Serial.begin(9600); } void loop() { // Put the read address on the bus Wire.beginTransmission(ADXL345); Wire.send(DATAX0); Wire.endTransmission(); // Request data starting with the X register Wire.beginTransmission(ADXL345); // 2 bytes gets us the LSB and MSB of the X data Wire.requestFrom(ADXL345, (uint8_t)2); // store the data in a signed integer quantity int16_t x; // pointer to use to store the data byte *p = (byte*)&x; // wait for 2 bytes to be available while (Wire.available() < 2) {} *p = Wire.receive(); p++; // advance the pointer to the next 8 bits *p = Wire.receive(); Wire.endTransmission(); Serial.println(x); // finally, print the quantity delay(1000); // delay a bit to avoid flooding }
If you upload this sketch to your Arduino, with the IMU connected as described in the earlier post, you'll probably get a sequence of zeroes in the serial monitor. If, for example, you tried to change the address in the above code to the primary (0x1D), you probably wouldn't see anything at all. So why is it only showing zeroes, even if I shake the heck out of the board? My guess is that the device doesn't start up in a mode where continuous measurements are taken (which is how the HMC5883L operates), and that to get these measurements, other registers must be manipulated...
To be continued...
No comments:
Post a Comment