Arduino、GPS、センサーによるリアルタイム・バイク・テレメトリー・システム
部品と材料
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino UNO | 1 | |
| u-blox GPS NEO-7M | 1 | 56チャネル、10Hz更新、低消費電力 |
| LM35DT 温度センサー | 1 | 外気温測定用 |
| SparkFun TMP006 非接触赤外線温度センサー | 1 | リア・タイヤ温度測定用(外気温も可) |
| HC-05 Bluetoothモジュール | 1 | Arduino⇔Windows Phone通信用 |
| 超音波距離センサー HC-SR04 | 2 | フロント/リア・サスペンション・ストローク測定用 |
| SparkFun ADXL345 3軸加速度センサー | 1 | 3軸G加速度、バンク角・ウィリー角算出用 |
| Ducati Monster 695 | 1 | 実験車両 |
| SparkFun ProtoShield Kit | 1 | |
| ハーフ・サイズ・ブレッドボード | 1 | |
| 9V電池 | 1 | またはモバイル・バッテリー |
| 9V電池スナップ | 1 | |
| ジャンパー・ワイヤー | 1セット | |
| Lumia 650 (Windows 10 Mobile) | 1 | 表示・クラウド送信用 |
使用アプリ・サービス
- Microsoft Azure(IoT Hub、Stream Analytics、SQL Database、Web App、Machine Learning)
- Microsoft Visual Studio 2015
- Microsoft Blend
- Arduino IDE
- GIMP(画像編集)
- Fritzing(回路図作成)
プロジェクト概要
新しいプロジェクトを始めるたびに、自分の情熱に関連する最新テクノロジーを駆使した何かを作りたくなります。今回は「バイクへの情熱」と「Arduinoというお気に入りガジェット」、そしてプログラミング知識を組み合わせました。
着想
MotoGP中継で見るテレメトリー映像(速度、バンク角、Gフォース等)にいつも魅了されてきました。これをArduinoで自作できないかと考え、Azureと連携したテレメトリー・システムを開発。全バイク愛好家が自分のバイクに装着できるよう、再現性を重視しました。
本システムで取得可能なデータ:
- 速度 [km/h]
- GPS位置(緯度/経度)
- 衛星情報(衛星数、HDOP)
- 高度 [m]
- バンク角(リーン・アングル)
- ウィリー角(ピッチ・アングル)
- 3軸G加速度 [m/s²]
- 外気温 [°C]
- リア・タイヤ温度 [°C]
- フロント・ショック・アブソーバー・ストローク [cm]
- リア・ショック・アブソーバー・ストローク [cm]
使用ハードウェア:Arduino Uno R3、各種センサー、UWPアプリ搭載Windows Phone、Azureサービス群。
システム・ワークフロー
- フェーズ1:制御ユニット(バイク搭載)が全テレメトリー・データを秒間約2回取得
- フェーズ2:データ取得ごとにBluetoothでArduinoからWindows Phoneへ送信
- フェーズ3:Phoneでデータ表示、3G/4G経由でAzure IoT Hubへ送信
- フェーズ4:AzureのStream Analytics JobがIoT Hubからデータ受信、SQL Azureデータベースに保存
- フェーズ5:AzureにデプロイしたWeb AppがSQLデータを用いてリアルタイム表示
- フェーズ6:Web Appで認証後、全テレメトリー情報をチャート表示(Entity FrameworkでSQL Azureから取得)
- フェーズ7:SQL Azureの全データをMachine Learningで処理、「運転スタイル」を分析。テレメトリー・パラメータに基づき運転改善ポイントを提示
I Think IT'S PRETTY COOL!!! さあ、プロジェクト詳細へ
ハードウェア・セットアップ
構成部品:
- Arduino Uno R3 ×1
- HC-SR04超音波測距モジュール ×2(フロント/リア・サスペンション・ストローク測定)
- TMP006赤外線サーモパイル非接触温度センサー ×1(タイヤ温度測定、外気温も可)
- GPS-NEO7M ×1(GPS位置、速度、高度)
- ADXL345 ×1(3軸G加速度、リーン・アングル、ウィリー・アングル算出)
- LM35DT ×1(外気温)
- HC-05 Bluetoothモジュール ×1(Arduino⇔Windows Phone通信)
- 電源(汎用バッテリーまたはモバイル・バッテリー)
ステップ1:Bluetooth接続
SoftwareSerialライブラリでHC-05とArduinoを接続、Windows Phoneとの無線通信を実現。HC-05はクラス2、シリアル・ポート・プロファイル対応、マスター/スレーブ両対応。
デフォルト名「HC-05」を変更(魅力的でないため)。
Arduino側コード例
#include
SoftwareSerial BTSerial(10, 11); // RX, TX
void setup() {
BTSerial.begin(9600);
}
void loop() {
BTSerial.print("Hello Hackster");
}
Windows PhoneとArduinoの通信準備完了、簡単です!
ステップ2:GPS通信
ハードウェア:GPS-NEO7M(56チャネル、10Hz更新、低消費電力)。
SoftwareSerialライブラリとTinyGPS++ライブラリで通信。
#include
#include
SoftwareSerial ss(12, 13); // RX, TX
TinyGPSPlus gps;
void setup() {
ss.begin(9600);
}
void loop() {
while (ss.available() > 0) {
if (gps.encode(ss.read())) {
if (gps.location.isValid()) {
double lat = gps.location.lat();
double lon = gps.location.lng();
}
}
}
}
ステップ3:加速度センサー(ADXL345)
3軸加速度とロール/ピッチ角(バンク角/ウィリー角)取得用。ADXL345は小型・薄型・超低消費電力、13ビット分解能、±16g測定可能。SPI(3/4線)またはI2Cインターフェース。
ADXL345.hライブラリで通信。重要:接続直後は重力加速度の値が未校正。最初のループで「ゼロ点」を決定し、以降の測定値から差し引く校正が必要。
// 初回ループでゼロ点取得
if (i == 0) {
refXg = Xg; refYg = Yg; refZg = Zg;
i = 1;
}
// ゼロ点減算
Xg = Xg - refXg;
Yg = Yg - refYg;
Zg = Zg - refZg + 1; // +1は重力補正
バンク角(ロール)とウィリー角(ピッチ)の計算式:
// Roll & Pitch Equations
roll = -(atan2(-fYg, fZg) * 180.0) / M_PI;
pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg)) * 180.0) / M_PI;
座標系:Z軸=重力方向、Y軸=進行方向、X軸=横方向。
ADXL345通信コード例
#include
#include
#include
SoftwareSerial ss(12, 13);
ADXL345 acc;
void setup() {
acc.begin();
}
void loop() {
double Xg, Yg, Zg;
acc.read(&Xg, &Yg, &Zg);
}
ステップ4:タイヤ温度(TMP006)
タイヤに触れずに温度測定するため、赤外線温度センサーTMP006を採用。
TMP006はMEMSサーモパイル・センサーで、物体からの受動的赤外線エネルギー(4〜16μm)を吸収し、オンチップ・ダイ温度センサー測定値と共にI2Cで出力。
センサー配置距離が重要。データシート推奨:センサー-物体距離 < 物体の立体角半径の半分。タイヤ幅160mm → 半径R=80mm → 推奨距離 ≤ 40mm (R/2)。
TMP006通信コード例
#include
#include "Adafruit_TMP006.h"
Adafruit_TMP006 tmp006;
void setup() {}
void loop() {
float objt = tmp006.readObjTempC(); // 対象物体温度(タイヤ)
float diet = tmp006.readDieTempC(); // センサー温度(外気温)
}
ステップ5:外気温(LM35)
LM35DTで外気温測定。出力電圧は摂氏温度に比例(1°C = 10mV)。
Arduinoアナログ入力で読み取り:
int TempExtPin = A1;
float celsius = 0, millivolts;
int sensor;
sensor = analogRead(TempExtPin);
millivolts = (sensor / 1023.0) * 5000;
celsius = millivolts / 10;
ステップ6:超音波センサーでサスペンション・ストローク測定
HC-SR04でサスペンションの伸縮量を測定。音波の往復時間を測り距離を算出。
音速 ≈ 340 m/s(20°C)。距離 S = 0.034 × t/2 (t: マイクロ秒)。
基本コード例(低速・低性能):
digitalWrite(triggerPort, LOW);
digitalWrite(triggerPort, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPort, LOW);
long duration = pulseIn(echoPort, HIGH);
long r = 0.034 * duration / 2;
本プロジェクトでは高性能なNewPing.hライブラリを採用:
#include
int triggerPort = 2;
int echoPort = 3;
NewPing sonar(triggerPort, echoPort, 200); // 最大200cm
void setup() {}
void loop() {
int Pos = ReadPositionPing();
}
int ReadPositionPing() {
unsigned int uS = sonar.ping();
return sonar.convert_cm(uS);
}
UWPソフトウェア(Windows Phoneアプリ)
Bluetoothで制御ユニットと接続するユーザー・インターフェース。Arduinoから送信される全データを表示し、IoT Hubへセンサー値を送信。
シリアル通信は入力文字列の解釈で処理。STARTとENDマーカーを含むか検証し、正しければ「|」で分割して各センサー値を抽出、UIに表示。
Arduinoから送信されるデータ文字列例
$START|40.909409|N|9.520008|E|8|2|2016|15:46:42|0.09|0.000000|0|0|-0.21|0.00|0.00|-0.02|0.98|-|0.00|35.19|29.58|16|10|$END|
分割後の配列定義(全25要素)
| 位置 | 内容 |
|---|---|
| 0 | STARTマーカー |
| 1 | 緯度 |
| 2 | N(北緯) |
| 3 | 経度 |
| 4 | E(東経) |
| 5 | 月 |
| 6 | 日 |
| 7 | 年 |
| 8 | 時:分:秒 |
| 9 | 速度 (km/h) |
| 10 | 高度 (m) |
| 11 | 衛星数 |
| 12 | HDOP |
| 13 | ロール(バンク角) |
| 14 | ピッチ(ウィリー角) |
| 15 | Xg |
| 16 | Yg |
| 17 | Zg |
| 18 | オーディオ(無効) |
| 19 | 走行距離 (m) |
| 20 | 外気温 (LM35) |
| 21 | タイヤ温度 (TMP006) |
| 22 | フロント・ショック・ストローク (cm) |
| 23 | リア・ショック・ストローク (cm) |
| 24 | ENDマーカー |
Arduino IDEのシリアル・モニタで動作確認可能:
Bluetooth経由の全データを管理するUniversal Windows Platform (UWP)アプリを開発。UWPはWindows 10搭載全デバイス・ファミリーで動作可能なプラットフォームの好例です。
Windows 10 Mobileへのアプリ展開手順
Windows 10 SDK Preview Build 10166で導入されたWinAppDeployCmd.exeを使用。PCからUSB/同一サブネット経由で.AppXをデバイスに配布可能(Visual Studioフル環境不要)。
- ステップ1:モバイル・デバイスを「開発者モード」に(設定>更新とセキュリティ>開発者向け)。USB接続し可視化(PINコード取得)
- ステップ2:Visual Studioでプロジェクト右クリック>ストア>アプリ・パッケージの作成
- ステップ3:ウィザードで「いいえ」(ローカル・パッケージ)、ARMプラットフォーム選択、作成
- ステップ4:コマンド・プロンプトで
C:\Program Files (x86)\Windows Kits\10\bin\x86\に移動し、
WinAppDeployCmd install -file "パッケージパス" -ip 127.0.0.1 -pin PINコード実行
Azureクラウド構築
必要なAzureリソース:
- Web App + SQL Azure
- IoT Hub
- Stream Analytics Job
- IoT Hub用Device ID
Azureアカウント未取得なら こちら から作成。取得済みなら ポータル へ。
ステップ1:IoT Hub作成・設定
IoT Hubはテレメトリー・データのクラウド入り口。
- 新規>Internet of Things>IoT Hub で作成
- ダッシュボードでデプロイ完了待ち
- 設定ブレードでホスト名をメモ
- 共有アクセス・ポリシー>iothubowner>接続文字列をコピー・メモ
ステップ2:Stream Analytics Job作成・設定
IoT Hubからデータを読み取り、SQL Azureテーブルに書き込み。
- 新規>Internet of Things>Stream Analytics Job で作成
- 入力:IoT Hubをソースに設定
- 出力:SQL Azureテーブルを宛先に設定(次ステップでDB作成)
ステップ3:Web App + SQL Azure作成
ダッシュボード>新規>ネットワーク>Web + Mobile>Web App + SQL
Web App設定:アプリ名、サブスクリプション、リソース・グループ、App Service Plan(無料のF1で可)。
SQL設定:新規作成、名前、価格レベル、サーバー名、管理者資格情報。
Stream Analyticsのクエリ設定:
SELECT * INTO SqlAzureMyTelemetry FROM MyTelemetryInputHub
「MyTelemetryInputHub」からデータを取り、「SqlAzureMyTelemetry」へ保存。簡単かつ強力!
最後にジョブの「開始」ボタンをクリック。
ステップ4:Device ID作成
デバイスとIoT Hubを接続するため、IDレジストリにデバイスIDを登録。
詳細:公式ドキュメント
Visual Studioでコンソール・アプリ作成、NuGetでMicrosoft.Azure.Devicesインストール、以下のコードでデバイスキー生成:
class Program {
static RegistryManager registryManager;
static string connectionString = "あなたのIoT Hub接続文字列";
static void Main(string[] args) {
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
AddDeviceAsync().Wait();
Console.ReadLine();
}
private async static Task AddDeviceAsync() {
string deviceId = "myDucatiMonsterDevice";
Device device;
try {
device = await registryManager.AddDeviceAsync(new Device(deviceId));
} catch (DeviceAlreadyExistsException) {
device = await registryManager.GetDeviceAsync(deviceId);
}
Console.WriteLine("Generated device key: {0}", device.Authentication.SymmetricKey.PrimaryKey);
}
}
実行(F5)でデバイスキー生成完了!
Webアプリケーション
テレメトリー・データを友人と共有・SNS投稿するため、ASP.NETでレスポンシブWebサイトを構築。Entity FrameworkでSQL Azureからデータ読み取り、ダッシュボード表示。
URL:WebアプリURL
Hacksterユーザー用テスト・アカウント:
User ID: demo / Password: demo
モバイル版もレスポンシブ対応。
無料ティアで作成したWeb Appのドメインは <websitename>.azurewebsites.net。独自ドメイン取得もAzureで簡単:ダッシュボード>Web App>カスタム・ドメインとSSL>ドメイン購入。
Ducati Monster 695 への実装
実験車両:Ducati Monster 695
車載ハードウェア(制御ユニット)の搭載写真:
タイヤ温度測定用ブラケットをホイール後ろにクランプ固定。
フロント・サスペンション測定用HC-SR04をヘッドライト下に固定(ヘッドライト〜フロント・フェンダー間距離測定)。
リア・サスペンション測定用HC-SR04をシート下に固定(シート〜リア・タイヤ間距離測定)。
中央ユニット(Arduino、GPS、加速度センサー、外気温センサー)をシート後ろに固定。
配線完了後の全景:
Machine Learning(機械学習)による運転スタイル分析
テレメトリー・データ間の相関を分析し、運転改善に役立てるのが最後のアイデア。データ・サンプルは毎回ルート・交通状況が異なるため直接比較は困難。サーキット走行での使用が理想的。実レースならテレメトリーに基づき、速度を上げるべきか下げるべきかを判断可能。
Azure Machine Learning Studio で実験:
- studio.azureml.net でAzureアカウントでサインイン、左メニュー「Studio」
- ダッシュボードで「NEW」>実験作成
- データ・インポート:SQL Azureから取得
- データ型変換(varchar→float)と不良データ除外
SELECT CAST(speed as float) _speed, CAST(roll as float) _roll, CAST(pitch as float) _pitch,
CAST(Xg as float) _Xg, CAST(Yg as float) _Yg, CAST(Zg as float) _Zg,
CAST(TempExt as float) _TempExt, CAST(TempTyre as float) _TempTyre,
CAST(FrontAbsorber as float) _FrontAbsorber, CAST(BackAbsorber as float) _BackAbsorber
FROM mytelemetry
WHERE CAST(speed as float) > 3
AND CAST(FrontAbsorber as float) > 0
AND CAST(BackAbsorber as float) > 0
AND CAST(roll as float) < 60
AND CAST(roll as float) > -60
- Split Dataで学習用/テスト用に分割
- Train Modelで予測対象フィールドとアルゴリズム選択
- Score Modelで学習モデルをテスト・データで評価
- Evaluate Modelでモデル精度を検証
分類モデル評価指標
- Accuracy:正解率 = (TP+TN)/(TP+TN+FP+FN)
- Precision:適合率 = TP/(TP+FP)
- Recall:再現率 = TP/(TP+FN)
- F-score:適合率と再現率の調和平均(理想値1)
- AUC:ROC曲線下面積(異種モデル比較に有用)
Two-class Decision ForestアルゴリズムでAccuracy/Precision/Recall/F1がほぼ1に近く、モデルがデータをよく記述できていることが判明。GREAT!
予測実験とWebサービス化
学習実験を予測実験に変換し、Webサービスとしてデプロイ。新しい実験でSQL Azureをデータソースとし、テレメトリー値に基づき分類(新規カラムScoredで分類結果表示)。
Multi-class Decision Forestアルゴリズムで学習、実行、予測Webサービスとしてデプロイ。ダッシュボードの「TEST」ボタンで手動テスト可能。
「HIGH STRESS HIGH SPEED」なら減速必要。
MLから得られた知見
- Azure ML環境での実験構築手法
- Two-class Decision Forestがバイク・テレメトリーをよく記述、予測にはMulti-class Decision Forestを使用
- モデルをWebサービス化する手順
- 運転スタイルの傾向:右バンクを好む、バンク角はタイヤ温度・速度に依存しない(タイヤ品質が高い証左)、タイヤ温度35°C超でウィリーしやすい
最終結論と今後の展望
本プロジェクトでは多くの技術領域をカバーしました:
- Arduinoとセンサーで60ドル以下のハードウェア構築、Microsoftサービス群の活用
- Azureの容易さとMachine Learning Studioの面白さを実証
- 改良の余地はあるが、C#、Azure、Arduino、バイク愛好家への良い出発点
今後の改良案:
- モバイル・アプリ(UWP)でネットワーク断時のデータ・バッファリング機能追加
- XamarinでAndroid/iOS対応アプリ作成
- より高精度センサー採用、性能・精度向上
- 中央ユニット小型化(Arduino MKR1000等活用)
- ソーシャル・メディア連携Webアプリで走行・テレメトリー共有、危険カーブ情報提供、安全性向上
- Machine Learningデータ・ソースをStream Analyticsに変更(同時走行・開発が困難だったためSQL Azureを使用)
新ワークフロー案:
- IoT Hub経由でデバイスにML予測サービスのスコアを返送
- 速度100km/h超で新Stream Analytics JobがテレメトリーをEvent Hubへ送信
- クラウド・サービスがEvent Hubからデータ読み取り、ML予測サービスにリクエストし運転スタイル・スコア取得
- クラウド・サービスがスコアをIoT Hubへ送信、IoT Hubからデバイス(Windows Phone)へ返送
... and now ENJOY !! :-) 質問・ヒントはお気軽にご連絡ください。
コード
回路図
MotorbikeProject.fzz (Fritzingファイル)
製造プロセス
- Sensor Telemetry 2.0.1:Azure IoT Hubによる高度な温度監視
- Arduinoと超音波センサーで作るAI障害物回避ロボット 〜Q学習による強化学習実装〜
- NeoPixelリングとArduinoで作るインタラクティブジャイロスコープLEDディスプレイ
- DIY Arduino USBゲームコントローラー - 高性能ゲームパッドを自作
- DIYクラウドコスチューム: LEDストリップ、Arduino Nano & SparkFunパーツで光る雲に
- 産業用ラインフォロワーロボット - 物資輸送用自律走行ロボット
- Pixie: Arduino Pro Miniで作るNeoPixel腕時計 - アナログとデジタル融合のDIY光る時計
- スマートArduino水筒:リアルタイム監視とアラート機能付き
- DIY ホリデーシャドーシアター:ArduinoとアドレサブルLEDで作る光の影絵劇
- 携帯型リモート監視カメラロボット - Raspberry PiとArduinoで構築
- スマート手話グローブ:ジェスチャーをテキスト/音声に変換