I’m using a raspberry pi to read accelerometer/gyroscope/temperature information from an ICM-20948 that I got in the sparkfun sensor kit (https://www.sparkfun.com/products/16156). I have the IMU wired up via the qwiic cable to the SparkFun Qwiic pHAT v2.0 for Raspberry Pi (https://www.sparkfun.com/products/15945).
I wrote a small python script to pull the values for me by using Sparkfun’s arduino library as a reference (https://github.com/sparkfun/SparkFun_IC … inoLibrary).
First I moved the ICM-20948 out of sleep mode by writing to PWR_MGMT_1:
i2cset -y 1 0x69 0x06 0x01
And verified by running:
pi@raspberrypi:~ $ i2cget -y 1 0x69 0x6
0x01
Next I ran my python script:
!/usr/bin/python3
import os
import subprocess as sub
class Icm20948:
def __init__(self, bout, fss_g, fss_a):
self.acc_x_raw = int.from_bytes(bout[0:1],byteorder='big', signed=True)
self.acc_y_raw = int.from_bytes(bout[2:3],byteorder='big', signed=True)
self.acc_z_raw = int.from_bytes(bout[4:5],byteorder='big', signed=True)
self.gyr_x_raw = int.from_bytes(bout[6:7],byteorder='big', signed=True)
self.gyr_y_raw = int.from_bytes(bout[8:9],byteorder='big', signed=True)
self.gyr_z_raw = int.from_bytes(bout[10:11],byteorder='big', signed=True)
self.temp_raw = (bout[12] << 8) | (bout[13] & 0xff)
self.fss_a = ( fss_a[0] >> 1 ) & 0x3
self.fss_g = ( fss_g[0] >> 1 ) & 0x3
self.acc_x = 0
self.acc_y = 0
self.acc_z = 0
self.gyr_x = 0
self.gyr_y = 0
self.gyr_z = 0
self.temp_c = 0
self.temp_f = 0
self.interpret()
def interpret(self):
if self.fss_a == 0:
self.acc_x = self.acc_x_raw / (16.384)
self.acc_y = self.acc_y_raw / (16.384)
self.acc_z = self.acc_z_raw / (16.384)
if self.fss_g == 0:
self.gyr_x = self.gyr_x_raw / 131
self.gyr_y = self.gyr_y_raw / 131
self.gyr_z = self.gyr_z_raw / 131
self.temp_c = ( (self.temp_raw - 21) / 333.87 ) + 21
self.temp_f = self.temp_c*(9.0/5.0) + 32
def __str__(self):
s = ""
s += "Acc: ({0:7.3f}, {1:7.3f}, {2:7.3f} )".format(self.acc_x, self.acc_y, self.acc_z)
s += ", "
s += "Gyr: ({0:7.3f}, {1:7.3f}, {2:7.3f} )".format(self.gyr_x, self.gyr_y, self.gyr_z)
s += ", "
s += "Temp: {0:7.3f} degC, {1:7.3f} degF".format(self.temp_c, self.temp_f)
return s
i2c_cmd = ['i2ctransfer', '-y', '1', 'w1@0x69', '0x2d', 'r14@0x69']
compProc = sub.run(i2c_cmd, capture_output=True, universal_newlines=True)
out_bytes = [int(x,0) for x in compProc.stdout.split()]
i2c_fss_g_cmd = ['i2ctransfer', '-y', '1', 'w1@0x69', '0x1', 'r1@0x69']
compProc_fss_g = sub.run(i2c_fss_g_cmd, capture_output=True, universal_newlines=True)
fss_g_bytes = [int(x,0) for x in compProc_fss_g.stdout.split()]
i2c_fss_a_cmd = ['i2ctransfer', '-y', '1', 'w1@0x69', '0x14', 'r1@0x69']
compProc_fss_a = sub.run(i2c_fss_a_cmd, capture_output=True, universal_newlines=True)
fss_a_bytes = [int(x,0) for x in compProc_fss_a.stdout.split()]
icm = Icm20948(out_bytes, fss_g_bytes, fss_a_bytes)
print(icm)
The values I get as output are as follows (with board lying flat, sensor face up):
Acc: ( -0.122, -0.122, 3.967 ), Gyr: ( 0.000, 0.000, -0.008 ), Temp: 28.078 degC, 82.540 degF
I’m confused by the 3.967 value in the z direction of the accelerometer. I expected 1g, but for some reason I’m seeing almost 4g. 16.384 is the correct sensitivity with full scale value of zero according to the spec. I considered dividing the raw value by 16.384*4, but I’m concerned that I’ll end up measuring 4g units instead of 1g units… Subtracting 4 from the z axis doesn’t seem to make sense because when I turn the sensor on it’s side (any side), the corresponding y or x value also reports almost 4g. Am I doing something wrong with the calculation or setup for this measurement?
Also, while the gyroscope values look normal in my example given that the gyroscope is at rest, the gyroscope is giving me subzero values for dps even when I quickly rotate the board multiple degrees per second with my hand.
Any help/advise would be appreciated in understanding what I might be missing.