ESP32でMicroPythonを用いて，KXM52-1050(加速度センサ)，L3GD20H(ジャイロセンサ)を利用する．

# はじめに
　ESP32でMicroPythonを利用して加速度と角速度を得るために，加速度センサ(KXM52-1050)，ジャイロセンサ(L3GD20H)を利用します．
  プログラムエディタはThonnyを利用しました．
 　ESP32でMicroPythonが使用できる前提で話を進めていきます．
  　以下のモジュールをインポートしています．
```
from machine import ADC, PWM, Pin, I2C
import time
```
Thoonyで開くことを前提にしており，Ctrl + Cでデータの取得を終了するようにしています．
   
# 加速度センサ(KXM52-1050)
## ESP32とKXM52-1050の接続方法
KXM52-1050のピン
1 ... ESP32の3.3V電源，KXM52-1050の2PIN
2 ... KXM52-1050の1PIN
3 ... ESP32のGND，KXM52-1050の4PIN
4 ... KXM52-1050の4PIN
5 ... なし
6 ... ESP32の34PIN
7 ... ESP32の39PIN
8 ... ESP32の36PIN

![加速度センサ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562115/8f8e99ed-6a0d-6c41-f508-4cd3ba0d7642.png)

## 加速度センサのプログラム
データを受け取る
```
#3軸それぞれの加速度データ受け取り
z = ADC(Pin(36, Pin.IN), atten=ADC.ATTN_11DB)
y = ADC(Pin(39, Pin.IN), atten=ADC.ATTN_11DB)
x = ADC(Pin(34, Pin.IN), atten=ADC.ATTN_11DB)

# 0-65535の範囲の整数を返す
x_v = x.read_u16()
y_v = y.read_u16()
z_v = z.read_u16()
```

センサのデータを[$m/s^2$]に変換する変数
```
def kasoku(v):
    V = v * (3.55 / 65535)
    ag = (V - 1.65) / 660 * 1000
    a = ag * 9.8
    return a
```
加速度センサ全体のプログラム
```
def kasoku(v):
    V = v * (3.55 / 65535)
    ag = (V - 1.65) / 660 * 1000
    a = ag * 9.8
    return a

 #3軸それぞれの加速度データ受け取り
z = ADC(Pin(36, Pin.IN), atten=ADC.ATTN_11DB)
y = ADC(Pin(39, Pin.IN), atten=ADC.ATTN_11DB)
x = ADC(Pin(34, Pin.IN), atten=ADC.ATTN_11DB)

# 0-65535の範囲の整数を返す
x_v = x.read_u16()
y_v = y.read_u16()
z_v = z.read_u16()
nowtime = time.ticks_ms() - first_time
        
# センサデータを加速度[m/s^2]へ変換する
x_val = kasoku(x_v)
y_val = kasoku(y_v)
z_val = kasoku(z_v)
```

# ジャイロセンサ(L3GD20H)
## ESP32とL3GD20Hの接続方法
1 ... ESP32の3.3V電源および，10k抵抗を利用してL3GD20Hの5PIN
2 ... ESP32の22PIN
3 ... ESP32の21PIN
4 ... L3GD20Hの8PIN
5 ... 10k抵抗を利用してL3GD20Hの1PIN
6 ... なし
7 ... なし
8 ... ESP32のGDNおよび，L3GD20Hの4PIN

![ジャイロセンサ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562115/56c1215e-c061-8fdd-4202-cf4219116711.png)

## ジャイロセンサのプログラム

データを受け取るための設定
```
# データを取得するESP-32のピンを設定する
p21 = Pin(21, Pin.IN, Pin.PULL_UP)
p22 = Pin(22, Pin.IN, Pin.PULL_UP)

# I2C通信を行うピンの設定を行う
i2c = I2C(scl=Pin(22), sda=Pin(21))  # sclピンとsdaピンを使用

# デバイスのI2Cアドレス
device_address = 0x6A  # 書き込み先アドレスを指定する変数

# データを書き込む
data_to_write = b'\x0F'  # 書き込むデータをバイト列で指定
i2c.writeto_mem(device_address, 0x20, data_to_write)
data_to_write = b'\x20'
i2c.writeto_mem(device_address, 0x23, data_to_write)

# 読み込み先アドレスを格納する変数
ANGULAR_VELOCITY_REG = 0x28
```

