简体   繁体   中英

Read a gyroscope value with the I2c bus

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.

数据表中的表15和表16

On the Adafruit module those pins are pulled high, so according to tables 15 and 16 in the datasheet:

  • accelerometer and compass are at address 0x1d ( 00011101 )
  • gyroscope is at address 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).

表17

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)

There are many i2c publications where you can find out how it works. Also most gyro and mems devices basically explain it in their data sheets also. But basically it is two wires which have logic high and logic low states. The messages are usually sent in 8 bit segments. To send a segment the clock wire goes low then the data is transitioned to the level which is to be sent. The data wire must be stable and then clock goes high. The data level when clock goes high is the bit 0 (data low) or 1 (data high). The devices 8 bit address is sent first (really 7 bit address, the last bit is to signal read or write). Usually to write you send read first then interrupt followed by write. When reading, after device address is sent, the next 8 or 16 bits are register address. Then the device will send information. Writing is similar. Some mems device have fifo register and interrupts which can be a little different. See your respective data sheets for details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM