使用 I2c 总线读取陀螺仪值

Read a gyroscope value with the I2c bus

产品:https://www.adafruit.com/product/2020

数据表:https://cdn-shop.adafruit.com/datasheets/LSM9DS0.pdf

我是学生,第一次使用I2c总线。我正在尝试读取基本陀螺仪值。我浪费了一部分时间来了解 I2c 的工作原理。但是在阅读了数据表并制作了我自己的脚本之后。 我的价值观被困在那里。什么都没动,我也不知道为什么。

Rotation in X-Axis : -1087
Rotation in Y-Axis : -28797
Rotation in Z-Axis : -15032

这是我的脚本。有人可以帮我解决吗?我正在使用黑色比格犬骨。

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

有许多 i2c 出版物,您可以从中了解其工作原理。此外,大多数陀螺仪和 mems 设备基本上也在其数据表中对其进行了解释。但基本上它是两条具有逻辑高和逻辑低状态的电线。消息通常以 8 位段的形式发送。要发送一个段,时钟线变低,然后数据转换为要发送的电平。数据线必须稳定,然后时钟变高。时钟变高时的数据电平是位 0(数据低)或 1(数据高)。首先发送设备的 8 位地址(实际上是 7 位地址,最后一位是读或写信号)。通常写你先发送读取然后中断然后写入。读取时,发送设备地址后,接下来的8位或16位为寄存器地址。然后设备将发送信息。写作是相似的。一些 mems 设备有 fifo 寄存器和中断,这可能有点不同。有关详细信息,请参阅各自的数据表。

根据datasheet,LSM9DS0包含2个子模块:一个包含加速度计和指南针,另一个包含陀螺仪。每个子模块位于不同的地址,由 SA0_XMSA0_G 引脚的状态决定。

Adafruit module 上,这些引脚被拉高,因此根据数据表中的 tables 15 和 16:

  • 加速度计和指南针位于地址 0x1d (00011101)
  • 陀螺仪在地址 0x6b (01101011)

据此,您访问的地址似乎正确。这也意味着在脚本的开头附近,您应该定义一些常量,例如

ACCEL_ADDRESS = 0x1d
GYRO_ADDRESS = 0x6b

并使用它们而不是在代码周围复制幻数。


现在是寄存器地址。由于有两个不同的设备,每个设备很可能会公开一组不同的寄存器。事实上,table 17 显示了这种情况,尽管有些间接。重要的部分是标题为 "Slave Address" 的列,它指的是 table 15(加速度计和指南针)或 table 16(陀螺仪)。 (寄存器的符号名称在某些情况下可能会帮助您区分它们,因为它们通常具有后缀 M(前者)或 G(后者),但并非总是如此。

这就是你的问题。对于陀螺仪,测量值在地址为 0x28..0x2d

的寄存器中

然而你正在阅读 0x08..0x0d,这是在陀螺仪模块中保留的(由于阅读而得到一些固定的废话,这并不意外)。

您似乎已经正确获取了控制寄存器 CTRL_REG1_GCTRL_REG4_G

当然,就像地址一样,您应该为要使用的所有寄存器定义常量:

CTRL_REG1_G = 0x20
CTRL_REG4_G = 0x23
OUT_X_L_G = 0x28
OUT_X_H_G = 0x29

等等...


顺便说一句,在实际读取测量值之前,我首先要尝试读取设备标识寄存器,在本例中为 WHO_AM_I_G (0x0F)。

由于此寄存器 returns 是一个常量,因此这是验证您正在与正确的设备通话以及通信是否正常工作的好方法。


还有一点:不要 copy-paste 编码,而是使用函数。

例如,重构的第一步可能会产生如下结果:

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)