在Raspberry Pi上使用Python smbus-语法混乱
我正在尝试在Raspberry Pi上使用python smbus与使用I2C的MMA7660加速计芯片进行通信 在下面的代码中,我正在读取芯片的寄存器0x00、0x01、0x02和0x03,我得到的所有值都完全相同。查看这些值,并倾斜芯片,我可以看到它们都对应于寄存器0x00,X值寄存器 输出:在Raspberry Pi上使用Python smbus-语法混乱,python,raspberry-pi,i2c,Python,Raspberry Pi,I2c,我正在尝试在Raspberry Pi上使用python smbus与使用I2C的MMA7660加速计芯片进行通信 在下面的代码中,我正在读取芯片的寄存器0x00、0x01、0x02和0x03,我得到的所有值都完全相同。查看这些值,并倾斜芯片,我可以看到它们都对应于寄存器0x00,X值寄存器 输出: ... 1 1 1 2 3 3 3 3 1 1 1 1 59 60 60 60 51 51 51 51 58 58 58 58 3 3 3 3 62 62 62 62 58 58 58 58 62 6
...
1 1 1 2
3 3 3 3
1 1 1 1
59 60 60 60
51 51 51 51
58 58 58 58
3 3 3 3
62 62 62 62
58 58 58 58
62 62 62 62
...
代码:
我的smbus语法是否有问题?我确实看了文件
我已经验证了芯片的工作原理——我可以使用Arduino和它进行良好的通信,并按照上面相同的顺序设置寄存器
更新#1(2013年6月28日):
根据Sylvain的评论,我为以下代码附加SDA/SCL线的示波器输出:
bus.write_byte(addr, 0x01)
print bus.read_byte(addr)
更新#2:
我想Raspberry Pi上的I2C存在一个已知的问题-没有“重复启动”
根据Linux SMBus规范:
SMBus Read Byte: i2c_smbus_read_byte_data()
============================================
This reads a single byte from a device, from a designated register.
The register is specified through the Comm byte.
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
但当我尝试时,示波器清楚地显示在重复启动之前的停止(p)
因此,我想我在Pi上使用I2C硬件与MMA7760对话时运气不佳。我绝对不确定这是否是问题所在,但根据规范p22:
使用内部存储的寄存器地址作为地址指针读取MMA7660FC,读取方式与存储的寄存器地址相同
用作写操作的地址指针。指针通常在使用相同的规则读取每个数据字节后自动递增
至于写入(表5)。因此,读取首先通过执行写入来配置设备的寄存器地址来启动(图11)
接着是重复的开始。主机现在可以从中读取“n”个连续字节,第一个数据字节从
由初始化的寄存器地址寻址的寄存器
据我所知,要从寄存器“读取”,必须先写入寄存器地址,然后盲目读取字节。我不知道SMBus.read\u byte\u data是否能帮你处理,但你可以手动尝试:
也许这会奏效:
bus.write_byte(addr,0x00)
x = bus.read_byte(addr)
y = bus.read_byte_data(addr)
z = bus.read_byte(addr)
tr = bus.read_byte(addr)
如果您一次读取所有需要的寄存器,它工作正常:
import smbus
bus = smbus.SMBus(1)
Register = bus.read_i2c_block_data(0x4c, 0x99,4)
acc_x = Register[0]*1.0
acc_y = Register[1]*1.0
acc_z = Register[2]*1.0
acc_tilt = Register[3]
在查看您的示例以及为MMA7455编写的类之后,我能够编写以下内容:
import smbus
import time
import os
import math
# Define a class for the accelerometer readings
class MMA7660():
bus = smbus.SMBus(1)
def __init__(self):
self.bus.write_byte_data(0x4c, 0x07, 0x00) # Setup the Mode
self.bus.write_byte_data(0x4c, 0x06, 0x10) # Calibrate
self.bus.write_byte_data(0x4c, 0x08, 0x00) # Calibrate
self.bus.write_byte_data(0x4c, 0x07, 0x01) # Calibrate
def getValueX(self):
return self.bus.read_byte_data(0x4c, 0x00)
def getValueY(self):
return self.bus.read_byte_data(0x4c, 0x01)
def getValueZ(self):
return self.bus.read_byte_data(0x4c, 0x02)
mma = MMA7660()
for a in range(1000):
x = mma.getValueX()
y = mma.getValueY()
z = mma.getValueZ()
print("X=", x)
print("Y=", y)
print("Z=", z)
time.sleep(0.2)
os.system("clear")
这应该能奏效 Raspberry PI I2C内核驱动程序在特定时间内不支持重复启动。但是,I2C内核驱动程序已经更新,现在支持重复启动,尽管此功能必须显式激活 将组合传输设置为“开”
sudo sh-c'/bin/echo Y>/sys/module/i2c\u bcm2708/parameters/combined'
将组合传输设置为“关闭”
sudo sh-c'/bin/echo N>/sys/module/i2c\u bcm2708/parameters/combined'
此处提供的信息:不幸的是,这两种方法都不起作用,但我认为您的方法是正确的。问题在于如何使用smbus实现这一点。我希望他们能对I2C启动/停止/重新启动等进行较低级别的调用。我可以在C和ATmega168中完全做到这一点,而且一切都可以。@M-V您有示波器或逻辑分析仪来检查总线吗?我有一个示波器,但不是一个功能非常强大的示波器。老实说,我还没有弄明白如何使用它来分析数字波形-数据会在一瞬间消失。@M-V你可能需要一个仪器来研究这种信号。谢谢@Sylvain-我花了一些时间研究如何使用示波器捕捉这些信号。我已经发布了信号-请分享任何见解。尝试使用MMA8452,但没有任何帮助。我猜你使用的任何芯片都能容忍不正确的启动/停止/重复启动。一旦这样做了,是什么控制了发出多少重复启动命令?如果我尝试使用smbus的read_i2c_block_data方法,是什么控制它在发出停止之前发出重复启动的次数?@Aerovistae在主设备将其数据传输到从设备(接收器模式下的从设备)后发出一次重复启动,以便从从设备(发射器模式下的从设备)读取数据。重复启动用于避免总线上的另一个主机过早获得对总线的控制。只要主设备没有发出停止条件,或者从设备在前一个传输字节后没有发出不确认信号,它就会请求数据。当它基本上与问题中的代码相同时,为什么要这样做呢?@DanielK.-对不起,已经5年了,所以我失去了这个答案的上下文。我相信这可能与-os.system(“clear”)有关
import smbus
bus = smbus.SMBus(1)
Register = bus.read_i2c_block_data(0x4c, 0x99,4)
acc_x = Register[0]*1.0
acc_y = Register[1]*1.0
acc_z = Register[2]*1.0
acc_tilt = Register[3]
import smbus
import time
import os
import math
# Define a class for the accelerometer readings
class MMA7660():
bus = smbus.SMBus(1)
def __init__(self):
self.bus.write_byte_data(0x4c, 0x07, 0x00) # Setup the Mode
self.bus.write_byte_data(0x4c, 0x06, 0x10) # Calibrate
self.bus.write_byte_data(0x4c, 0x08, 0x00) # Calibrate
self.bus.write_byte_data(0x4c, 0x07, 0x01) # Calibrate
def getValueX(self):
return self.bus.read_byte_data(0x4c, 0x00)
def getValueY(self):
return self.bus.read_byte_data(0x4c, 0x01)
def getValueZ(self):
return self.bus.read_byte_data(0x4c, 0x02)
mma = MMA7660()
for a in range(1000):
x = mma.getValueX()
y = mma.getValueY()
z = mma.getValueZ()
print("X=", x)
print("Y=", y)
print("Z=", z)
time.sleep(0.2)
os.system("clear")