Система телеметрии мотоцикла в реальном времени: Arduino, GPS, датчики, Azure и ML
Компоненты и материалы
| Arduino UNO | × | 1 |
| GPS‑модуль u‑blox NEO‑7M | × | 1 |
| Датчик температуры LM35DT | × | 1 |
| ИК‑термометр TMP006 (SparkFun) | × | 1 |
| Bluetooth‑модуль HC‑05 | × | 1 |
| Ультразвуковые датчики HC‑SR04 | × | 2 |
| Акселерометр ADXL345 (SparkFun) | × | 1 |
| Мотоцикл Ducati Monster 695 (объект установки) | × | 1 |
| SparkFun ProtoShield Kit | × | 1 |
| Половинчатая макетная плата | × | 1 |
| Крона 9 В + клемма | × | 1 |
| Перемычки | × | 1 |
| Смартфон Lumia 650 (Windows 10 Mobile) | × | 1 |
Приложения и сервисы
- Microsoft Azure (IoT Hub, Stream Analytics, SQL Azure, Web App, Machine Learning)
- Microsoft Visual Studio 2015
- Microsoft Blend
- Arduino IDE
- GIMP
- Fritzing
О проекте
Каждый новый проект — попытка совместить последние технологии с хобби. Здесь — страсть к мотоциклам и Arduino.
Идея
Всегда восхищался телеметрией MotoGP на ТВ. Решил построить свою систему на Arduino + Azure, легко воспроизводимую любым мотоциклистом.


Система собирает:
- Скорость [км/ч]
- GPS позиция (широта/долгота)
- Спутники (кол-во, HDOP)
- Высота [м]
- Угол наклона (Lean Angle)
- Угол «виляния» (Wheelie Angle)
- G‑ускорение по 3 осям [м/с²]
- Внешняя температура [°C]
- Температура задней шины [°C]
- Ход передней вилки [см]
- Ход заднего амортизатора [см]
Железо: Arduino Uno R3, сенсоры, UWP‑приложение на Windows Phone, облако Azure.
Рабочий процесс:

- Фаза 1 — Бортовый блок (на мотоцикле) опрашивает датчики ~2 раза/сек.
- Фаза 2 — Данные по Bluetooth (HC‑05) уходят на Windows Phone.
- Фаза 3 — Телефон отображает данные и шлёт их 3G/4G в Azure IoT Hub.
- Фаза 4 — Stream Analytics Job в Azure пишет данные в SQL Azure.
- Фаза 5 — WebApp на Azure читает SQL и показывает телеметрию в реальном времени.
- Фаза 6 — WebApp с аутентификацией, графики (Entity Framework).
- Фаза 7 — Machine Learning обрабатывает накопленные данные, выявляет паттерны стиля вождения для рекомендаций по улучшению.
I Think IT'S PRETTY COOL!!! Приступим к описанию.
Аппаратная настройка

Состав:
- 1× Arduino Uno R3
- 2× HC‑SR04 — ход вилки и амортизатора
- 1× TMP006 — бесконтактная температура шины (и опционально воздуха)
- 1× GPS NEO‑7M — позиция, скорость, высота
- 1× ADXL345 — 3‑осевое ускорение, расчёт Lean/Wheelie углов
- 1× LM35DT — внешняя температура
- 1× HC‑05 — Bluetooth к телефону
- 1× Питание (пауэрбанк или батарея)
Шаг 1 — Bluetooth
Библиотека SoftwareSerial для UART на пинах 10/11. HC‑05 — Class 2, SPP, мастер/слейв.

Сменили имя устройства (было «HC‑05» — неэстетично).
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(10,11); // RX, TX
void setup() {
BTSerial.begin(9600);
}
...
BTSerial.print("Hello Hackster");
Bluetooth готов — просто и надёжно.
Шаг 2 — GPS
Модуль NEO‑7M: 56 каналов, 10 Гц, низкое потребление.

Коммуникация через SoftwareSerial (пины 12/13) и библиотеку TinyGPS++.
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
SoftwareSerial ss(12,13);
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