データを受け取り，値を[$deg/s$]に変換する
```
#角速度データ受け取り
xl = i2c.readfrom_mem(device_address, 0x28, 1)
xh = i2c.readfrom_mem(device_address, 0x29, 1)
yl = i2c.readfrom_mem(device_address, 0x2A, 1)
yh = i2c.readfrom_mem(device_address, 0x2B, 1)
zl = i2c.readfrom_mem(device_address, 0x2C, 1)
zh = i2c.readfrom_mem(device_address, 0x2D, 1)
        
# センサデータを、合成する
wx = xh[0] << 8 | xl[0]
wy = yh[0] << 8 | yl[0]
wz = zh[0] << 8 | zl[0]
        
if wx >= 32768:
    wx = wx - 65536
if wy >= 32768:
    wy = wy - 65536
if wz >= 32768:
    wz = wz - 65536
        
angular_velocity_x = wx * 0.07
angular_velocity_y = wy * 0.07
angular_velocity_z = wz * 0.07
```

ジャイロセンサ全体のプログラム
```
# データを取得するESP-32のピンを設定する
p21 = Pin(21, Pin.IN, Pin.PULL_UP)
p22 = Pin(22, Pin.IN, Pin.PULL_UP)

# I2C通信を行うピンの設定を行う
i2c = I2C(scl=Pin(22), sda=Pin(21))  # sclピンとsdaピンを使用

# デバイスのI2Cアドレス
device_address = 0x6A  # 書き込み先アドレスを指定する変数

# データを書き込む
data_to_write = b'\x0F'  # 書き込むデータをバイト列で指定
i2c.writeto_mem(device_address, 0x20, data_to_write)
data_to_write = b'\x20'
i2c.writeto_mem(device_address, 0x23, data_to_write)

# 読み込み先アドレスを格納する変数
ANGULAR_VELOCITY_REG = 0x28

#角速度データ受け取り
xl = i2c.readfrom_mem(device_address, 0x28, 1)
xh = i2c.readfrom_mem(device_address, 0x29, 1)
yl = i2c.readfrom_mem(device_address, 0x2A, 1)
yh = i2c.readfrom_mem(device_address, 0x2B, 1)
zl = i2c.readfrom_mem(device_address, 0x2C, 1)
zh = i2c.readfrom_mem(device_address, 0x2D, 1)
        
# センサデータを、合成する
wx = xh[0] << 8 | xl[0]
wy = yh[0] << 8 | yl[0]
wz = zh[0] << 8 | zl[0]
        
if wx >= 32768:
    wx = wx - 65536
if wy >= 32768:
    wy = wy - 65536
if wz >= 32768:
    wz = wz - 65536
        
angular_velocity_x = wx * 0.07
angular_velocity_y = wy * 0.07
angular_velocity_z = wz * 0.07
```

## 実装

取得時間を計測するために，データを取得し始める前に開始時間を持つ変数を作成します．

```
#開始時間を取得する
first_time = time.ticks_ms()

#経過時間の計算
nowtime = time.ticks_ms() - first_time
```

データをテキストファイルとして保存するために，ファイルに書き込みを行えるようにし，データの取得終了時にファイルを閉ます．
```
# 取得データの書き込み先のファイルを開く
f = open('data_test.txt', 'w')

#ファイルを閉じる
f.close()
```

