はじめに
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
加速度センサのプログラム
データを受け取る
#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
ジャイロセンサのプログラム
データを受け取るための設定
# データを取得する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()
取得したデータ
傾けずに地面に置いた場合
Z軸の加速度が約9[$m/s^2$]になっており,重力加速度がかかっていることが分かります.
同様に横,縦に傾けた結果,Y軸,X軸の値が約10[$m/s^2$]になっており,重力加速度を測定できていることが分かります.
参考にしたサイト
概要 — MicroPython latest ドキュメント : https://micropython-docs-ja.readthedocs.io/ja/latest/index.html
加速度センサ - garretlab - FC2 : https://garretlab.web.fc2.com/arduino/lab/acceleration_sensor/
3軸ジャイロセンサーL3GD20Hの使い方(I2C通信/SPI通信) | 初心者のためのセンサーと測定入門 : https://s-design-tokyo.com/use_l3gd20h_i2c/