在Raspberry Pi上使用Python smbus-语法混乱

在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

我正在尝试在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
...
代码:

我的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")