第2章 モーションセンサを使おう

2024/08/26 各章を個別ページ化

未来を操れ!ロボット、ドローンの世界は3次元、姿勢計測を学ぼう!

目 次

第2章 モーションセンサ

モーションセンサとは

モーションセンサとは、モーション(動き)をセンシング(検出)する部品のことを指します。
最近は、様々な動きを検出し、そうに応じた制御をすることが一般的です。
ロボットやドローンも安全な動作を実現したり、人の操縦をアシストするためにモーションセンサが使われています。

<参考>
https://www.tdk.com/ja/tech-mag/core-technologies/13

本授業では、3軸のジャイロスコープと3軸の加速度センサーを組み合わせた6軸の動きを検出可能なMPU-6050を用いる。

準備1:センサを使うために必要なライブラリファイルをインストールする

スケッチ -> ライブラリをインクルード -> ライブラリを管理

左側に画面が開くので、検索欄に「MPU6050」と打つ。
検索結果に出てくる次の2つをインストールする。

  • MPU6050 by Electric Cats
  • Adafruit MPU6050 by Adafruit

インストールをクリック、画面が開いたら全てをインストールをクリックしてインストールする。

モーションセンサの出力を見てみよう!

1.Arduinoとセンサを接続する

電源2本、信号2本の計4本を繋ぎます。

センサジャンパ線Arduino
VCC5V
GNDGND
SCLSCL(D19)
SDASDA(D18)

2.プログラムを開く

ファイル → スケッチ例 → Adafuruit MPU-6050 → plotter

3. Arduino をPCに繋ぐ

3.プログラムをアップロードする

4.正しく出力が得られているか確認する

  • アップロードが完了したら、右下の「9600 baud」を「115200 baud」に変更する。
  • 右上の「シリアルプロッタ」(波形のアイコン)を起動する。

モーションセンサを利用しよう!

センサと動かしたら画面の中のオブジェクトも同じように動かせるようにする
6軸センサーの出力をarduinoで読み取り、リアルタイムにPCに送信する。
PCでは、受信した値をProcessingというアプリケーション(ソフトウェア)を使ってオブジェクトの姿勢として画面に描画する。

Processingとは
描画やアニメーションをコードで実行するアプリケーション(ソフトウェア)。
arduinoとの組合せでよく使われる。

https://processing.org/

<参考>
・Processingで学ぶプログラミング入門 – 京都産業大学
https://www.cc.kyoto-su.ac.jp/~mmina/learningProgramming/

1.arduinoでスケッチを新規作成

#include "MPU6050.h" //センサを動かす命令を使うからその命令を理解してねという命令
MPU6050 mpu; //mpuと書いたらMPU6050への命令だよと宣言

int16_t ax, ay, az;//加速度 int16_tは2バイトの符号付き整数 
int16_t gx, gy, gz;//角速度 同上

void setup() //{から}までを一度だけ実行する命令
{
  Wire.begin(); //端子を使って通信するよと命令
  Serial.begin(115200); //115200kbpsという通信速度で通信開始と命令
  mpu.initialize(); //MPU6050(I2Cデバイス)に今から使うよと初期化の命令
  delay(300); //300ms待機せよと命令(初期化が完了するのを待つ時間)
}

void loop() //{から}までをずっと繰り返す命令
{
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //MPU6050からの出力値を取得してax等に入れなさいと命令
  Serial.print(ax/16384.0); Serial.print(","); //取得した値を計算して、serial通信の画面に出力しなさいと命令,カンマを出力しなさいと命令
  Serial.print(ay/16384.0); Serial.print(",");
  Serial.print(az/16384.0); Serial.print(",");
  Serial.print(gx/131.0); Serial.print(",");
  Serial.print(gy/131.0); Serial.print(",");
  Serial.print(gz/131.0); Serial.print(",");
  Serial.print("\n"); //改行しなさいと命令
  delay(10);
}

2.arduinoにアップロード

arduinoの準備は完了です。

3.Processingを開く

Windowsメニューを開く(左下のWindowsマークをクリック)->メニューが出たら「processing」と打つ。 -> 検索結果に出てきた「Processing」をクリックして起動する。

4.プログラム(スケッチ)をコピーして実行
実行するとarduinoがPCにデータを送っているシリアルポート番号(端子番号)が表示されます。

import processing.serial.*; //シリアル通信をするための命令を使うから命令を理解してねという命令
Serial myPort; //通信するよと命令
printArray(Serial.list()); //シリアル通信の通信中のポート(端子)一覧を画面に表示せよと命令

COM1以外の番号を次で使う。

5.プログラム(スケッチ)をコピーして実行
ファイル → 新規 で新しいスケッチを開く。
次のプログラムをコピーして、3行目の「2」を1つ前で調べたCOMの番号に書き換える。

import processing.serial.*; // シリアル通信するからこんな命令が来るからねと教えてます

Serial myPort;  //myportという名前のシリアル通信をするよって宣言
int available_serialport = 2; // 通信に使うポートを設定(調べた値に変更する)
String arduinoPort = Serial.list()[available_serialport ]; //1行前で設定したポート番号のシリアル通信を設定
float []data = new float [6]; //シリアルのデータを格納する配列(入れ物、7個用)を準備

