加速度センサーの使い道
ちょっとした興味本位で加速度センサーを買ったのですが、あまり使わなくて古くから眠っていたものを最近掘り起こしたのでちょっと遊んでみました。
使用機器
MMA8452Qモジュールキットを使いました。秋月電子で買いましたが今はもう売ってないらしいです。
RaspberryPi Zeroとつないで動かしています
何をしたか
Pythonから加速度データを整形し、pythonのcursesモジュールを用いて傾けるとカーソルの位置も変わるというちょっとしたものを作って遊びました。
ちなみに軸の取り方はこんな感じです(公式データシートより)
プログラムと動作
加速度センサーを操るプログラム
加速度センサーとはI2Cで通信します。その際にsmbusというモジュールを使います。
#MMA8452Q加速度センサーモジュール
import smbus
import time
import math
#I2C設定
i2c = smbus.SMBus(1)
address = 0x1D
#センサー設定
ret = i2c.write_byte_data(address,0x0E,0x00)
ret = i2c.write_byte_data(address,0x2A,0x01)
def get_data():
#データ読み込み
dat = i2c.read_i2c_block_data(address,0x01,0x06)
#print(dat)
#データ変換
dat_x = (dat[0] << 8 | dat[1]) >> 4
dat_y = (dat[2] << 8 | dat[3]) >> 4
dat_z = (dat[4] << 8 | dat[5]) >> 4
#極性診断
if dat_x >= 2048:
dat_x -= 4096
if dat_y >= 2048:
dat_y -= 4096
if dat_z >= 2048:
dat_z -= 4096
#物理量(加速度)に変換
out_x = dat_x / 1024.0
out_y = dat_y / 1024.0
out_z = dat_z / 1024.0
return (out_x, out_y, out_z)
表示するプログラム
cursesモジュールを使いました。詳しいことは過去記事をご覧ください。
ちなみに、センサーが返す値は重力加速度=1となる値として帰ってきます。
#!usr/bin/ python
# -*- coding: utf-8 -*-
import sys,os,time
import curses
#前述プログラム
import sensor
def pointer(stdscr):
#初期化
cursor_x = 0
cursor_y = 0
x,y,z = 0,0,0
#画面の初期化
stdscr.clear()
stdscr.refresh()
#カラー定義
curses.start_color()
curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK) # カラー1は、文字色をシアン、背景色を黒
while 1:
#画面初期化
stdscr.clear()
#画面の最大値を取得
height, width = stdscr.getmaxyx()
#加速度データ取得(zは使わない)
x,y,z = new_3dsensor.get_data()
x = round((-1)*x,6)
y = round(y,6)
#カーソル中心を取得
center_x, center_y = width // 2, height // 2
cursor_x = center_x + int(center_x * x)
cursor_y = center_y + int(center_y * y)
#カーソル枠の補正
cursor_x = max(0, cursor_x)
cursor_x = min(width-1, cursor_x)
cursor_y = max(0, cursor_y)
cursor_y = min(height-1, cursor_y)
# カーソル位置の表示
whstr = "W:{},H:{} , x:{},y:{} , cursor x:{} / y:{}".format(width, height,x,y,cursor_x,cursor_y)
stdscr.addstr(0, 0, whstr, curses.color_pair(1)) # 文字列whstrを(0,0)にカラー1で表示する
#カーソル
stdscr.move(cursor_y, cursor_x)
#リフレッシュ
stdscr.refresh()
#待機
time.sleep(0.1)
#元に戻す
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()
def main():
curses.wrapper(pointer)
if __name__ == "__main__":
main()
元に戻すという部分がありますが、breakするポイントがないので意味はないです。(Ctrl-Cブッチ)
また、加速度データを読み込む際のround関数あたりでx軸だけ正負反転させていますが、操作上直感的なものになるようにしているだけです。(左に傾けたら左にカーソルがいくようにした)
カーソルも基本的に中心になるようちょっと工夫があります。
実際の挙動
実際動かすとちらつきが半端ないですが、一応完成しました!
直したいとこ
通常の世界で静止しているときの重力加速度は真下にしか働かず、ななめにするとx:0.5,y:0.5と分散されるのは当たり前ですが、このプログラムだと隅っこにカーソルが動かないという問題があります。
片方が1に近づくともう片方の加速度も1になるよう調整できたらいいかなと思いました。
...まあ遊びなのでとりあえず動いたのでヨシ!!