Sunday, 29 June 2014

Raspberry Pi - ADXL345 Accelerometer & Python


A little while ago I got my hands on a Adafuit ADXL345 (a triple axis accelerometer) from pimoroni, you can also get them from Amazon (US, UK) if that's easier, and I finally got around to setting it up.

Pimoroni also provide a really useful python module to interacting with the ADXL345 which you can get from github - https://github.com/pimoroni/adxl345-python.

Connecting it up
Wiring up the accelerometer is pretty easy, there are only 4 connections:

Raspberry Pi -> ADXL345:
  • GND - GND 
  • 3V - 3V3
  • SDA - SDA
  • SCL - SCL

Configure your Pi
The ADXL345 supports both I2C and SPI connections, I used I2C, which requires some configuration on the Pi:

Add the I2C modules to the Pi's configuration:
sudo nano /etc/modules
add the following lines:
i2c-bcm2708
i2c-dev
Remove I2C from the blacklist:
sudo nano /etc/modprobe.d/raspi-blacklist.conf
comment out:
blacklist i2c-bcm2708
so its:
#blacklist i2c-bcm2708
Reboot to make the changes:
sudo shutdown -r now
Install Software
You will need to install some software:
sudo apt-get install python-smbus i2c-tools git-core
Test ADXL345
You can check that your ADXL345 is found on the I2C bus, by running:
sudo i2cdetect -y 1
You should see a device at address 53


Download the ADXL345 pimoroni python library from github:
git clone https://github.com/pimoroni/adxl345-python
Run the example code and test it is working:
cd adxl345-python
sudo python example.py
You should see the G readings from the ADXL345.


If you get 0.000G for all axis then something probably isn't set-up correctly.

Writing your own python program
The adxl345-python project from pimoroni contains a python module for reading data from the ADXL345 perhaps not unsurprisingly called "adxl345.py", inside there is a class called "ADXL345" which is how you to interact with the accelerometer

The program below imports the module, instantiates an ADXL345 object and reads values from the accelerometer as g-forces.
#import the adxl345 module
import adxl345

#create ADXL345 object
accel = adxl345.ADXL345()

#get axes as g
axes = accel.getAxes(True)
# to get axes as ms^2 use
#axes = accel.getAxes(False)

#put the axes into variables
x = axes['x']
y = axes['y']
z = axes['z']

#print axes
print x
print y
print z
Change sensitivity
You can change the sensitivity of the ADXL345 by using the .setRange() method of the class.

The default range is 2g which means that the maximum G the ADXL345 can measure is 2.048, but at a high degree of sensitivity, you can change it so the maximum is 2g, 4g, 8g or 16g but with a lower level of sensitivity using:
accel.setRange(adxl345.RANGE_2G)
accel.setRange(adxl345.RANGE_4G)
accel.setRange(adxl345.RANGE_8G)
accel.setRange(adxl345.RANGE_16G)
Its a great accelerometer and really easy to use in your python projects.

