-1

I've been trying to use a Raspberry Pi 3 B+ to get data from an accelerometer, namely an ADXL 357, via I2C but the problem is that the data rate is about 200 Hz or even less. I tried to set the accelerometer to high speed mode and it didn't help. I also tried to change the baudrate in the Rasberry but I wouldn't go higher than 2.000.000 or something similar.

import smbus
import time
import csv
import RPi.GPIO as GPIO
from datetime import datetime



i2c_ch=1

i2c_adress = 0x1D

acc_range = 0x81 # 0x01->8g, 0x02->20g, 0x03->40g

# I'm putting 0x81 rather than 0x01 to set it to high speed mode rather than fast mode

bus = smbus.SMBus(i2c_ch)



#val = bus.read_i2c_block_data(i2c_adress,reg_range,3)
def configure_raspberry():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(8,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(18,GPIO.OUT)

def configure_adxl() :

    #reset
    bus.write_byte_data(i2c_adress,0x2f,0x52)

    #set filter

    bus.write_byte_data(i2c_adress,0x28,0x01)

    # set i2c speed to normal and acceleration range
    bus.write_byte_data(i2c_adress,0x2c,acc_range)

    #set in measurement mode (not standby)
    bus.write_byte_data(i2c_adress,0x2d,0x00)

def get_temperature() :

    temp1 = bus.read_byte_data(i2c_adress,0x06)
    temp2 = bus.read_byte_data(i2c_adress,0x07)
    temp = (temp1 << 8) | temp2
    temp = (float)(1852 - temp)/9.05 + 25
    return temp

def get_x_accel() :
    x1 = bus.read_byte_data(i2c_adress,0x08)
    x2 = bus.read_byte_data(i2c_adress,0x09)
    x3 = bus.read_byte_data(i2c_adress,0x0A)
    x = (x1 << 12) | (x2 << 4) | (x3 >> 4)
    if(x & 0x80000) :
        x = (x & 0x7ffff) - 0x80000
    return x

def get_y_accel() :
    y1 = bus.read_byte_data(i2c_adress,0x0B)
    y2 = bus.read_byte_data(i2c_adress,0x0C)
    y3 = bus.read_byte_data(i2c_adress,0x0D)
    y = (y1 << 12) | (y2 << 4) | (y3 >> 4)
    if(y & 0x80000) :
        y = (y & 0x7ffff) - 0x80000
    return y

def get_z_accel() :
    z1 = bus.read_byte_data(i2c_adress,0x0E)
    z2 = bus.read_byte_data(i2c_adress,0x0F)
    z3 = bus.read_byte_data(i2c_adress,0x8)
    z = (z1 << 12) | (z2 << 4) | (z3 >> 4)
    if(z & 0x80000) :
        z = (z & 0x7ffff) - 0x80000
    return z

def convert_in_g(accel) :
    if(acc_range == 0x01) :
        accel = (float)(accel)/0x7ffff*8
    if(acc_range == 0x02) :
        accel = (float)(accel)/0x7ffff*20
    if(acc_range == 0x03) :
        accel = (float)(accel)/0x7ffff*40
    return accel



configure_adxl()
configure_raspberry()

while True :
        date = datetime.now()

        timestamp = datetime.timestamp(date)
        dateStr = date.strftime("%d-%b-%Y (%H:%M:%S.%f)")

        name = dateStr +'.csv'


        if GPIO.input(8) == GPIO.HIGH :
            f = open(name,'a',newline = "")
            c = csv.writer(f)

            time.sleep(0.08)
            while GPIO.input(8) == GPIO.HIGH :
                GPIO.output(18,GPIO.HIGH)
                temp = get_temperature()
                print("temperature uncalibrated : ",temp)
                print("_________________________________________________________")
                print("\n")
                x = get_x_accel()
                print("x raw acceleration : ",x)
                x = convert_in_g(x)
                print("x acceleration in g : ",x)
                print("\n")
                y = get_y_accel()
                print("y raw acceleration : ",y)
                y = convert_in_g(y)
                print("y acceleration in g : ",y)
                print("\n")
                z = get_z_accel()
                print("z raw acceleration : ",z)
                z = convert_in_g(z)
                print("z acceleration in g : ",z)
                print("\n\n\n\n")
                date2 = datetime.now()

                timestamp = datetime.timestamp(date2)
                c.writerow([timestamp,x,y,z])
            f.close()
            GPIO.output(18,GPIO.LOW)
Fred
  • 4,592
  • 19
  • 29

1 Answers1

0

Question

I can only get ADXL357 data rate 200Hz. Can I do better?

Datasheet Spec

(1) ODR (Output Data Rate) is 4kHz. (Table 2, Page 4)

(2) I2C speed standard rate 100kHz, max 3.4MHz. (Page 26)

Reason

Rpi3B+, because of a design bug, has a I2C flat rate of ridiculously low standard 100kHz. Yes, you cannot adjust I2C speed for Rpi3B+ stretch.

IT IS A BUG.

The official instruction tells you how to set to speed to 400kHz or higher. I have checked with scope that it does not work. I have also read about this bug in other forums, as reported by very experienced users.

Solution

Upgrade to Rpi4B, then you can set higher I2C speed, therefore higher ADXL357 output data rate.

References

(1) ADXL356/ADXL357 3 Axis MEMS Accelerometers Data Sheet - Analog Devices

https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL356-357.pdf

(2) ADXL345 3-Axis, Digital Accelerometer Data Sheet - Analog Devices

https://www.analog.com/media/en/technical-documentation/data-sheets/ADXL345.pdf

(3) Adafruit 9-DOF accelerometer/magnetometer/gyroscope sensor Forum Discussion

Adafruit 9-DOF or other accelerometer/magnetometer/gyroscope sensor for Raspberry PI 2/3 with Windows IoT

(4) Rpi4B Raspbian 10 buster circuit-python-blinka installation problem (BNO0955 9DOF) Forum Discussion

Rpi4B Raspbian 10 buster circuit-python-blinka installation problem

(5) SparkFun Triple Axis Accelerometer Breakout - ADXL345 $19

https://www.sparkfun.com/products/9836

(6) SparkFun ADXL345 Hookup Guide

https://learn.sparkfun.com/tutorials/adxl345-hookup-guide

(7) SparkFun Accelerometer, Gyro and IMU Buying Guide

https://www.sparkfun.com/pages/accel_gyro_guide

(8) SparkFun Accelerometers Catalog

https://www.sparkfun.com/categories/80

AdaFruit ADXL345 - Triple-Axis Accelerometer (+-2g/4g/8g/16g) w/ I2C/SPI - $18

https://www.adafruit.com/product/1231

(10) AdaFruit ADXL345 Digital Accelerometer Learning Notes

https://learn.adafruit.com/adxl345-digital-accelerometer/overview

(11) AdaFruit I2C Addresses List

https://learn.adafruit.com/i2c-addresses/the-list

.END

tlfong01
  • 4,847
  • 3
  • 12
  • 24