chart.jsで加速度・ジャイロセンサーを可視化してみた

Kibana可視化と問題点

前回、温湿度センサーのデータをOSSのElasticSearchとKibanaを使ってグラフ化しました。

camelrush.hatenablog.com

しかし、このツールはグラフの描画間隔の最小単位で1秒となっており、リアルタイムな描画ができませんでした。

chartjs-plugin-streaming

加速度センサーなど、プロッタのようなグラフ描画を行う方法を調べたところ、OSSとして、chart.jsの派生プラグインである「chartjs-plugin-streaming」がgitに公開されていました。

https://nagix.github.io/chartjs-plugin-streaming/ja/

描画サンプル

f:id:camelrush:20200526061709g:plain

加速度センサーの可視化

上記を基にして、加速度センサーから取得した駆動データを、グラフにプロットすることにします。
今回、計測には以下の慣性センサーを使用します。製品仕様として、3軸加速度+3軸角速度(ジャイロ)のセンサーを搭載した製品となっています。

慣性センサーの知識

慣性センサーとはセンサーの種類を示す大きな分類であり、具体的な計測対象に応じて「加速度」を計測する「加速度センサー」、「角速度」を計測する「ジャイロセンサー」が存在します。

加速度センサー

加速度センサーとは、物体の加速度(単位時間当たりの速度の変化量)を計測する装置であり、機器の移動の変化を検知するものです。センサは、その方向に応じて「x」「y」「z」の3軸のベクトルへの移動値を出力します。単位は「m/s^2」で表されます。一秒間でどの程度の距離を進んだかという表現になります。 f:id:camelrush:20200526063210p:plain

ジャイロセンサー

ジャイロセンサーは、ジャイロスコープとも呼ばれ、角度(傾き)や角速度(回転の速さ)を測るセンサーです。単位は「°/s」「rad/s」で表されます。一秒間で何度角度が回転したかという表現になります。 f:id:camelrush:20200526064251p:plain

システム構成

構成としては、RaspberryPiで受信したセンサーデータをMQTTによって送信します。MQTTブローカーには、AWSのIoTCoreを使用しています。最終的に表示するWebページで「chartjs-plugin-streaming」を使用してリアルタイムグラフを表示します。 f:id:camelrush:20200527054645p:plain

プログラム

以下のGitHubにプログラムを掲載しています。
github.com

加速度センサー「MPU6050」制御

加速度センサーのデバイス制御は「devices/accelerometer.py」に記載しています。データシートをもとに、I2Cによってデータを取得します。

from abc import ABCMeta
import smbus
import math
from time import sleep

# MPU6050 Register Map
DEV_ADDR = 0x68
ACCEL_XOUT = 0x3b
ACCEL_YOUT = 0x3d
ACCEL_ZOUT = 0x3f
TEMP_OUT = 0x41
GYRO_XOUT = 0x43
GYRO_YOUT = 0x45
GYRO_ZOUT = 0x47
PWR_MGMT_1 = 0x6b
PWR_MGMT_2 = 0x6c   

class AbstractAccelerometer(metaclass=ABCMeta):
    def __init__(self ,devadr):
        self._devadr = devadr
        self._bus = smbus.SMBus(1)

    def startup(self ,pwr_mgmt_adr):
        self._bus.write_byte_data(self._devadr, pwr_mgmt_adr, 0)

    def _read_word(self ,adr):
        high = self._bus.read_byte_data(self._devadr, adr)
        low = self._bus.read_byte_data(self._devadr, adr+1)
        val = (high << 8) + low
        return val

    def read_word_sensor(self ,adr):
        val = self._read_word(adr)
        if (val >= 0x8000):         # minus
            return -((65535 - val) + 1)
        else:                       # plus
            return val

class AccelerometerMPU6050(AbstractAccelerometer):

    def __init__(self):
        super().__init__(DEV_ADDR)
        super().startup(PWR_MGMT_1)

    def get_temp(self):
        temp = super().read_word_sensor(TEMP_OUT)
        x = temp / 340 + 36.53      # data sheet(register map)記載の計算式.
        return x

    def get_gyro(self):
        x = super().read_word_sensor(GYRO_XOUT)/ 131.0
        y = super().read_word_sensor(GYRO_YOUT)/ 131.0
        z = super().read_word_sensor(GYRO_ZOUT)/ 131.0
        return [x, y, z]

    def get_accel(self):
        x = super().read_word_sensor(ACCEL_XOUT)/ 16384.0
        y = super().read_word_sensor(ACCEL_YOUT)/ 16384.0
        z = super().read_word_sensor(ACCEL_ZOUT)/ 16384.0
        return [x, y, z]

データシートは以下を参照ください。

http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Components/General%20IC/PS-MPU-6000A.pdf

配線図

配線は比較的シンプルです。データ取得にはI2Cバスを使用します。 f:id:camelrush:20200527060721p:plain

動作結果

数10ms程度のタイムラグはありますが、センサーデータのリアルタイムプロットができました。
youtu.be