28 comments:

  1. Hi,

    It doesn't work with my RPi Model B Rev 2. I tried all that you said in your post. I don't know why I can't read any address. I connected all wires in the correct gpio pin, so I don't understand (I have two Rpi, same model...same results)

    Can you help me?

    ReplyDelete
    Replies
    1. Hi,

      Does the module show up when you run sudo i2cdetect -y 1 ? Or are any errors shown?

      If there are no errors and it doesn't show up I suspect its either not wired up properly or doesn't work.

      Mart

      p.s. I wrote this setup based on a model b rev 2.

      Delete
  2. Hi,

    there is any error when I run sudo i2cdetect -y 1 .. I'll try with other sensor.

    Regards,

    ReplyDelete
  3. When you say "SDL", I assume you mean "SCL"?

    ReplyDelete
    Replies
    1. I do indeed, a slip of the keyboard. Post updated!

      Delete
  4. Could i connect multiple Accelerometers?

    ReplyDelete
    Replies
    1. yes sure its how you connect SD0 you can change the i2c bus adress
      with a other adress you can read a other device

      http://wiki.analog.com/resources/tools-software/linux-drivers/input-misc/adxl345

      Configuration

      Selectable ADXL34X I2C Device Address:
      SDO I2C Address
      0 0x53
      1 0x1D

      Delete
  5. I would like to use the accelerometer data to set off a buzzer if a car is tilted 15 degrees to horizontal. Any ideas how to do this in Python. I'm very new to this , but I'm trying hard to introduce the raspberry Pi into our high school curriculum. Any help much appreciated!!

    ReplyDelete
    Replies
    1. That doesnt sound too complicated. You will need to work out the maths to convert g to 3d angles (http://lmgtfy.com/?q=accelerometer+calculate+angle). Then an if statement and turn on a GPIO pin which is connected to a buzzer.

      Delete
  6. Why does it show ~1g on the Z axis while sitting stationary?

    In order to get an accurate reading while vibrating, should the ~1g be subtracted?

    Great write up, it's super appreciated!

    ReplyDelete
    Replies
    1. Right if I understand you correctly... It measures 1g on the Z axis (which is presumably down for you), because the earth is pulling it down to the tune of 1g!

      Delete
  7. Hi,
    Thank you for your tutorial, it is really helpful. It works perfectly on Python 2 (Idle) but I have problems on Python 3 (Idle3). Error message: "ImportError: No module named smbus". Any idea what to do?

    ReplyDelete
    Replies
    1. python-smbus is installed (newest version).

      Delete
  8. Hi
    I got the wrong values. While not woving the acceleration is much greater then the acceleration of the earth. I ve got two sensors and both of them messure nearly the same wrong values. Cann you say me what to do?
    Thanks for your help

    ReplyDelete
    Replies
    1. For instance:
      root@raspberry: /DatenManuel/ADXL345/adxl345-python# python example.py
      ADXL345 on address 0x53:
      x=-0.640G
      y=-1.092G
      z=2.044G

      Do you have any idea how to fix that?

      Delete
    2. And that is when the accelerometer is flat on a surface not being moved? If so, no idea. Although if you minus out all the values you do get to about 1g. I wonder if it just needs calibrating, I never had to do mine but adafruit have a tutorial https://learn.adafruit.com/adxl345-digital-accelerometer/programming

      Delete
    3. Those are not invalid numbers. Could you describe us how is the accelerometer displayed over your test surface? May be necessary to calibrate the sensor in order to correct the baseline (removing the offset)

      Where did you buy your sensors?

      Regards

      Delete
  9. News: z axis seems to be stuck on z=2.044G even if I move the sensor. x and y are changing the values.

    ReplyDelete
  10. root@raspberrypi:/DatenManuel/ADXL345/adxl345-python# sudo python myexample.py
    ADXL345 on address 0x53:
    x = -0.652G
    y = -1.100G
    z = 2.044G
    x = -0.652G
    y = -1.100G
    z = 2.044G
    x = -0.640G
    y = -1.108G
    z = 2.044G
    x = -0.652G
    y = -1.104G
    z = 2.044G
    x = -0.644G
    y = -1.100G
    z = 2.044G
    x = -0.644G
    y = -1.104G
    z = 2.044G
    x = -0.648G
    y = -1.108G
    z = 2.044G
    x = -0.620G
    y = -1.456G
    z = 2.044G
    x = -0.680G
    y = -0.676G
    z = 2.044G
    x = -1.908G
    y = -1.508G
    z = 2.044G

    ReplyDelete
    Replies
    1. Is it the ADXL345 accelerometer

      Delete
    2. well of corse... i just wrote myexample.py with a Loop to take several messurements instead of one ... i don't now what to do now....

      Delete
    3. Perhaps try calibrating the accelerometer. Other than that, I would be tempted to start again. Reimage, reconnect, recode.

      Delete
    4. How to calibrate? I don't understand how to manage to adapt the arduino tutorial to raspberry

      Delete
  11. Hi, i follow the step exactly as you said.
    I'm using Raspberry Pi 2, and the address I've got is !E instead...

    When i run the python code, I get only one reading no matter how i move my accelerometer (ADXL345)

    ADXL345 on address 0x1e:
    x = 20.480G
    y = 120.840G
    z = 0.276G

    mind helping??

    ReplyDelete
    Replies
    1. Those values are definitely not right. are you sure these arent the readings from a different device? Im pretty sure this isnt from the accelerometer.

      Delete
  12. I record the time that I sample data. It appears that regardless of the value of BW_rate I enter, my rate hovers around 800 Hz. I have added a print statement, and the value that I expect gets passed into .setBandwidthRate. Any ideas as to what might be amiss? (I am actually using the SainSmart GY-85 board, a combo Accelerometer/compass/gyro, but it does use the ADXL345, and the address appears good and I am certainly getting good data from it.

    ReplyDelete
    Replies
    1. Sorry I dont have anything to add..

      Delete