ADXL345 — 3‑осевой, 13‑бит, до ±16 g, SPI/I2C. Библиотека ADXL345.h.
Важно: сырые данные не откалиброваны. Нужно задать нулевую точку (offset) в первом цикле:
if (i == 0) { refXg = Xg; refYg = Yg; refZg = Zg; i = 1; }
Xg -= refXg; Yg -= refYg; Zg = Zg - refZg + 1;
Углы крена (Roll) и тангажа (Pitch) из компонент g:
roll = -(atan2(-fYg, fZg) * 180.0) / M_PI; // Lean Angle
pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg)) * 180.0) / M_PI; // Wheelie Angle
Оси: Z — гравитация, Y — движение вперёд, X — боковой скольжение.

#include <Wire.h>
#include <ADXL345.h>
ADXL345 acc;
void setup() { acc.begin(); }
void loop() { double Xg,Yg,Zg; acc.read(&Xg,&Yg,&Zg); }
Шаг 4 — Температура шины (TMP006)


TMP006 — MEMS термопара, измеряет ИК‑излучение 4–16 мкм без контакта. I2C интерфейс.
Расположение: ширина шины 160 мм → радиус твёрдого угла 80 мм → рекомендуемое расстояние ≤40 мм (R/2).


Код (SoftwareSerial + Adafruit_TMP006):
#include <SoftwareSerial.h>
#include "Adafruit_TMP006.h"
Adafruit_TMP006 tmp006;
void loop() {
float objt = tmp006.readObjTempC(); // температура объекта (шина)
float diet = tmp006.readDieTempC(); // температура датчика (воздух)
}
Шаг 5 — Внешняя температура (LM35)

LM35 — 10 мВ/°C, линейная зависимость. Чтение через АЦП:
int TempExtPin = A1;
float celsius = 0;
int sensor = analogRead(TempExtPin);
float millivolts = (sensor / 1023.0) * 5000;
celsius = millivolts / 10;
Шаг 6 — Ультразвуковые датчики (ход подвески)


Скорость звука ~340 м/с. Формула: S = 0.034 × t / 2 (t в мкс, S в см).
Базовый код медленный. Используем библиотеку NewPing.h — быстрая и удобная.
#include <NewPing.h>
int triggerPort = 2, echoPort = 3;
NewPing sonar(triggerPort, echoPort, 200);
int ReadPositionPing() {
unsigned int uS = sonar.ping();
return sonar.convert_cm(uS);
}
UWP‑приложение (Windows 10 Mobile)
UI: слева — Bluetooth, центр — 3 шкалы (скорость, lean, wheelie), справа — GPS, температуры, подвеска.






Протокол: строка с маркерами $START|...|$END|, разделитель «|». Позиции полей:
- START
- Latitude
- N/S
- Longitude
- E/W
- Month
- Day
- Year
- Time hh:mm:ss
- Speed km/h
- Altitude m
- Satellites count
- HDOP
- Roll (lean)
- Pitch (wheelie)
- Xg
- Yg
- Zg
- Audio (disabled)
- Distance m
- Temp Ext (LM35)
- Temp Tyre (TMP006)
- Front shock cm
- Back shock cm
- END

Развёртывание UWP на Windows 10 Mobile
- Телефон в «Режим разработчика» (Обновление и безопасность → Для разработчиков). USB → видимое подключение → PIN.
- В Visual Studio: Project → Store → Create App Packages.
- Wizard: No (локальный пакет) → ARM → Create.
- Получен .appxbundle. Деплой через
WinAppDeployCmd.exe:
(AAA123 — PIN с телефона).WinAppDeployCmd install -file "путь_к_appxbundle" -ip 127.0.0.1 -pin AAA123 - Приложение установлено, можно закрепить в старте.
Настройка Azure
Создаём: WebApp + SQL Azure, IoT Hub, Stream Analytics Job, Device ID.
- IoT Hub: New → IoT Hub → заполнить поля. Запомнить Hostname и Connection String (policy iothubowner).
- Stream Analytics: New → Stream Analytics Job. Input — IoT Hub, Output — таблица SQL Azure.
- WebApp + SQL: New → Web App + SQL. Настроить App Service Plan (F1 Free), SQL (admin credentials).
- Query Stream Analytics:
SELECT * INTO SqlAzureMyTelemetry FROM MyTelemetryInputHub— запустить Job.