加速度センサおよび，角速度センサを取得し続けるためのプログラム全体
```
# 必要なモジュールをインポートする
from machine import ADC, PWM, Pin, I2C
import time

# センサから取得したデータを加速度[m/s^2]に変換する
def kasoku(v):
    V = v * (3.55 / 65535)
    ag = (V - 1.65) / 660 * 1000
    a = ag * 9.8
    return a

###################################################################
#角速度変数

# データを取得するESP-32のピンを設定する
p21 = Pin(21, Pin.IN, Pin.PULL_UP)
p22 = Pin(22, Pin.IN, Pin.PULL_UP)

# I2C通信を行うピンの設定を行う
i2c = I2C(scl=Pin(22), sda=Pin(21))  # sclピンとsdaピンを使用

# デバイスのI2Cアドレス
device_address = 0x6A  # 書き込み先アドレスを指定する変数

# データを書き込む
data_to_write = b'\x0F'  # 書き込むデータをバイト列で指定
i2c.writeto_mem(device_address, 0x20, data_to_write)
data_to_write = b'\x20'
i2c.writeto_mem(device_address, 0x23, data_to_write)

# 読み込み先アドレスを格納する変数
ANGULAR_VELOCITY_REG = 0x28

####################################################################

# 経過時間を調べるためにデータ取得開始時間を取得する
first_time = time.ticks_ms()

# 取得データの書き込み先のファイルを開く
f = open('data_test.txt', 'w')

# Ctrl + Cで停止させた後に、ファイルに書き込むためにtry文でwhileを回す
try:
    while True:
        #########################################################################################
        #3軸それぞれの加速度データ受け取り
        z = ADC(Pin(36, Pin.IN), atten=ADC.ATTN_11DB)
        y = ADC(Pin(39, Pin.IN), atten=ADC.ATTN_11DB)
        x = ADC(Pin(34, Pin.IN), atten=ADC.ATTN_11DB)

        # 0-65535の範囲の整数を返す
        x_v = x.read_u16()
        y_v = y.read_u16()
        z_v = z.read_u16()
        
        # センサデータを加速度[m/s^2]へ変換する
        x_val = kasoku(x_v)
        y_val = kasoku(y_v)
        z_val = kasoku(z_v)
        #########################################################################################
        #角速度データ受け取り
        xl = i2c.readfrom_mem(device_address, 0x28, 1)
        xh = i2c.readfrom_mem(device_address, 0x29, 1)
        yl = i2c.readfrom_mem(device_address, 0x2A, 1)
        yh = i2c.readfrom_mem(device_address, 0x2B, 1)
        zl = i2c.readfrom_mem(device_address, 0x2C, 1)
        zh = i2c.readfrom_mem(device_address, 0x2D, 1)
        
        # センサデータを、合成する
        wx = xh[0] << 8 | xl[0]
        wy = yh[0] << 8 | yl[0]
        wz = zh[0] << 8 | zl[0]
        
        if wx >= 32768:
            wx = wx - 65536
        if wy >= 32768:
            wy = wy - 65536
        if wz >= 32768:
            wz = wz - 65536
        
        angular_velocity_x = wx * 0.07
        angular_velocity_y = wy * 0.07
        angular_velocity_z = wz * 0.07
        #########################################################################################
        #経過時間の計算
        nowtime = time.ticks_ms() - first_time
        
        #ファイルへの書き込み
        f.write(str(nowtime) + ", " + str(x_val) + ", " + str(y_val) + ", " + str(z_val) + ", " + str(angular_velocity_x) + ", " + str(angular_velocity_y) + ", " + str(angular_velocity_z) + "\n")
        #シェルへの書き込み
        print(str(nowtime) + ", X: " + str(x_val) + ", Y: " + str(y_val) + ", Z:" + str(z_val) + ", WX:" + str(angular_velocity_x) + ", WY" + str(angular_velocity_y) +  ", WZ" + str(angular_velocity_z))
        
        time.sleep(0.03)
finally:
    f.close()
```

# 取得したデータ

傾けずに地面に置いた場合
![zkita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562115/0814ef04-e0c3-3885-7368-ffd24d01fc56.png)
Z軸の加速度が約9[$m/s^2$]になっており，重力加速度がかかっていることが分かります．

![y_kita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562115/39e1349d-fb1b-fb42-12b4-cf17b8b5f7b0.png)

![xkita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562115/7c003b17-6f73-3dab-0161-c2a4280cb364.png)

同様に横，縦に傾けた結果，Y軸，X軸の値が約10[$m/s^2$]になっており，重力加速度を測定できていることが分かります．

# 参考にしたサイト
[概要 — MicroPython latest ドキュメント : https://micropython-docs-ja.readthedocs.io/ja/latest/index.html](https://micropython-docs-ja.readthedocs.io/ja/latest/index.html)
[加速度センサ - garretlab - FC2 : https://garretlab.web.fc2.com/arduino/lab/acceleration_sensor/](https://garretlab.web.fc2.com/arduino/lab/acceleration_sensor/)
[3軸ジャイロセンサーL3GD20Hの使い方（I2C通信／SPI通信） | 初心者のためのセンサーと測定入門 : https://s-design-tokyo.com/use_l3gd20h_i2c/](https://s-design-tokyo.com/use_l3gd20h_i2c/)