我正在尝试在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 62 62 62
...
代码:
import smbus
import time
bus = smbus.SMBus(1)
# I2C address for MMA7660
addr = 0x4C
try:
bus.write_byte_data(addr, 0x07, 0x00)
bus.write_byte_data(addr, 0x06, 0x10)
bus.write_byte_data(addr, 0x08, 0x00)
bus.write_byte_data(addr, 0x07, 0x01)
except IOError, err:
print err
while True:
try:
x = bus.read_byte_data(addr,0x00)
y = bus.read_byte_data(addr,0x01)
z = bus.read_byte_data(addr,0x02)
tr = bus.read_byte_data(addr,0x03)
print x, y, z, tr
time.sleep(0.25)
except:
print 'exiting...'
break
我是否对smbus语法做错了?我确实查看了文档here。
我已经验证芯片有效 - 我可以使用Arduino与它进行良好的通信,并按照与上面相同的顺序设置寄存器。
更新#1(2013年6月28日):
根据Sylvain的评论,我为以下代码附加了SDA / SCL线路的示波器输出:
bus.write_byte(addr, 0x01)
print bus.read_byte(addr)
更新#2:
我猜在Raspberry Pi上有一个已知的I2C问题 - 没有“重复启动”。
https://raspberrypi.stackexchange.com/questions/7138/mma8452-i2c-module
根据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
但是当我尝试它时,示波器在重复启动(S)之前清楚地显示STOP(P)。
所以我想我在Pi上使用I2C硬件与MMA7760通信时运气不佳。
答案 0 :(得分:2)
如果您一次阅读所有需要的寄存器,它可以正常工作:
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]
答案 1 :(得分:1)
我绝对不确定这是问题,但根据规范p22:
使用内部存储的寄存器地址作为地址指针读取MMA7660FC,与存储的寄存器地址相同 用作写入的地址指针。在使用相同的规则读取每个数据字节后,指针通常会自动递增 至于写(表5)。因此,首先通过执行写入配置器件的寄存器地址来启动读取(图11) 然后重复开始。主机现在可以从中读取'n'个连续字节,第一个数据字节从中读取 寄存器由初始化寄存器地址寻址。
据我所知,要从寄存器“读取”,您必须先从写寄存器地址开始,然后盲目地读取一个字节。我不知道SMBus.read_byte_data
是否会为您处理此问题,但您可以手动手动:
bus.write_byte(addr,0x00)
x = bus.read_byte(addr)
bus.write_byte(addr,0x01)
y = bus.read_byte_data(addr)
bus.write_byte(addr,0x02)
z = bus.read_byte(addr)
bus.write_byte(addr,0x03)
tr = bus.read_byte(addr)
也许甚至可以工作:
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)
答案 2 :(得分:0)
在查看了您的示例以及为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")
这应该可以解决问题。
答案 3 :(得分:0)
Raspberry PI I2C内核驱动程序不支持在特定时间重复启动。但是,I2C内核驱动程序已更新,现在支持重复启动,但必须明确激活此功能。
在'
上设置合并转移 sudo sh -c '/bin/echo Y > /sys/module/i2c_bcm2708/parameters/combined'
将联合转移设置为“关闭”
sudo sh -c '/bin/echo N > /sys/module/i2c_bcm2708/parameters/combined'
此处的信息:http://raspberrypi.znix.com/hipidocs/topic_i2c_rs_and_cs.htm