Создание Device ID для Hub
Консольное приложение Visual Studio + NuGet Microsoft.Azure.Devices:
class Program {
static RegistryManager registryManager;
static string connectionString = "xxxxxxxxxxxxxx";
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) → получаем ключ устройства.
Веб‑приложение (ASP.NET)
Дашборд с телеметрией, данные через Entity Framework из SQL Azure.
Демо‑доступ для Hackster: User: demo / Pass: demo






Мобильная версия:






Домен бесплатного tier: <name>.azurewebsites.net. Свой домен: Dashboard → Custom domains and SSL → Buy domains.



Монтаж на Ducati Monster 695

Фото бортового блока:






Кронштейн TMP006 за задним колесом:


HC‑SR04 под фарой (передняя вилка):

HC‑SR04 под сиденьем (задний амортизатор):

Центральный блок (Arduino, GPS, ADXL345, LM35) за сиденьем:





Итоговый вид:


Machine Learning в Azure
Поиск корреляций телеметрии для улучшения стиля вождения. Данные неоднородны (разные маршруты, трафик) — идеально на трассе.
Azure ML Studio: studio.azureml.net → вход Azure → Studio.


- Experiments → NEW → Import Data из 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, часть на Test.
- Train Model — выбрать целевое поле и алгоритм (Two‑class Decision Forest показал лучшие метрики).
- Score Model + Evaluate Model — оценка качества.




Метрики классификации: Accuracy, Precision, Recall, F1, AUC. Decision Forest даёт значения ≈1 — модель хороша.
Predictive Experiment
Конвертация обучающего эксперимента в предсказательный → веб‑сервис.




Train Model → Set Up Web Service → Predictive Web Service → Deploy.




TEST: вводим значения → предсказание «SAFE DRIVING» (снижать скорость не нужно). Если «HIGH STRESS HIGH SPEED» — снижать.


Выводы по ML:
- Настройка экспериментов в Azure ML.
- Two‑class Decision Forest лучше описывает телеметрию; для предсказания — Multiclass Decision Forest.
- Создание предиктивного веб‑сервиса.
- Инсайты: предпочитаю наклон вправо, угол наклона не зависит от температуры шины и скорости (шины качественные), виляние (wheelie) появляется при температуре шины >35 °C.



Итоговые выводы
Проект охватывает: Arduino + сенсоры (<$60), Azure (IoT Hub, Stream Analytics, SQL, WebApp, ML), UWP. Прототип требует доработок, но хорошая база для энтузиастов C#, Azure, Arduino, мотоциклов.
Перспективы развития:
- Буферизация данных в UWP при потере 3G/4G.
- Xamarin‑приложение для Android/iOS.
- Точнее сенсоры, выше производительность.
- Меньший блок (Arduino MKR1000).
- Социальная веб‑платформа для обмена треками и предупреждений об опасных поворотах.
- Источник ML — Stream Analytics вместо SQL (параллельная разработка и езда).

Новый workflow (обратная связь ML → устройство):
- IoT Hub → ML predictive service → score → обратно на устройство (телефон).
- При скорости >100 км/ч отдельный Stream Analytics Job шлёт данные в Event Hub.
- Cloud Service читает Event Hub, запрашивает ML, возвращает score в IoT Hub → устройство.
... and now ENJOY !! :-) Вопросы и идеи — welcome.
Код
UWP App C# Code: GitHub
Arduino Code — Bike Telemetry: GitHub
Схемы
Схемы телеметрической системы. Набордная схема:

MotorbikeProject.fzz (Fritzing файл)
Производственный процесс
- Sensor Telemetry 2.0.1 — продвинутый мониторинг температуры с Azure IoT Hub
- Система избегания препятствий с ИИ (Q-learning) на Arduino и ультразвуковых датчиках
- Интерактивный гироскопический LED-дисплей на NeoPixel Ring и Arduino
- DIY USB-геймпад на Arduino: собственный высокопроизводительный контроллер
- DIY-костюм «Облако»: LED-лента, Arduino Nano и детали SparkFun
- Промышленный робот-линейный следователь для транспортировки материалов
- Pixie: DIY-наручные часы на Arduino Pro Mini и NeoPixel — стильный светодиодный тахометр времени
- Умная бутылка для воды на Arduino: мониторинг и напоминания в реальном времени
- DIY Теневой театр на Arduino и адресной LED-ленте: световое шоу к праздникам
- Переносная система видеонаблюдения: робот с камерой на Raspberry Pi и Arduino