【问题标题】:Read a gyroscope value with the I2c bus使用 I2c 总线读取陀螺仪值
【发布时间】:2017-09-24 11:55:20
【问题描述】:

产品: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

【问题讨论】:

  • 您能正确读取WHO_AM_I_G (0Fh) 寄存器吗?这将是我尝试的第一件事,因为它返回一个常量。
  • 在我看来,您从错误的地址读取。陀螺仪输出寄存器位于 0x28...0x2D(数据表中的第 8.9 - 8.11 节)。访问陀螺仪子模块时保留地址 0x08..0x0D。

标签: python beagleboneblack i2c gyroscope


【解决方案1】:

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

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

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

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

ACCEL_ADDRESS = 0x1d
GYRO_ADDRESS = 0x6b

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


现在是寄存器地址。由于有两种不同的设备,因此很可能每个设备都公开一组不同的寄存器。实际上,表 17 表明情况确实如此,尽管有些间接。重要的部分是标题为“从属地址”的列,它指的是表 15(加速度计和指南针)或表 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)。

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


还有一个:不要复制粘贴代码,而是使用函数。

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

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)

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我也不使用python。所以你自己在那里使用MCU并闪烁它。
    • 恕我直言,这根本没有解决 OP 的问题。
    • 提问者似乎不知道从哪里开始解决他们的问题。对我来说,对 i2c 有基本的了解是必要的。我可以看到不习惯数据表的初学者,时间和上升下降时间的东西可能会令人生畏。我认为通过尝试用常用词简要描述正在发生的事情可能会开始一些理解。我不熟悉 beaglebone 或者它是基于 python 的汇编器/编译器,它通常是 i2c 硬件和控制或 python。当时没有人回答,我认为问题没有那么糟糕。
    • 我认为我的其他答案仍然是相关的,甚至有用的,虽然可以更清楚,正确的 i2c 标准等。但我认为它的相关性肯定存在。
    • 您的回答似乎更多地关注python风格和代码的清洁度,我认为这无关紧要。但是 stackxchange 已经采用了编程方法,而不是解决硬件问题等功能性问题(我不喜欢 stackexchange 的这一方面)。所以我猜你最终是正确的,但我会在这里使用我的投票,而我还有一个(已经被禁止提问)。
    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多