やること
LSM9DS1を使用した秋月の9軸センサモジュール(9DoF IMU)の値を読み取ります。
このハードウェアはブレイクアウトボードとしてはI2Cのみの対応となります。
秋月の公式マニュアルにもテスト方法が詳しく紹介されています。
準備
・秋月の9軸センサモジュール(9DoF IMU)
・Arduino系のマイコン
・ライブラリ SparkFunLSM9DS1 の導入
→ライブラリはArduinoIDEのライブラリマネージャから導入できます
配線例
Arduino系 | 9DoF IMU |
---|---|
3.3v | 1. +V |
GND | 2. GND |
SDA | 3. SDA |
SCL | 4. SCL |
Arduino系用スケッチ
Arduino
//https://github.com/sparkfun/LSM9DS1_Breakout を参考に
# include <Wire.h>
# include <SparkFunLSM9DS1.h>
LSM9DS1 imu;// LSM9DS1 Library Init
# define LSM9DS1_M 0x1C // コンパスのI2C初期アドレス
# define LSM9DS1_AG 0x6A // 加速度とジャイロのI2C初期アドレス
// Sketch Output Settings //
# define PRINT_SPEED 50 // 50ms毎にデータを出力
static unsigned long lastPrint = 0; // 最後の出力時刻をキープ
// 以下を利用して利用値の地磁気補正?を行う
// http://www.ngdc.noaa.gov/geomag-web/#declination
# define DECLINATION 7.46 // 東京はたぶんこの値?
//取得した数値を格納する行列
float imu_9dof[13];//ax,ay,az,gx,gy,gz,mx,my,mz,temperature,roll,pitch,yaw
void setup()
{
Serial.begin(115200);
Wire.begin();
if (imu.begin(LSM9DS1_AG, LSM9DS1_M, Wire) == false)//IMUの起動を判定
{
Serial.println("Failed to communicate with LSM9DS1.");
while (1);
}
//シリアルプロッタの凡例表示用
Serial.println("ax,ay,az,gx,gy,gz,mx,my,mz,temp,roll,pitch,yaw");
delay(100);
}
void loop()
{
getIMU();//IMUの値を取得する関数を実行
if ((lastPrint + PRINT_SPEED) < millis())//更新タイミングが来たらデータを表示
{
for (int i = 0; i < 13; i++) {
Serial.print(imu_9dof[i]);
Serial.print(", ");
}
Serial.println();
lastPrint = millis(); // 次回出力時刻を設定
}
}
void getIMU() {//IMUの値を取得する関数
if ( imu.gyroAvailable() )
{
imu.readGyro();
}
if ( imu.accelAvailable() )
{
imu.readAccel();
}
if ( imu.magAvailable() )
{
imu.readMag();
}
if ( imu.tempAvailable() )
{
imu.readTemp();
}
//取得したデータを配列に格納する。roll, pitch, yawの計算は適当
imu_9dof[0] = imu.calcAccel(imu.ax);
imu_9dof[1] = imu.calcAccel(imu.ay);
imu_9dof[2] = imu.calcAccel(imu.az);
imu_9dof[3] = imu.calcGyro(imu.gx);
imu_9dof[4] = imu.calcGyro(imu.gy);
imu_9dof[5] = imu.calcGyro(imu.gz);
imu_9dof[6] = imu.calcMag(imu.mx);
imu_9dof[7] = imu.calcMag(imu.my);
imu_9dof[8] = imu.calcMag(imu.mz);
imu_9dof[9] = imu.temperature;
//※以下の算出方法はすごく適当な仮の値なので全く参考にしないでください。
imu_9dof[10] = atan2(imu.ay, imu.az) * 180.0 / PI; //roll
imu_9dof[11] = atan2(-imu.ax, sqrt(imu.ay * imu.ay + imu.az * imu.az)) * 180.0 / PI; //pitch
imu_9dof[12] = atan2(imu.mx, imu.my) * 180.0 / PI; //yaw
}
実行
ArduinoIDEのシリアルモニタを表示させると、加速度のxyz,ジャイロのxyz,磁力センサのxyz, 温度, 簡易計算したroll, pitch, yaw の数値がズラズラと表示されます。
また、実行中にArduino IDEのシリアルプロッタを開くと、下記のようなグラフが表示されます。

Sparksfun版チュートリアルの要約
↑に有用な情報が集まっているようです。以下その要約です。
概要
- LSM9DS1は、3軸加速度センサ、3軸ジャイロセンサ、3軸地磁気センサの9自由度(9DOF)を1つのICに搭載
- 加速度センサーのレンジは±2、4、8、16g
- ジャイロスコープのレンジは±245、500、2000 DPS(°/s)
- 地磁気センサーのレンジは±2、4、12、16ガウス
- LSM9DS1はデジタルインターフェースとしてI2CとSPIの両方をサポート(秋月版ボードはI2Cのみ)
- LSM9DS1自体には様々な割り込みがあります。(秋月版ボードでは割り込み用のピンは省略されている)
- ちなみにsparksfun版での割り込み用出力ピンは加速度、ジャイロスコープがINT1、INT2。磁力計がDRDYとINTM
使用上の注意
- LSM9DS1は3.3Vのデバイスで、3.6V以上の電圧を供給すると、ICが永久に壊れる
- Arduinoの3.3Vの電源出力でI2Cが普段使えているならOK。SPIを使用したい場合は、レベルシフターが必要になるかも
- 5V動作のArduino(UNO、RedBoard、Leonardoなど)には、ロジックレベルシフターが必要
特徴
- LSM9DS1は、2つのICを1つのパッケージに収めたものと言える。片方がジャイロと加速度を、もう片方が地磁気を担当
- LSM9DS1 ICの軸方向に注意。加速度(x/y/z)、回転角(x/y/z)、磁力(x/y/z)のそれぞれの向きを確認
- データシートのICの極性を示すドットに注目。加速度と回転角は右手座標系、磁気センサーのx軸とy軸は反転
基礎知識の補足
- ジャイロは角速度の測定。"どのくらいの速さで、どの軸に沿って回転しているか "ということ。角速度の単位は、1秒あたりの度数。DPSまたは°/s
- 加速度は通常、/s2(メートル毎秒毎秒)またはg(重力[約9.8m/s2])で測定。物体が動かないとき地面に向かって1gを計測
- 磁力計は地球の磁場や小さな強磁性体の磁場を測定する
ライブラリの使用についてのポイント
- LSM9DS1 imu; でimuという名前でコンストラクタのインスタンスを作成。以降、データには"imu.変数名"でアクセスできる
- readAccel()・readGyro()・readMag()は、LSM9DS1をポーリングして、3つのセンサーからそれぞれ最新の読み取り値を取得する
取得した値はax, ay, az、gx, gy, gz、mx, my, mzにそれぞれ更新反映される。"imu.ax"などで扱える - calcAccel()・calcGyro()・calcMag()は設定したセンサのレンジに応じて浮動小数点で値を返す
- レンジの設定は、
imu.settings.accel.scale = 16; // 加速度のレンジを+/-16g
imu.settings.gyro.scale = 2000; // ジャイロのレンジを+/-2000dps
imu.settings.mag.scale = 8; // 磁力のレンジを +/-8Gs
imu.begin(); // 最新のレンジで更新
のように行う。
おわりに
とりいそぎ、秋月の9軸センサモジュール(9DoF IMU)の値が取得できることが試せました。
時間分解能やMadgwickフィルタなどによる真値推定などはまた調べてみます。