本記事の内容
- Raspberry Pi PicoとMPU-6050、SSD1306ディスプレイモジュールを使用して、測定した三軸加速度をリアルタイムでディスプレイに表示させました。
- モバイルデバイスとして持ち運びができるように、Micro-USBケーブルでなく電池駆動として、単四電池×4本で動作させるように設計しています。
必要なもの
- Raspberry Pi Pico:550円
- waves MPU-6050 3軸ジャイロ+3軸加速度センサ:230円
- KeeYees OLEDディスプレイモジュール SSD1306:560円
- その他、ブレッドボード、単四電池、単四電池ホルダーなど
基本的にはBMP180を使用したデジタル気圧・高度計と同じ構成になっています。単四電池×4ホルダーとブレッドボードがピッタリ入るアクリルケース内に全て収納します。
3軸加速度センサとは
一言で説明すると、3軸加速度センサとは「3次元(直行3軸方向)の慣性運動を検出する装置です。どんな状態でどのような数値が測定されるかを、以下の2パターンで簡単に説明します。
静止している物体の場合
地上に対して静止している物体は、地球の引力(重力)として重力加速度9.8m/s2の加速度を受けています。3軸加速度センサでは重力加速度9.8を”1″と定義しているため、x=0, y=0, z=-1 と表示されます。
この物体を、x軸を中心に90度回転させると引力の加わる方向が変化して、x=0, y=1 (y=-1), z=0 となります。逆にy軸を中心に90度回転させると、x=1 (x=-1), y=0 , z=0 となります。
いわゆる数学のベクトルの世界です。私はとっくにベクトルの公式を忘れていますが、上手に計算すると内角から物体の置かれている状態が測定できるます。
そのため、ビルや橋梁などの建造物の傾斜を計測することなどに活用されています。
動いている物体の場合
再度、物理(力学)の話に戻ります。等速直線運動をしている物体は重力を除いた加速度を受けないため、3軸加速度センサとしては、x=0, y=0, z=1 と表示されます。
ただし、加速度が生じたタイミング(動かし始め、動かし終わり等)では、xとyの値は力の方向に応じて変化します。また、重力方向(縦方向)に加速度が生じた場合は、zの値も変化します。
それゆえ、地震計などにも3軸加速度センサは活用されています。
配線
まずは、Raspberry Pi PicoとMPU-6050を繋ぎます。MPU-6050にはVCCからINTまでの計8ピンがありますが、Datasheetを確認する限り、モード次第で使用するピンと使用しなくても良いピンがあります。
I2C Master Mode(SDA/SCLを使用)
SDA/SCLを使った一般的なI2C通信ができます。System applications processorの介在なしに(?)、3軸加速度を測定できる。
Pass-Through Mode(XDA/XCLを使用)
External system processor(外部システムプロセッサ?)を機能させて、補助I2Cバスピン(XDA/XCL)に接続された外部センサーと直接通信をする。
Pass-Through Modeは外部センサーを構成したり、外部センサーとしてMPU-6050を低電力で駆動するのに役立ちます。
誤訳の可能性もありますが、要するに、通常のI2C通信ならSDA/SCL、それ以外で特殊な使い方をしたい場合はXDA/XCLを使用しましょうかと思います。
私は加速度が読めればいいだけなので、SDA/SCLを繋げただけです。以下に配線を図示します。
Raspberry Pi Pico | OLEDディスプレイモジュール | MPU-6050 |
①GP0(I2C0 SDA) | SDA | |
②GP1(I2C0 SCL) | SCL | |
㊳GND | GND | GND |
㊱3V3(OUT) | VIN | VIN |
㉛GP26(I2C1 SDA) | SDA | |
㉜GP27(I2C1 SCL) | SCL |
MPU-6050のXDA以下残り4ピンは、OLEDディスプレイモジュールの下に隠れていますが、配線はしていません。
プログラムコード
前回の記事と同様に、まずはGitHubからssd1306.pyをダウンロードして、Raspberry Pi Picoにアップロードします。
あとは、MPU-6050で三軸加速度を測定して、ディスプレイモジュールに表示させるだけです。MPU-6050で三軸加速度を測定する部分は、こちらの方の記事を参考にさせていただきました。
from machine import Pin, I2C
from utime import sleep
from ssd1306 import SSD1306_I2C
import ustruct
#unsignedを、signedに変換(16ビット限定)
def u2s(unsigneddata):
if unsigneddata & (0x01 << 15) :
return -1 * ((unsigneddata ^ 0xffff) + 1)
return unsigneddata
class mpu6050:
def __init__(self, scl, sda):
self.scl = scl
self.sda = sda
self.i2c = I2C(1,scl = self.scl, sda = self.sda, freq = 100000)
#slv = self.i2c.scan()
self.slvAddr = 104 #slv[0]
# レジスタをリセットする
self.writeByte(0x6B,0x80)
sleep(0.1)
# PWR_MGMT_1をクリア
self.writeByte(0x6B,0x00)
sleep(0.1)
def readXYZ(self):
data = self.readByte(0x3B ,6)
x = (2.0 / 0x8000) * u2s(data[0] << 8 | data[1])
y = (2.0 / 0x8000) * u2s(data[2] << 8 | data[3])
z = (2.0 / 0x8000) * u2s(data[4] << 8 | data[5])
return (x,y,z)
def writeByte(self, addr, data):
d = bytearray([data])
self.i2c.writeto_mem(self.slvAddr, addr, d)
def readByte(self, addr, num):
s = self.i2c.readfrom_mem(self.slvAddr, addr, num)
return s
i2c = I2C(0,sda=Pin(0), scl=Pin(1), freq=400000)
oled = SSD1306_I2C(128, 64, i2c)
while True:
x,y,z = mpu6050(Pin(27), Pin(26)).readXYZ()
#print('x:',x,'y:',y,'z:',z,'uint:mg')
oled.text("X:", 0, 5)
oled.text("{: .4f}".format(x), 10, 15)
oled.text("Y:", 0, 25)
oled.text("{: .4f}".format(y), 10, 35)
oled.text("Z:", 0, 45)
oled.text("{: .4f}".format(z), 10, 55)
oled.show()
sleep(1)
oled.fill(0)
oled.show()
まとめ
- Raspberry Pi PicoとMPU-6050、SSD1306ディスプレイモジュールを使用して、測定した三軸加速度をリアルタイムで表示する小型デバイスを作製しました。
- 加速度を積分して移動距離を算出すれば、GPSを使わない測位システムが作れそうですね。アレンジが捗りそうです。
コメント