【センサー入門】RasPi4でMPU9250加速度、温度、角速度、磁気センサーで遊んでみた♪

今回は。MPU9250　9軸センサモジュールで遊んでみた記録です。
加速度(g)、温度、角速度（３軸まわりの回転速度ω（degree/s））、磁気の10個の測定ができるようです。
参考①でいろいろ書かれているのでほぼOKですが、RasPi4でやってみたので、その記録です。

【参考】
①[Rasberry pi 3でストロベリー・リナックス社製の「MPU-9250 ９軸センサモジュール (メーカー品番：MPU-9250)」を使う](https://qiita.com/boyaki_machine/items/915f7730c737f2a5cc79)
②[Raspberry Pi 3 Mobel B+とカムプログラムロボットでロボット作成](https://qiita.com/K-Ponta/items/507b1a655a3489663bc8)

###やったこと
・環境
・加速度の測定
・温度の測定
・角速度の測定
・地磁気の測定
###・環境
####i2cを有効にする
参考①と異なり、RasPi４の環境で有効にします。
メニューー設定ーRaspberryPiの設定ーインターフェース：I2Cを有効ーOK
で有効にできます。
####製品と配線
以下のとおり
製品；クリックするとアマゾンへ飛びます
[![51I7i7llQjL._AC_SL1010_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/7b92b5b4-7943-cae1-fb07-bd38a4716fdf.jpeg)](https://www.amazon.co.jp/HiLetgo%C2%AE-MPU9250-9%E8%87%AA%E7%94%B1%E5%BA%A61-%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AD%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97-%E7%A3%81%E6%B0%97%E3%82%BB%E3%83%B3%E3%82%B5/dp/B0154PM102/ref=sr_1_2?dchild=1&keywords=MPU9250&qid=1617418837&sr=8-2)
このモジュールをRasPi4のGPIOの各pinに接続します。
※短い側に半田つけしてから、ブレッドボードへ指してRasPi4と接続します
VCC-3.3v(3.3v pin1)
GND-GND(GND pin6)
SCL-SCL1(GPIO3 pin5)
SDA-SDA1(GPIO2 pin3)
【参考】
③[ラズパイ（Raspberry Pi）のGPIOを再確認！　まずは汎用入出力からマスターしよう](https://deviceplus.jp/hobby/raspberrypi-gpio/)
####MPU9250
i2c-toolsをインストールする。

```
$ sudo apt-get install i2c-tools python-smbus
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 
```

```i2c_access.py
#!/usr/bin/python -u
# -*- coding: utf-8 -*-

import smbus
import time

address = 0x68
channel = 1
bus     = smbus.SMBus(channel)

# PWR_MGMT_1をクリア
bus.write_i2c_block_data(address, 0x6B, [0x00])
time.sleep(0.1)

# I2Cで磁気センサ機能(AK8963)へアクセスできるようにする(BYPASS_EN=1)
bus.write_i2c_block_data(address, 0x37, [0x02])
time.sleep(0.1)
```
以下のようにI2Cで磁気センサ機能(AK8963)に0x0cで接続できる。

```
$ python3 i2c_access.py
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- 0c -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 
```
###・加速度の測定
実は、参考①をまんまでも（python3対応はしますが）とりあえず動きます。
しかし、数字がおかしいです。
また、取得方法も
data    = bus.read_i2c_block_data(address, 0x3B ,6)
となっていますが、[リンク先](https://ryusakura.wordpress.com/2015/04/16/mpu9250%E3%81%AE%E5%8A%A0%E9%80%9F%E5%BA%A6/)では、以下のコードで取得できるとなっています。

```py
def getAccel(axis):
    if axis == 'X':
        accel_H = dataGet(0x3B,1)
        accel_L = dataGet(0x3C,1)
    elif axis == 'Y':
        accel_H = dataGet(0x3D,1)
        accel_L = dataGet(0x3E,1)
 
    elif axis == 'Z':
        accel_H = dataGet(0x3F,1)
        accel_L = dataGet(0x40,1)
 ```
ここが判じ物なので、それなりに楽しめました。
まず、取得方法の違いを理解するためにデータシートを見てみます。
以下にありました。
【参考】
[MPU-9250レジスタ・リファレンスマニュアル ](https://strawberry-linux.com/pub/RM-MPU-9250A-00.pdf)
部分的に示すと、以下のようになっています。

|adress(Hex)|adress(Dec.)|Register Name|R/W|Bit(7-0)|
|:-:|:-:|:-:|:-:|:-:|
|   |   |   |   ||
|3B| 59| ACCEL_XOUT_H| R| ACCEL_XOUT_H[15:8]|
|3C| 60| ACCEL_XOUT_L| R| ACCEL_XOUT_L[7:0]|
|3D| 61| ACCEL_YOUT_H| R| ACCEL_YOUT_H[15:8]|
|3E| 62| ACCEL_YOUT_L| R| ACCEL_YOUT_L[7:0]|
|3F| 63| ACCEL_ZOUT_H| R| ACCEL_ZOUT_H[15:8]|
|40| 64| ACCEL_ZOUT_L| R| ACCEL_ZOUT_L[7:0]|
|41| 65| TEMP_OUT_H| R| TEMP_OUT_H[15:8]|
|42| 66| TEMP_OUT_L| R| TEMP_OUT_L[7:0]|
|43| 67| GYRO_XOUT_H| R| GYRO_XOUT_H[15:8]|
|44| 68| GYRO_XOUT_L| R| GYRO_XOUT_L[7:0]|
|45| 69| GYRO_YOUT_H| R| GYRO_YOUT_H[15:8]|
|46| 70| GYRO_YOUT_L| R| GYRO_YOUT_L[7:0]|
|47| 71| GYRO_ZOUT_H| R| GYRO_ZOUT_H[15:8]|
|48| 72| GYRO_ZOUT_L| R| GYRO_ZOUT_L[7:0]|
つまり、リンク先では一ずつアクセスして取得していますが、参考①では3B-40まで一度に取得して変換しているのが分かります。
また、数字がおかしいのがわかりませんでしたが、答えを見ると、どうやら

```
# 平均値をオフセットにする
```
というのが怪しいので、オフセットを導入します。
通常は、積算して平均のオフセットを使うのが普通ですが、ここでは単にオフセットの効果をみたいので、最初のデータを使ってオフセットとします。
Z-軸の重力加速度を１としています。

```py
#!/usr/bin/python -u
# -*- coding: utf-8 -*-

import smbus
import time
import matplotlib.pyplot as plt

address = 0x68
channel = 1
bus     = smbus.SMBus(channel)


#unsignedを、signedに変換(16ビット限定）
def u2s(unsigneddata):
    if unsigneddata & (0x01 << 15) : 
        return -1 * ((unsigneddata ^ 0xffff) + 1)
    return unsigneddata

if __name__ == "__main__":
    # レジスタをリセットする
    bus.write_i2c_block_data(address, 0x6B, [0x80])
    time.sleep(0.1)     

    # PWR_MGMT_1をクリア
    bus.write_i2c_block_data(address, 0x6B, [0x00])
    time.sleep(0.1)

    # 加速度センサのレンジを±8gにする
    #bus.write_i2c_block_data(address, 0x1C, [0x08])

    data    = bus.read_i2c_block_data(address, 0x3B ,6)
    rawX0    = -(2.0 / 0x8000) * u2s(data[0] << 8 | data[1])
    rawY0    = -(2.0 / 0x8000) * u2s(data[2] << 8 | data[3])
    rawZ0    = -(2.0 / 0x8000) * u2s(data[4] << 8 | data[5]) + 1
    print ('|acc_X,| acc_Y,| acc_Z: |')
    print ('|:--:|:--:|:--:|')
    print ('|{0:.7f},|{1:.7f},|{2:.7f},|'.format(rawX0, rawY0, rawZ0))
    sk =0
# データを取得する
    try:
        while True:
            data    = bus.read_i2c_block_data(address, 0x3B ,6)
            rawX    = (2.0 / 0x8000) * u2s(data[0] << 8 | data[1]) + rawX0
            rawY    = (2.0 / 0x8000) * u2s(data[2] << 8 | data[3]) + rawY0
            rawZ    = (2.0 / 0x8000) * u2s(data[4] << 8 | data[5]) + rawZ0
            print ('|{0:.7f},|{1:.7f},|{2:.7f},|'.format(rawX, rawY, rawZ))
            plt.plot(sk,rawX, 'ro')
            plt.plot(sk,rawY, 'bo')
            plt.plot(sk,rawZ, 'go')
            plt.pause(1)
            sk += 1
    except KeyboardInterrupt:
        pass
    finally:
        plt.savefig('accl{}.png'.format(sk))
```
上のコードで取得した加速度です。
センサーを平行にしたり、９０度傾けたりすると、センサーの方向によって数字が以下のように変化しました。
数字がほぼ１だけ変化しているので、重力を１にしたのは、この程度の精度では妥当なようです。
![accl36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/ec70a2cc-95e1-2948-c5c0-2627c16b0064.png)

|acc_X,| acc_Y,| acc_Z: |
|:--:|:--:|:--:|
|-0.2480469,|-1.0312500,|0.6799316,|
|0.0014648,|0.0017090,|0.9997559,|
|0.0000000,|0.0007324,|1.0000000,|
|0.0000000,|-0.0029297,|0.9985352,|
|-0.0046387,|0.0046387,|0.9938965,|
|0.0017090,|-0.0012207,|0.9978027,|
|-0.0026855,|0.0051270,|1.0009766,|
|-0.0021973,|-0.0014648,|0.9902344,|
|0.0029297,|-0.0944824,|0.9956055,|
|-0.0119629,|-1.0141602,|0.2441406,|
|-0.0324707,|-1.0534668,|-0.0285645,|
|-0.0319824,|-1.0549316,|-0.0253906,|
|-0.0312500,|-1.0576172,|-0.0195312,|
|-0.0300293,|-1.0551758,|-0.0153809,|
|-0.0297852,|-1.0546875,|-0.0334473,|
|-0.0317383,|-1.0556641,|-0.0322266,|
|-0.0415039,|-1.0566406,|-0.0219727,|
|-0.0283203,|-1.0559082,|-0.0068359,|
|-0.0488281,|-1.0537109,|-0.0832520,|
|-0.0673828,|-1.0537109,|0.0244141,|
|-0.0610352,|-1.0544434,|0.0205078,|
|-0.0463867,|-1.0852051,|0.0349121,|
|-0.0612793,|-1.0527344,|-0.0390625,|
|-0.0615234,|-1.0778809,|-0.0253906,|
|-0.0366211,|-1.0515137,|0.0839844,|
|-0.0754395,|-1.0480957,|-0.1606445,|
|0.0192871,|-1.2529297,|-0.5146484,|
|0.0031738,|-0.1552734,|-1.0761719,|
|0.0915527,|-0.1540527,|-1.0302734,|
|0.1247559,|-0.1457520,|-1.0219727,|
|0.0351562,|-0.1464844,|-1.0195312,|
|0.0625000,|-0.1503906,|-1.0310059,|
|-0.0339355,|-0.5021973,|-0.8676758,|
|-0.0546875,|-0.7507324,|0.7204590,|
|0.0048828,|-0.0019531,|0.9763184,|
|0.0043945,|0.0031738,|0.9875488,|
|0.0021973,|0.0000000,|0.9934082,|
|0.0051270,|0.0007324,|0.9934082,|
グラフを工夫すれば以下のような絵もえられます。
![accl71.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/d38dcae4-99d9-9e03-50fa-eb0d6aa568b3.png)
**これを利用すれば、物体の方向の監視や制御ができそうです。ひも付きだけど**
###・温度の測定
上記のデータシートを見れば温度のaddressから、以下のコードで計測できる。
しかし、計測値と温度の関係式は感度などが個別の素子でことなるから、係数は独自に校正する必要がある。
以下では、単純に室温を再現するもっとも簡単な式で算出している。

```get_temp.py
import smbus
import time

address = 0x68
channel = 1
bus     = smbus.SMBus(channel)

# レジスタをリセットする
bus.write_i2c_block_data(address, 0x6B, [0x80])
time.sleep(0.1)     

# PWR_MGMT_1をクリア
bus.write_i2c_block_data(address, 0x6B, [0x00])
time.sleep(0.1)

# 生データを取得する
while True:
    data    = bus.read_i2c_block_data(address, 0x41 ,2)
    raw    = data[0] << 8 | data[1]    # 上位ビットが先
    Temp_real=(raw/130)
    print( "%+8.7f" % Temp_real + "   ",)
    time.sleep(1)
```

ネット上には以下の係数が使われているコードがあるが、参考でしかない。    
[Temperature=((data-21)/333.87)+21; ](https://os.mbed.com/users/kylongmu/code/MPU9250_SPI/file/084e8ba240c1/MPU9250.cpp/)

[temperature = ((float) tempCount) / 333.87f + 21.0f; // Temperature in degrees Centigrade ](https://github.com/kriswiner/MPU9250/blob/master/STM32F401/main.cpp)

[Temperature=(data/340)+36.53;](https://os.mbed.com/users/kylongmu/code/MPU9250_SPI/file/084e8ba240c1/MPU9250.cpp/)
あくまで以下の3個のパラメータを利用する温度範囲で決めるべきである。
※通常は、０℃、１００℃、３７℃、室温などが使われるが、センサーが水にふれたくないので工夫が必要だ
　TEMP＿OUTが計測値



```math
\textrm{TEMP_degC} = \frac{\textrm{TEMP_OUT – RoomTemp_Offset}}{\textrm{Temp_Sensitivity}} + \textrm{21degC} \\

例）　\textrm{temp} = \frac{\textrm{raw-21℃の時のセンサー読み}}{333.87} + 21
```
###・角速度の測定
データシートから上の延長で計測できるのは、gyroである。
４３ー４８を測定すればよい。
測定パラメータ条件は以下のとおり
　●ジャイロ
　・測定レンジ ±250 / ±500 / ±1000 / ±2000dps（°/sec）
　・分解能：16ビット
　・出力レート：4～8000Hz

```py
#!/usr/bin/python -u
# -*- coding: utf-8 -*-

import smbus
import time
import matplotlib.pyplot as plt

address = 0x68
channel = 1
bus     = smbus.SMBus(channel)


#unsignedを、signedに変換(16ビット限定）
def u2s(unsigneddata):
    if unsigneddata & (0x01 << 15) : 
        return -1 * ((unsigneddata ^ 0xffff) + 1)
    return unsigneddata

if __name__ == "__main__":
    # レジスタをリセットする
    bus.write_i2c_block_data(address, 0x6B, [0x80])
    time.sleep(0.1)     

    # PWR_MGMT_1をクリア
    bus.write_i2c_block_data(address, 0x6B, [0x00])
    time.sleep(0.1)

    # センサのレンジを±1000degps default; ±250degpsにする
    #bus.write_i2c_block_data(address, 0x1B, [0x10])

    data    = bus.read_i2c_block_data(address, 0x43 ,6)
    rawX0    = -(250 / 0x8000) * u2s(data[0] << 8 | data[1])
    rawY0    = -(250 / 0x8000) * u2s(data[2] << 8 | data[3])
    rawZ0    = -(250 / 0x8000) * u2s(data[4] << 8 | data[5])
    print ('|acc_X,| acc_Y,| acc_Z: |')
    print ('|:--:|:--:|:--:|')
    print ('|{0:.7f},|{1:.7f},|{2:.7f},|'.format(rawX0, rawY0, rawZ0))
    sk =0
    plt.plot(sk,rawX0, 'ro', label = 'gyro_X')
    plt.plot(sk,rawY0, 'bo', label = 'gyro_Y')
    plt.plot(sk,rawZ0, 'go', label = 'gyro_Z')
    plt.legend()
    # データを取得する
    try:
        while True:
            data    = bus.read_i2c_block_data(address, 0x43 ,6)
            rawX    = (250 / 0x8000) * u2s(data[0] << 8 | data[1]) + rawX0
            rawY    = (250 / 0x8000) * u2s(data[2] << 8 | data[3]) + rawY0
            rawZ    = (250 / 0x8000) * u2s(data[4] << 8 | data[5]) + rawZ0
            print ('|{0:.7f},|{1:.7f},|{2:.7f},|'.format(rawX, rawY, rawZ))
            plt.plot(sk,rawX, 'ro')
            plt.plot(sk,rawY, 'bo')
            plt.plot(sk,rawZ, 'go')
            plt.pause(1)
            sk += 1
    except KeyboardInterrupt:
        pass
    finally:
        plt.savefig('gyro{}.png'.format(sk))
 ```
以下は適当に動かしたときの図       
![gyro93.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/f581c6be-c78c-ce7a-fbcd-a51804cd6d06.png)


###・地磁気の測定
　●コンパス（AK8963）
　・測定レンジ：±4800μT
　・分解能：14ビット/16ビット
　・連続変換モードあり
[AK8963データシート](https://strawberry-linux.com/pub/AK8963.pdf)
**地磁気の並びは上のものとは異なり、番号が若い方からL→Hに並んでいる。**

|名前| アドレス|READ/WRITE|内容|ビット幅|説明|
|:-:|:-:|:-:|:-:|:-:|:-:|
|WIA| 00H| READ|デバイスID| 8|
|INFO| 01H| READ| インフォメーション| 8|
|ST1| 02H| READ| ステータス1| 8 |データステータス|
|HXL| 03H| READ| 測定データ |8| X軸データ|
|HXH| 04H| ||8|
|HYL| 05H| ||8| Y軸データ
|HYH| 06H| ||8|
|HZL| 07H| ||8| Z軸データ
|HZH| 08H| ||8|
|ST2 |09H| READ| ステータス2| 8| データステータス|

```py
#mpu9250.py より引用
#https://qiita.com/K-Ponta/items/507b1a655a3489663bc8
#!/usr/bin/python3 -u
# -*- coding: utf-8 -*-

import smbus
import time
import matplotlib.pyplot as plt

class SL_MPU9250:
    # 定数宣言
    REG_PWR_MGMT_1      = 0x6B
    REG_INT_PIN_CFG     = 0x37

    MAG_MODE_POWERDOWN  = 0         # 磁気センサpower down
    MAG_MODE_SERIAL_2   = 2         # 磁気センサ100Hz連続測定モード

    MAG_ACCESS          = False     # 磁気センサへのアクセス可否
    MAG_MODE            = 0         # 磁気センサモード
    MAG_BIT             = 14        # 磁気センサが出力するbit数

    magRange            = 4912      # 'μT'  

    # コンストラクタ
    def __init__(self, address, channel):
        self.address    = address
        self.channel    = channel
        self.bus        = smbus.SMBus(self.channel)
        self.addrAK8963 = 0x0C
        # Sensor initialization
        self.resetRegister()
        self.powerWakeUp()
        self.magCoefficient16   = self.magRange   / 32760.0   # センシングされたDecimal値をμTに変換する係数(16bit時)

    # レジスタを初期設定に戻します。
    def resetRegister(self):
        if self.MAG_ACCESS == True:
            self.bus.write_i2c_block_data(self.addrAK8963, 0x0B, [0x01])    
        self.bus.write_i2c_block_data(self.address, 0x6B, [0x80])
        time.sleep(0.1)
        # DLPF設定
        self.bus.write_i2c_block_data(self.address, 0x1A, [0x00])
        self.MAG_ACCESS = False
        time.sleep(0.1)

    # レジスタをセンシング可能な状態にします。
    def powerWakeUp(self):
        # PWR_MGMT_1をクリア
        self.bus.write_i2c_block_data(self.address, self.REG_PWR_MGMT_1, [0x00])
        time.sleep(0.1)
        # I2Cで磁気センサ機能(AK8963)へアクセスできるようにする(BYPASS_EN=1)
        self.bus.write_i2c_block_data(self.address, self.REG_INT_PIN_CFG, [0x02])
        self.MAG_ACCESS = True
        time.sleep(0.1)

    # 磁気センサのレジスタを設定する
    def setMagRegister(self, _mode, _bit):      
        if self.MAG_ACCESS == False:
            # 磁気センサへのアクセスが有効になっていないので例外を上げる
            raise Exception('001 Access to a sensor is invalid.')

        _writeData  = 0x00
        # 測定モードの設定
        if _mode=='100Hz':        # 連続測定モード２
            _writeData      = 0x06
            self.MAG_MODE   = self.MAG_MODE_SERIAL_2

        #　出力するbit数 
        # _bit='16bit'      # 16bit 出力
        _writeData      = _writeData | 0x10
        self.MAG_BIT    = 16

        self.bus.write_i2c_block_data(self.addrAK8963, 0x0A, [_writeData])

    #センサからのデータはそのまま使おうとするとunsignedとして扱われるため、signedに変換(16ビット限定）
    def u2s(self,unsigneddata):
        if unsigneddata & (0x01 << 15) : 
            return -1 * ((unsigneddata ^ 0xffff) + 1)
        return unsigneddata
 
    def getMag(self):
        if self.MAG_ACCESS == False:
            # 磁気センサが有効ではない。
            raise Exception('002 Access to a sensor is invalid.')

        # 事前処理
        if self.MAG_MODE==self.MAG_MODE_SERIAL_2:
            status  = self.bus.read_i2c_block_data(self.addrAK8963, 0x02 ,1)
            if (status[0] & 0x02) == 0x02:
                # データオーバーランがあるので再度センシング
                self.bus.read_i2c_block_data(self.addrAK8963, 0x09 ,1)

        # ST1レジスタを確認してデータ読み出しが可能か確認する。
        status  = self.bus.read_i2c_block_data(self.addrAK8963, 0x02 ,1)
        while (status[0] & 0x01) != 0x01:
            # データレディ状態まで待つ
            time.sleep(0.01)
            status  = self.bus.read_i2c_block_data(self.addrAK8963, 0x02 ,1)

        # データ読み出し
        data    = self.bus.read_i2c_block_data(self.addrAK8963, 0x03 ,7)
        rawX    = self.u2s(data[1] << 8 | data[0])  # 下位bitが先
        rawY    = self.u2s(data[3] << 8 | data[2])  # 下位bitが先
        rawZ    = self.u2s(data[5] << 8 | data[4])  # 下位bitが先
        st2     = data[6]

        # オーバーフローチェック
        if (st2 & 0x08) == 0x08:
            # オーバーフローのため正しい値が得られていない
            raise Exception('004 Mag sensor over flow')

        # μTへの変換
        rawX    = rawX * self.magCoefficient16
        rawY    = rawY * self.magCoefficient16
        rawZ    = rawZ * self.magCoefficient16

        return rawX, rawY, rawZ


if __name__ == "__main__":
    sensor  = SL_MPU9250(0x68,1)
    sk =0
    try:
        sensor.resetRegister()
        sensor.powerWakeUp()
        sensor.setMagRegister('100Hz','16bit')
        print ('|i|mag_X,| mag_Y,| mag_Z: |')
        print ('|:--:|:--:|:--:|:--:|')
        mag     = sensor.getMag()
        plt.plot(sk,mag[0], 'ro', label = 'mag_X')
        plt.plot(sk,mag[1], 'bo', label = 'mag_Y')
        plt.plot(sk,mag[2], 'go', label = 'mag_Z')
        plt.legend()
        while True:
            now     = time.time()
            mag     = sensor.getMag()
            print ('|{0:d},|{1[0]:.7f},|{1[1]:.7f},|{1[2]:.7f},|'.format(sk,mag))
            plt.plot(sk,mag[0], 'ro')
            plt.plot(sk,mag[1], 'bo')
            plt.plot(sk,mag[2], 'go')
            plt.pause(1)
            sk += 1
            sleepTime       = 0.5 - (time.time() - now)
            if sleepTime < 0.:
                continue
            time.sleep(sleepTime)|
            
    except KeyboardInterrupt:
        pass
    finally:
        plt.savefig('mag{}.png'.format(sk))
```
センサーをぐるぐる方向をかえてみる、さて北はどっちだ？
![mag98.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/60a39d5c-1f3e-3b17-9071-1309be3b321b.png)

なんか分け分からないなと思ったが、このあたりの地磁気の偏角９度、伏角５０度もあるんだね。
水平成分３０μT　鉛直成分　３６μT　全磁力　４６．５μTなので大体測れていそうです。
[磁気図@国土地理院](https://www.gsi.go.jp/buturisokuchi/menu03_magnetic_chart.html)

|i|mag_X,| mag_Y,| mag_Z: |
|:--:|:--:|:--:|:--:|
|0,|16.4932845,|25.7894994,|-1.4993895,|
|1,|15.5936508,|25.7894994,|-0.8996337,|
|2,|16.1934066,|25.7894994,|-0.2998779,|
|3,|16.9431013,|26.8390720,|-0.1499389,|
|4,|17.2429792,|25.3396825,|-0.7496947,|
|5,|15.8935287,|25.4896215,|-1.7992674,|
|6,|17.6927961,|25.4896215,|-0.2998779,|
|7,|16.0434676,|25.0398046,|-0.4498168,|
|8,|17.3929182,|24.5899878,|-0.5997558,|
|9,|16.6432234,|27.1389499,|-0.1499389,|
|10,|18.2925519,|31.1873016,|-2.0991453,|
|11,|19.1921856,|32.6866911,|0.0000000,|
|12,|20.3916972,|34.4859585,|-1.1995116,|
|13,|21.7411477,|37.0349206,|0.1499389,|
|14,|23.9902320,|35.9853480,|0.0000000,|
|15,|24.4400488,|37.3347985,|-0.7496947,|
|16,|22.7907204,|37.1848596,|0.2998779,|
|17,|23.2405372,|36.4351648,|0.1499389,|
|18,|22.7907204,|37.1848596,|-0.2998779,|
|19,|21.7411477,|34.9357753,|-0.7496947,|
|20,|27.8886447,|39.2840049,|-0.8996337,|
|21,|34.0361416,|45.7313797,|-1.6493284,|
|22,|34.7858364,|44.6818071,|-0.2998779,|
|23,|36.5851038,|45.2815629,|-1.1995116,|
|24,|39.7338217,|45.7313797,|-1.6493284,|
|25,|38.6842491,|45.8813187,|0.0000000,|
|26,|38.9841270,|44.9816850,|-2.0991453,|
|27,|38.5343101,|45.1316239,|-0.1499389,|
|28,|39.2840049,|43.4822955,|0.0000000,|
|29,|39.5838828,|44.6818071,|-0.8996337,|
|30,|39.8837607,|44.0820513,|-1.4993895,|
|31,|35.6854701,|44.3819292,|-1.7992674,|
|32,|40.6334554,|45.7313797,|-0.7496947,|
|33,|40.6334554,|44.5318681,|0.1499389,|
|34,|42.5826618,|44.0820513,|-2.3990232,|
|35,|41.9829060,|44.9816850,|-1.1995116,|
|36,|41.0832723,|45.2815629,|-1.1995116,|
|37,|40.6334554,|45.7313797,|-1.3494505,|
|38,|41.2332112,|46.0312576,|-2.5489621,|
|39,|40.7833944,|44.3819292,|-2.3990232,|
|40,|40.4835165,|45.8813187,|-2.6989011,|
|41,|41.0832723,|44.6818071,|-1.1995116,|
|42,|36.7350427,|42.7326007,|1.6493284,|
|43,|35.2356532,|43.9321123,|-1.3494505,|
|44,|36.4351648,|49.6297924,|-10.3457875,|
|45,|40.3335775,|46.3311355,|-41.2332112,|
|46,|44.2319902,|44.5318681,|-40.6334554,|
|47,|45.1316239,|41.2332112,|-42.7326007,|
|48,|44.3819292,|41.3831502,|-41.3831502,|
|49,|45.5814408,|40.7833944,|-42.8825397,|
|50,|44.6818071,|41.3831502,|-44.0820513,|
|51,|44.9816850,|39.8837607,|-44.0820513,|
|52,|44.9816850,|40.4835165,|-44.6818071,|
|53,|37.3347985,|50.2295482,|-13.0446886,|
|54,|35.3855922,|44.6818071,|-2.3990232,|
|55,|42.2827839,|18.8923077,|14.6940171,|
|56,|41.6830281,|6.2974359,|12.5948718,|
|57,|42.5826618,|0.2998779,|9.8959707,|
|58,|39.8837607,|2.0991453,|10.1958486,|
|59,|39.2840049,|1.1995116,|10.1958486,|
|60,|39.8837607,|2.0991453,|11.0954823,|
|61,|40.7833944,|7.1970696,|12.2949939,|
|62,|40.3335775,|9.1462759,|12.7448107,|
|63,|37.3347985,|15.7435897,|14.2442002,|
|64,|40.4835165,|46.7809524,|-2.3990232,|
|65,|40.7833944,|46.7809524,|-1.7992674,|
|66,|44.6818071,|44.9816850,|-1.1995116,|
|67,|48.5802198,|47.9804640,|-4.1982906,|
|68,|46.0312576,|39.7338217,|-45.4315018,|
|69,|47.5306471,|38.8341880,|-46.0312576,|
|70,|46.7809524,|38.6842491,|-46.4810745,|
|71,|45.8813187,|38.0844933,|-47.0808303,|
|72,|46.4810745,|37.1848596,|-46.4810745,|
|73,|48.1304029,|38.8341880,|-46.6310134,|
|74,|47.9804640,|38.6842491,|-44.6818071,|
|75,|48.2803419,|38.0844933,|-45.5814408,|
|76,|43.3323565,|43.3323565,|-43.6322344,|
|77,|25.1897436,|40.1836386,|-39.5838828,|
|78,|25.0398046,|47.8305250,|-27.4388278,|
|79,|17.8427350,|38.5343101,|-30.1377289,|
|80,|16.0434676,|38.5343101,|-24.4400488,|
|81,|16.6432234,|39.1340659,|-25.3396825,|
|82,|16.3433455,|39.7338217,|-24.4400488,|
|83,|16.9431013,|40.0336996,|-24.1401709,|
|84,|16.7931624,|38.3843712,|-23.6903541,|
|85,|17.3929182,|41.3831502,|-26.3892552,|
|86,|18.1426129,|38.5343101,|-23.8402930,|
|87,|16.0434676,|22.9406593,|-0.7496947,|
|88,|16.6432234,|23.2405372,|-0.7496947,|
|89,|16.7931624,|22.7907204,|0.8996337,|
|90,|15.8935287,|22.7907204,|-0.5997558,|
|91,|16.4932845,|23.9902320,|-0.5997558,|
|92,|17.0930403,|22.7907204,|0.5997558,|
|93,|17.2429792,|24.1401709,|-0.1499389,|
|94,|15.8935287,|23.6903541,|0.5997558,|
|95,|17.2429792,|24.1401709,|-0.4498168,|
|96,|16.3433455,|23.2405372,|-0.7496947,|
|97,|16.9431013,|23.5404151,|-0.1499389,|
|98,|16.6432234,|24.1401709,|-1.0495726,|

以下の図のX-Y-Z-軸をよくみて回転しつつ測らないとほんとのところは分からないという印象です。

![51I7i7llQjL._AC_SL1010_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/05bb20a3-f6f9-33df-e278-15a6bf31ab7b.jpeg)
###まとめ
・MPU9250　9軸センサーをRasPi4で動かしてみた
・加速度センサーは一応測れているようだ
・温度と角速度、そして地磁気は測れたが、もう一つしっくりしない

・いずれにしても、もう少し信頼できるよう校正したいと思う
・これらを利用したおもちゃを動かしてみたい