void setup() {
  lights();
  size(300, 300, P3D); // 画面に表示するキャンバスサイズ
  myPort = new Serial(this, arduinoPort, 115200); // シリアルポートの設定
}

void draw() {
  background(230); //背景の色を設定
  translate(width / 2, height / 2, 0); // 原点を図形の中心に設定
  rotateX(radians(data[0])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる
  rotateZ(radians(-data[1])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる

  int size = 10;//図形のサイズ倍率。キャンバスを大きくする時に変更可
  box(20 * size, 1 * size, 15 * size); //直方体を描く
  translate(0, -4 * size, 0);
}

void serialEvent(Serial p) { //シリアルを監視する命令
  String inString = myPort.readStringUntil('\n'); //データがあったら改行のところまで読み込む
  if (inString != null) { //シリアルの文字列データが入っていれば
    inString = trim(inString); //文字列の前後の空白を削除する
    data = float(split(inString, ',')); //ピリオドで分割してdataという配列に格納する
    println(data);//dataという配列の中身ををprocessingのコンソールに出力
  }
}

書き換えるのは次の行。ほとんどの場合は1にすれば良い。

int available_serialport = 2; // 調べた値に変更しておく

次の場合はエラーとなる。
・番号が間違っている場合 ⇒ シリアルポートを調べるプログラムをもう一度実行してリスト番号を確認する。([0]とか[1]とかの数字)
・arduinoが使いたい通信ポートに繋がっている場合 ⇒ 起動しているarudino IDEを全て終了する。(これでarduinoが通信ポートを使わなくなる)

6.センサーと画面内のブロックが同期して動くことを確認する

画面内のブロックはどのように動いていますか?

モーションセンサの出力を滑らかにしてみよう!

1つ前のプログラムでは、センサの出力をそのまま利用していました。
センサの基板である程度は補正を行ってくれているので大きくおかしなことにはなっていません。
次は出力の値を安定させるように処理します。

スケッチ -> ライブラリをインクルード -> ライブラリを管理

  • Madgwick by Arduino

1.Arduinoで新規スケッチを開く

ファイル → 新規スケッチ を開く。

2.プログラムを準備する

貼り付ける前のプログラムは全て削除する。
*全選択(Ctrl + A)して、Deleteキーを押すのが早い。

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

次のプログラムをコピペする。

#include "MPU6050.h"
MPU6050 accelgyro;
#include <MadgwickAHRS.h>
Madgwick MadgwickFilter;

int16_t ax, ay, az;//加速度 int16_tは2バイトの符号付き整数
int16_t gx, gy, gz;//角速度 同上
float ROLL, PITCH, YAW;

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  accelgyro.initialize();//I2Cデバイスの初期化
  delay(300);
  MadgwickFilter.begin(100);//フィルタのサンプリングを100Hzで
}

void loop()
{
  accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  MadgwickFilter.updateIMU(gx / 131.0, gy / 131.0, gz / 131.0, ax / 16384.0, ay / 16384.0, az / 16384.0);
  ROLL = MadgwickFilter.getRoll();
  PITCH = MadgwickFilter.getPitch();
  YAW  = MadgwickFilter.getYaw();
  Serial.print(ROLL); Serial.print(",");
  Serial.print(PITCH); Serial.print(",");
  Serial.print(YAW);
  Serial.print("\n");
  delay(10);
}

3.arduinoを実行(アップロード)する
*アップロードが完了したらarduino IDEは終了してもOK

4.Processingのスケッチを実行しセンサを動かしてみる

さきほど使ったProcessingのプログラムをMadgwickフィルタの出力に合わせて2箇所変更する

変更箇所1:6行目の配列の数を 6 から 3に書き換える。
*センサの出力データは6つ(x, y, zの加速度と各軸周りの角加速度)。Madgwickフィルタではセンサ出力から各軸周りの”角度”を求めて出力する。

書き換える前

float []data = new float [6]; //シリアルのデータを格納する配列を宣言

書き換えた後

float []data = new float [3]; //シリアルのデータを格納する配列を宣言

変更箇所2:17, 18行目を次のように書き換える

書き換える前

  rotateX(radians(data[0])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる
  rotateZ(radians(-data[1])*90); //dataの中身は重力加速度gなので、90を掛けると角度に概算できる

書き換えた後

  rotateX(radians(-data[1]));
  rotateZ(radians(-data[0]));

Processingを実行する。

さっきまでと比べて違いがわかりますか。
今回は、滑らかに動いていると思います。

これは誤差を含む測定データからより正確な情報を推定する技術(フィルタ)を使いました。
大学の制御工学という授業ではその基本となるカルマンフィルタというもの習いますが、ここではさらに難しい、けれども実用的なMadgwickフィルタを使いました。
このように、フィルタという技術を使うことでセンサの出力をそのまま使うよりも使いやすい、場合によってはより正確な情報を導き出すことができます。


大学の授業では、センサ自体についてはセンサ工学、センサの原理は振動工学や電気電子工学、データの処理には制御工学や統計力学など様々な授業で学び、それらを実験授業で組み合わせてロボットなどを動かすことで、学んだことを実際に手で動かして身につけて行くことができます。

<参考>

体験型模擬授業 >> 第1章 Arduinoを使おう >> 第2章 モーションセンサを使おう