MMA7455L + Python + Cubieboard

MMA7455L (PDF) 三轴加速度传感器,可以使用 I2C 或者 SPI 总线连接。两者 Cubieboard 均有提供,虽然不懂有多大区别但是 SPI 要四根线好麻烦所以就用 I2C 了..(

与 Cubieboard 的连接参照 WikiPB18 (TWI1-SCK)PB19 (TWI1-SDA) 两根接在模块的 SCLSDI 口上,接好电源(3.3V)和地线,模块的 CS 也接在电源上(以使能 I2C)。官网 ubuntu 镜像默认启用 I2C-1,若未启用则需修改 Fex 文件:twi1_used = 1

可以使用 i2c-tools 确认连接正确。装好后输入i2cdetect -y 1,如果出现1d(MMA7455L 的地址),说明连接无误可以通讯。

在 Cubieboard 上使用 Python 读取加速度数值,代码在这:MMA7455L.py,目前实现功能有:

  • 读取 8 或 10 位的 X, Y, Z 轴加速度数值(-127 ~ 128 / -511 ~ 512);
  • 切换 ±2g, ±4g 和 ±8g(set_range());
  • 自动校准(set_offset()clear_offset())。

#!/usr/bin/env python
import smbus
import time


class Accel():
    def __init__(self, dev=1, g=2):
        self.bus = smbus.SMBus(dev)
        self.set_range(g)


    def write(self, register, data):
        self.bus.write_byte_data(0x1D, register, data)


    def read(self, data):
        return self.bus.read_byte_data(0x1D, data)


    def set_range(self, g):
        if g == 8:
            d = 0b01000001
        elif g == 4:
            d = 0b01001001
        elif g == 2:
            d = 0b01000101
        else:
            raise ValueError("Only 2, 4 or 8.")
        self.write(0x16, d)
        self.g = g


    def _get(self, addr):
        l = self.read(addr)
        h = self.read(addr + 1)
        d = h << 8 | l
        if d > 511:
            d -= 1024
        return d


    def get_x(self):
        return self._get(0x00)


    def get_y(self):
        return self._get(0x02)


    def get_z(self):
        return self._get(0x04)


    def clear_offset(self):
        self.write(0x10, 0)
        self.write(0x11, 0)
        self.write(0x12, 0)
        self.write(0x13, 0)
        self.write(0x14, 0)
        self.write(0x15, 0)
        time.sleep(0.1)


    def _set_offset(self, addr, zero):
        d = self._get(addr - 0x10)
        d = zero - d
        d = int(d * 2.5)
        d += 65536
        self.write(addr, d & 0xff) # Low
        self.write(addr + 1, d >> 8 & 0xff) # High


    def set_offset(self):
        self.clear_offset()
        self._set_offset(0x10, 0)
        self._set_offset(0x12, 0)
        if self.g == 4:
            zero = 32
        else:
            zero = 64
        self._set_offset(0x14, zero)
        time.sleep(0.1)


def main():
    mma = Accel(1)
    mma.set_offset()
    while True:
        x = mma.get_x()
        y = mma.get_y()
        z = mma.get_z()
        print("x =%4d ,y =%4d, z =%4d" % (x, y, z))
        time.sleep(0.1)


if __name__ == '__main__':
    main()

这块IC功能挺多的,先把好玩的给写了,以后有需要再改脚本。

P.s. 写校准时被坑了两次,MMA7455L 的 PDF 里不给计算方法,得下 AN3745 看。里面有两句话:

(…) values calculated in Step 2 must be multiplied by two.
Note that there will still be a bit of offset shift, and you may need to multiply by a bit more than two to exactly subtract the offset.

果断只看到前一句就乘 2 了,实际上反复测试要乘 2.5 才完美…
另外虽然 PDF 里写数据只有 10 位,但负数取补码时得按 16 位取,发 16 位才行…

发表评论

电子邮件地址不会被公开。 必填项已用*标注