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

时间:2013-06-26 10:13:41

标签: 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 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)

enter image description here

更新#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通信时运气不佳。

4 个答案:

答案 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