Product : https://www.adafruit.com/product/2020
datasheet: https://cdn-shop.adafruit.com/datasheets/LSM9DS0.pdf
I'm student and it's the first time for me to use I2c bus. I am trying to read the basic gyroscope value. I wasted a part of my life to understand how the I2c work. But after reading the datasheet and made my own script. My values are stuck there. Nothing move and I don't know why.
Rotation in X-Axis : -1087
Rotation in Y-Axis : -28797
Rotation in Z-Axis : -15032
Here is my script. Someone can help me to solve it? I'm working with a beagle bone black.
import smbus
import time
bus = smbus.SMBus(1)
# 0x6b adress (found with i2cdetect), 0x20 register (found with the data sheet), CTRL_REG1_G(20h)
bus.write_byte_data(0x6b, 0x20, 0x0F)
bus.write_byte_data(0x6b, 0x23, 0x30)
time.sleep(0.5)
data0 = bus.read_byte_data(0x6b, 0x08)
data1 = bus.read_byte_data(0x6b, 0x09)
xGyro = data1 * 256 + data0
if xGyro > 32767 :
xGyro -= 65536
data0 = bus.read_byte_data(0x6b, 0x0A)
data1 = bus.read_byte_data(0x6b, 0x0B)
yGyro = data1 * 256 + data0
if yGyro > 32767 :
yGyro -= 65536
data0 = bus.read_byte_data(0x6b, 0x0C)
data1 = bus.read_byte_data(0x6b, 0x0D)
zGyro = data1 * 256 + data0
if zGyro > 32767 :
zGyro -= 65536
print "Rotation in X-Axis : %d" %xGyro
print "Rotation in Y-Axis : %d" %yGyro
print "Rotation in Z-Axis : %d" %zGyro
According to the datasheet, the LSM9DS0 contains 2 submodules: one containing accelerometer and compass, the other containing the gyroscope. Each of the submodules is located at a different address, determined by the state of SA0_XM
and SA0_G
pins.
On the Adafruit module those pins are pulled high, so according to tables 15 and 16 in the datasheet:
0x1d
(00011101
)0x6b
(01101011
)Based on this, it appears you're accessing the correct address. It also means that near the beginning of your script, you should define a few constants, such as
ACCEL_ADDRESS = 0x1d
GYRO_ADDRESS = 0x6b
and use those instead of copying the magic number all around your code.
Now the register addresses. Since there are two different devices, there's a good chance that each exposes a different set of registers. Indeed, table 17 shows this to be the case, albeit somewhat indirectly. The important part is the column titled "Slave Address", which refers either to table 15 (accelerometer an compass) or table 16 (gyro). (The symbolic names of the registers might help you tell the difference in some cases, since they often have suffix M
(former) or G
(latter), but not always).
And herein lies your problem. For a gyroscope, the measurements are in registers at addresses 0x28..0x2d
yet you are reading from 0x08..0x0d
, which are reserved in the gyroscope module (getting some fixed nonsense as a result of reading that would not be unexpected).
You seem to have gotten the control registers CTRL_REG1_G
and CTRL_REG4_G
correctly.
Of course, just as with the addresses, you should have constants defined for all the registers you want to use:
CTRL_REG1_G = 0x20
CTRL_REG4_G = 0x23
OUT_X_L_G = 0x28
OUT_X_H_G = 0x29
and so on...
As an aside, the first thing I would try, before actually reading the measured values, would be reading the device identification register, in this case WHO_AM_I_G
(0x0F).
Since this register returns a constant, it's a good way to validate you're talking with the right device, and that the communication works correctly.
One more: don't copy-paste code around, use functions instead.
For example the first step of refactoring could yield something like:
def read_int16(bus, device, register):
lsb = bus.read_byte_data(device, register)
msb = bus.read_byte_data(device, register + 1)
result = msb * 256 + lsb
return (result - 65536) if (result > 32767) else result
xGyro = read_int16(bus, GYRO_ADDRESS, OUT_X_L_G)
yGyro = read_int16(bus, GYRO_ADDRESS, OUT_Y_L_G)
zGyro = read_int16(bus, GYRO_ADDRESS, OUT_Z_L_G)