目次
販売リンク、データシート
秋月電子で買いました、以下リンクです
開発環境
Raspberry Pi 4 Model B
OS : 2024-10-22-raspios-bullseye-armhf
python 3.10
ラズパイへの接続方法
Raspberry PiはI2C通信用のピンを備えています
I2Cとは、マイコン間で主に使用される通信方式の一つです
ADXL367はI2C通信で情報をやり取りできるので、Raspberry PiとADXL367をI2C通信できるように接続します

I2Cの有効化
Raspberry PiのI2Cはデフォルトでは無効になっているので、設定を変更して有効にします
以下のコマンドを使用してラズパイの設定を変更します
raspi-config

Interfacing Options -> I2C -> Yes を選択してI2Cを有効化します
設定できたら、左右矢印でFinishを選択して、エンターキーを押して、raspi-configを終わります
コードを動かすための前準備
PythonからI2Cをコントロールするためのライブラリ「smbus」のインストール
$ sudo apt install python-smbus
もろもろの計算用にnumpyのインストール
$ sudo apt install python-numpy
コード
ADXL367を動かして加速度のデータを取得するためのコードは以下の通りです
# -*- coding: utf-8 -*-
# 使用センサー: ADXL367
import math
import time
import numpy as np
import smbus
class LowGAcc3:
def __init__(self, calibrated=False, offset_list = [[0 for _ in range(10)] for _ in range(3)]):
self.calibrated = calibrated
self.offset_list = offset_list
self.acc_x = 0
self.acc_y = 0
self.acc_z = 0
self.acc_norm = 0
# self.ADDR = 0x1d
self.ADDR = 0x53
self.i2c = smbus.SMBus(1)
# センサーの諸設定
self.i2c.write_byte_data(self.ADDR, 0x2C, 0x03) # output data rate 100 Hz
self.i2c.write_byte_data(self.ADDR, 0x2D, 0x02)
time.sleep(0.5)
def apply_offset_list(offset_list, x, y, z):
xyz_array = np.array([x, y, z])
for i, offset in enumerate(offset_list):
offset_array = np.array(offset)
xyz_array[i] -= np.mean(offset_array)
return tuple(xyz_array)
def get_calibration_data(self):
calibration_iter = 10
for _ in range(calibration_iter):
x, y, z = self.get_acc_raw()
self.offset_list[0].append(x)
self.offset_list[1].append(y)
self.offset_list[2].append(z-1.0)
print(self.offset_list)
self.calibrated = True
def get_acc_raw(self):
# 単位はGです
try:
#データ読み込み
xh = self.i2c.read_byte_data(self.ADDR, 0x0E)
xl = self.i2c.read_byte_data(self.ADDR, 0x0F)
yh = self.i2c.read_byte_data(self.ADDR, 0x10)
yl = self.i2c.read_byte_data(self.ADDR, 0x11)
zh = self.i2c.read_byte_data(self.ADDR, 0x12)
zl = self.i2c.read_byte_data(self.ADDR, 0x13)
#データ変換
x = (xh << 6) | (xl >> 2)
y = (yh << 6) | (yl >> 2)
z = (zh << 6) | (zl >> 2)
#極性判断
if x >= 8192:
x = x - 16384
if y >= 8192:
y = y - 16384
if z >= 8192:
z = z - 16384
#物理量(加速度[g])に変換
x = x * 2 / 8191 # 2g設定
y = y * 2 / 8191
z = z * 2 / 8191
self.acc_x = x
self.acc_y = y
self.acc_z = z
self.acc_norm = math.sqrt(x**2 + y**2 + z**2)
except IOError as e:
print("I/O error({0}): {1}".format(e.errno, e.strerror))
return x, y, z, math.sqrt(x**2+y**2+z**2)
def get_acc_calibrated(self):
if not self.calibrated:
print("set calibration data!")
return
x, y, z = self.get_acc_raw()
x, y, z = self.apply_offset_list(self.offset_list, x, y, z)
self.acc_x = x
self.acc_y = y
self.acc_z = z
self.acc_norm = math.sqrt(x**2 + y**2 + z**2)
return x, y, z, math.sqrt(x**2 + y**2 + z**2)
def main():
low_g_acc = LowGAcc3()
while True:
out_x, out_y, out_z, norm = low_g_acc.get_acc_raw()
print(f"{out_x}, {out_y}, {out_z}, {norm}")
time.sleep(0.1)
def test_calib():
low_g_acc = LowGAcc3()
low_g_acc.get_calibration_data()
out_x, out_y, out_z, norm = low_g_acc.get_acc_calibrated()
print(f"{out_x}, {out_y}, {out_z}, {norm}")
print("offset_list:")
print(low_g_acc.offset_list)
if __name__ == "__main__":
main()
起こりやすいエラーとその対処
このコードを実行したときにこんな I/O error が表示されることがあります
$ python adxl367.py
Traceback (most recent call last):
File "/home/pi/adxl367.py", line 124, in <module>
main()
File "/home/pond/adxl367.py", line 106, in main
low_g_acc = LowGAcc3()
^^^^^^^^^^
File "/home/pi/adxl367.py", line 24, in __init__
self.i2c.write_byte_data(self.ADDR, 0x2C, 0x03) # output data rate 100 Hz
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 5] Input/output error
この場合はソースコードの次の部分
# self.ADDR = 0x1d
self.ADDR = 0x53
を
self.ADDR = 0x1d
# self.ADDR = 0x53
とI2Cアドレスを変更することで解決する場合があります
こうなる理由としては、この加速度センサー ADXL367 は2つのI2Cアドレスを使用することが出来、ASEL pinをGNDに接続することで 0x1d のアドレスを使用するように出来るようになっているのですが、このピンをGNDに接続していないときでも 0x1d のアドレスを使用する場合があるためです(なぜこのようなことが起こるのかは不明)
コードの簡単な解説
- classを使ってオブジェクト指向風に書きました
- __init__ メソッドで初期化設定を行い、データの範囲を ±2 g 、出力レートを 100 Hz に設定しました (データシート 44 ページ目)
- get_acc_raw メソッドでデータの取得を行い、x, y, z, norm の順で加速度のデータを返します (データシート 34, 35, 36 ページ目)
- その他メソッドはキャリブレーションに使用する目的で書きました
応用
加速度センサーは衝撃検知や自由落下検知、速度測定に使用できます
自由落下検知は単に加速度の値が 0 になったことを検知すれば実現できます。センサーの機能としても実装されているので興味があればデータシートを読んでみるのも面白いと思います
また、加速度の値を積分すれば物体の速度を測ることも出来ます。数値積分の方法については台形積分やシンプソンの公式などがあるのでこれも調べてみると面白いと思います