4

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

在下面的代码中,我正在读取芯片的寄存器 0x​​00、0x01、0x02 和 0x03,并且我得到了完全相同的值。查看这些值,倾斜芯片,我可以看到它们都对应于寄存器 0x​​00,即 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 语法上做错了吗?我确实在这里查看了文档。

我已经验证了芯片可以正常工作——我可以使用 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)之前清楚地显示了一个停止(P)。

因此,我想我在 Pi 上使用 I2C 硬件与 MMA7760 通信并不走运。

4

4 回答 4

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] 
于 2013-09-22T10:33:14.837 回答
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)
于 2013-06-26T10:36:49.903 回答
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

于 2016-09-03T20:30:45.310 回答
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")

这应该够了吧。

于 2015-11-14T22:22:17.750 回答