加速度センサ

以前にArduinoで使ってみた加速度センサのインタフェースがI2Cなので、これもRaspberry Piに接続して試してみる事にした。加速度センサはフリースケール社のMMA7455Lを14ピンのDIP基板に乗せたものだ。ストロベリーリナックスで購入できる。

動作電圧が2.4V~3.6Vで、5Vでは動作しないから5V動作のArduinoで使う時は注意が必要なのだが、Raspberry PiはGPIOが3.3Vなので都合が良い。まずはブレッドボード上でVCC/GND/SDA/SCLの各ピンをGPIOの対応するピンに接続。
MMA7455

MMA745Lモジュール

Raspberry Pi

1 : GND

6 : GND

2 : VDD  6 : AVDD  8 : CS

1 : 3.3V

13 : SDA

3 : SDA

14 : SCL

5 : SCL

Raspberry PiのI2Cポートにはプルアップ抵抗が付いているので、プルアップする必要は無いはずなのだが、抵抗を外付けしないと正しく認識されなかった。正しく認識されていれば以下のように検出される。

>pi@raspberrypi ~ $ sudo i2cdetect 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n]
0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- 1d -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

あとはPythonで簡単なプログラムを書いて確認。加速度センサの値は簡単に取得できたので、ついでに値をPyGameでグラフ表示できるようにしてみた。プログラムは以下の通り。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import pygame
from pygame.locals import *
import smbus
import time

screen_rect = Rect(0, 0, 640, 320)
white = 255, 255, 255
red = 255, 0, 0
green = 0, 255, 0
blue = 0, 0, 255
yellow = 255, 255, 0

class MMA7455L:
    i2c = smbus.SMBus(1)   
    addr = 0x1d
    def __init__(self):
        self.i2c.write_byte_data(self.addr, 0x16, 0x05)     # 2G/Measurement Mode
        for i in range(0, 6):
            self.i2c.write_byte_data(self.addr, 0x10 + i, 0)
        time.sleep(0.1)
    def get(self):
        return self.i2c.read_i2c_block_data(self.addr, 0x06, 3)
    def drift(self):
        dd = [0, 0, 0]
        for i in range(0, 20):
            buf = self.i2c.read_i2c_block_data(self.addr, 0x06, 3)
            dd[0] = dd[0] + signed(buf[0])
            dd[1] = dd[1] + signed(buf[1])
            dd[2] = dd[2] + signed(buf[2]) - 64
        dd[0] = (dd[0] / 8) * -1
        dd[1] = (dd[1] / 8) * -1
        dd[2] = (dd[2] / 8) * -1
        for i in range(0, 3):
            self.i2c.write_byte_data(self.addr, 0x10 + i * 2, dd[i])
            self.i2c.write_byte_data(self.addr, 0x11 + i * 2, (dd[i] >> 8) & 0x07)
        time.sleep(0.1)

def signed(n):
    return n if n < 128 else n - 256 

if __name__ == "__main__":
    mma = MMA7455L()
    mma.drift()
    pygame.init()
    screen = pygame.display.set_mode(screen_rect.size)
    center = screen_rect.height / 2
    pygame.draw.line(screen, blue, (20, center),\
                    (screen_rect.width, center), 1)
    pygame.draw.line(screen, blue, (20, center - 64),\
                    (screen_rect.width, center - 64), 1)
    pygame.draw.line(screen, blue, (20, center + 64),\
                    (screen_rect.width, center + 64), 1)
    pygame.draw.line(screen, blue, (20, center - 128),\
                    (screen_rect.width, center - 128), 1)
    pygame.draw.line(screen, blue, (20, center + 128),\
                    (screen_rect.width, center + 128), 1)
    pygame.draw.line(screen, blue, (20, 0), (20, screen_rect.height), 1)
    font = pygame.font.Font(None, 16)
    text = font.render("+2G", True, white)
    screen.blit(text, (0, center - 133))
    text = font.render("+1G", True, white)
    screen.blit(text, (0, center - 69))
    text = font.render(" 0G", True, white)
    screen.blit(text, (0, center - 5))
    text = font.render("-1G", True, white)
    screen.blit(text, (0, center + 59))
    text = font.render("-2G", True, white)
    screen.blit(text, (0, center + 123))
    d1 = mma.get()
    d1[0] = signed(d1[0]) * -1
    d1[1] = signed(d1[1]) * -1
    d1[2] = signed(d1[2]) * -1
    x = 20
    try:
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
            d2 = mma.get()
            d2[0] = signed(d2[0]) * -1
            d2[1] = signed(d2[1]) * -1
            d2[2] = signed(d2[2]) * -1
            pygame.draw.line(screen, red, (x, d1[0] + center),\
                            (x + 1, d2[0] + center), 1)
            pygame.draw.line(screen, green, (x, d1[1] + center),\
                            (x + 1, d2[1] + center), 1)
            pygame.draw.line(screen, yellow, (x, d1[2] + center),\
                            (x + 1, d2[2] + center), 1)
            pygame.display.update()
            x = x + 1
            d1 = d2
            time.sleep(0.1)
    except KeyboardInterrupt:
        print '\nbreak'
        pygame.quit()

実行すると以下のように表示される、グラフの赤線がX軸、緑線がY軸、黄色線がZ軸。Z軸が最初から1Gになっているのは、何もしなくても重力が加わっているからだ。グラフの最初は加速度センサを傾けた時、後半はそれぞれの軸に対して振ったときの値を示している。
MMATest プルアップ抵抗の謎はあったが、I2C液晶の時よりも簡単に使う事ができた。モジュールは千円以下で買えるので、手軽に色々な応用ができそうだ。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中