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

Using Python smbus on a Raspberry Pi - confused with syntax

我正在尝试在Raspberry Pi上使用python-smbus与I2C进行MMA7660加速度计芯片通信。

在下面的代码中,我正在读取芯片的寄存器0x00、0x01、0x02和0x03,并且得到的值完全相同。查看这些值并倾斜芯片,我可以看到它们都对应于寄存器0x00,即X值寄存器。

输出:

1
2
3
4
5
6
7
8
9
10
11
12
...
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
...

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  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语法上做错什么了吗?我确实在这里查看了文档。

我已经验证了芯片的工作原理-我可以使用Arduino与它进行良好的通信,并按照与上述相同的顺序设置寄存器。

更新#1(2013年6月28日):

根据Sylvain的评论,我为以下代码附加了SDA / SCL行的示波器输出:

1
2
bus.write_byte(addr, 0x01)
print bus.read_byte(addr)

enter

https://raspberrypi.stackexchange.com/questions/7138/mma8452-i2c-module

根据Linux SMBus规范:

1
2
3
4
5
6
7
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进行通信。


如果您一次读取所有需要的寄存器,则可以正常工作:

1
2
3
4
5
6
7
8
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]


我绝对不确定这是问题所在,但根据规格p22:

MMA7660FC is read using it’s internally stored register address as address pointer, the same way the stored register address
is used as address pointer for a write. The pointer generally auto-increments after each data byte is read using the same rules
as for a write (Table 5). Thus, a read is initiated by first configuring the device’s register address by performing a write (Figure 11)
followed by a repeated start. The master can now read 'n' consecutive bytes from it, with the first data byte being read from the
register addressed by the initialized register address.

据我了解,要从寄存器"读取",必须先写入寄存器地址,然后盲目读取一个字节。我不知道SMBus.read_byte_data是否为您解决了这个问题,但是您可以手动尝试:

1
2
3
4
5
6
7
8
9
10
11
  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)

也许甚至可以工作:

1
2
3
4
5
6
  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)


Raspberry PI I2C内核驱动程序在特定时间内不支持重复启动。但是,尽管必须显式激活此功能,但I2C内核驱动程序已经更新,现在支持重复启动。

设置联合转账\\'on \\'

sudo sh -c '/bin/echo Y > /sys/module/i2c_bcm2708/parameters/combined'

设置合并转账\\'off \\'

sudo sh -c '/bin/echo N > /sys/module/i2c_bcm2708/parameters/combined'

可在此处找到信息:http://raspberrypi.znix.com/hipidocs/topic_i2c_rs_and_cs.htm


在查看您的示例以及为MMA7455编写的类之后,我能够编写以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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")

那应该可以解决问题。