Still mucking around with the Raspberry Pi, I wanted to dip my toes into using the I2C bus to interface with sensors. The sensor I'm going to use to demonstrate here is the ADXL345 accelerometer from Analog Devices. It actually supports I2C or SPI but the RPi only allows 1 SPI device so I wanted to use I2C instead.
To enable I2C on the Raspberry Pi I followed this tutorial.
Hooking up the sensor is simple enough. Power (3.3v), ground, and the two I2C connections: SDA (data) and SCL (clock). However in addition to these 4 connections the sensor needs 2 additional connections. The pin labeled CS goes to power (3.3v) and the pin labeled SDO goes to ground. This is needed to put the sensor into I2C mode instead of SPI.
Now comes the fun part, interfacing with the sensor. For this we will refer to data sheet available here. Looking at the register chart, there are a few things we need to set up before we can actually get data from the sensor.
First we enable i2c; set the address of the sensor, the ADXL345 has address 0x53; and set the clock divider, 2500 gives use a clock frequency of 100kHz which is standard for I2C.
Next we need to write to the POWER_CTL register located at 0x2D. We write 0x08 to it which enables the measurment mode on the ADXL345. Disabling the measurment bit would put the sensor into standby mode. Standby mode powers up the sensor but won't take measurements. This would be useful in a situation where power conservation was an issue.
Finally we must tell the sensor what type of data we want. Writing 0x0B to the DATA_FORMAT register located at 0x31 means we want to use the full resolution of 13-bits with a g range of +/-16g. There are several different ranges to choose from (2, 4, 8, 16) but choosing anything else limits the number of bits to 10 instead of 13. And more bits is always better.
Check out the register descriptions in the data sheet and you will get a much better understanding of what I just described above.
Now that all the initialization is out of the way it's time to actually get from readings from the sensor. The readings are stored in 6 bytes starting at 0x32. There are 2 bytes for each axis. It looks something like this:
DATAX0 - DATAX1 - DATAY0 - DATAY1 - DATAZ0 - DATAZ1
Where DATAx0 has the least significant bits and DATAx1 has the most significant bits. It's important to do a single read of all the registers to minimize any change in the data that might happen between reads.
So combine the bytes and we've got a result from the sensor. Since we're using full resolution mode we will get a range of -4096 to 4095 for each axis and dividing the result by 256 gives the G value. If the sensor is lying flat on a table it should read 1G in the z-axis due to gravity.
And that's pretty much it. Now you can interface with I2C devices from your Raspberry Pi! I wrote a simple program with will flash an LED whenever there is more than a G in either X-axis direction that I hope illustrates what I've explained here.
(I've since stopped paying for a server so the file is no longer available. Email me if you are interested to see the code)