아두이노, GPS, 다중 센서로 구현하는 실시간 모터바이크 텔레메트리 시스템
부품 및 소모품
부품 수량 비고
아두이노 우노 (Arduino UNO R3) 1 메인 컨트롤 유닛 (바이크 탑재)
u-blox NEO-7M GPS 모듈 1 위치, 속도, 고도, 위성 정보
LM35DT 온도 센서 1 외부 기온 측정 (아날로그 출력)
TMP006 적외선 온도 센서 (스파크펀) 1 후면 타이어 표면 온도 비접촉 측정
HC-05 블루투스 모듈 1 아두이노 ↔ 윈도우 폰 통신
초음파 거리 센서 HC-SR04 2 프론트/리어 쇽업소버 스트로크 측정
ADXL345 3축 가속도계 (스파크펀) 1 G-포스, 린 각도(뱅크), 윌리 각도(피치) 산출
두카티 몬스터 695 1 테스트 차량 (임의 바이크 적용 가능)
스파크펀 프로토실드 키트 1 회로 기판용
하프 사이즈 브레드보드 1 프로토타이핑용
9V 배터리 + 클립 1씩 독립 전원용 (파워뱅크 대체 가능)
점퍼 와이어 1세트
루미아 650 (윈도우 10 모바일) 1 UWP 앱 실행 디바이스
소프트웨어 및 앱
마이크로소프트 애저 (Azure IoT Hub, Stream Analytics, SQL Database, Web App, Machine Learning)
마이크로소프트 비주얼 스튜디오 2015 (UWP 앱 개발)
마이크로소프트 블렌드 (UI 디자인)
아두이노 IDE
김프 (GIMP, 이미지 편집)
프리츠링 (Fritzing, 회로도 작성)
프로젝트 개요
모토GP 중계에서 보는 실시간 텔레메트리(속도, 린 각도, G-포스, 타이어 온도 등)를 아두이노와 애저 클라우드로 구현했습니다. 바이크에 장착된 컨트롤 유닛이 초당 2회 센서 데이터를 수집 → 블루투스로 윈도우 폰 전송 → 3G/4G로 애저 IoT 허브 업로드 → 스트림 애널리틱스로 SQL DB 저장 → 웹앱으로 실시간 대시보드 표시 → 머신러닝으로 주행 스타일 분석까지 통합된 엔드투엔드 시스템입니다.
모토GP 스타일 텔레메트리 화면 예시
수집 데이터 항목
속도 [km/h] (GPS 기반)
GPS 위치 (위도/경도), 위성 수, HDOP, 고도 [m]
린 각도 (뱅크 앵글), 윌리 각도 (피치 앵글)
3축 G-가속도 [m/s²]
외부 기온 [°C] (LM35)
후면 타이어 온도 [°C] (TMP006 비접촉)
프론트/리어 쇽업소버 스트로크 [cm] (HC-SR04 ×2)
시스템 워크플로우 (7단계)
데이터 수집 : 컨트롤 유닛(아두이노)이 초당 2회 센서 읽기
블루투스 전송 : HC-05로 윈도우 폰에 시리얼 스트림 전송
폰 표시 & 클라우드 업로드 : UWP 앱에서 실시간 게이지 표시 + 3G/4G로 애저 IoT 허브 전송
스트림 애널리틱스 : IoT 허브 데이터 수신 → SQL 애저 DB 테이블에 저장
웹앱 대시보드 : SQL DB 데이터를 엔티티 프레임워크로 읽어 실시간 차트 표시 (인증 필요)
머신러닝 : 축적된 데이터로 주행 스타일 분류 모델 학습/예측
하드웨어 상세 구현
1단계: 블루투스 통신 (SoftwareSerial)
HC-05를 클래스 2, SPP 프로파일, 슬레이브 모드로 설정. 기본 이름 'HC-05'를 변경 권장.
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(10, 11); // RX, TX
void setup() { BTSerial.begin(9600); }
void loop() { BTSerial.print("데이터 문자열"); }
2단계: GPS 통신 (TinyGPS++ 라이브러리)
NEO-7M, 56채널, 10Hz 업데이트. SoftwareSerial + TinyGPS++로 파싱.
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
SoftwareSerial ss(12, 13);
TinyGPSPlus gps;
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 (I2C/SPI)
13비트 분해능, ±16g. I2C 인터페이스 사용. 초기 루프에서 중력 벡터 기준점(오프셋) 캘리브레이션 후 상대값 사용.
// 첫 루프에서 기준점 저장
if (i == 0) { refXg = Xg; refYg = Yg; refZg = Zg; i = 1; }
Xg -= refXg; Yg -= refYg; Zg = Zg - refZg + 1; // Z축에 1g 보상
// 롤(린 각도) & 피치(윌리 각도) 계산
roll = -(atan2(-fYg, fZg) * 180.0) / M_PI;
pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg)) * 180.0) / M_PI;
축 정의: Z=중력 방향, Y=진행 방향, X=측방향
4단계: 타이어 온도 - TMP006 적외선 센서
비접촉 온도 측정 (4~16μm 적외선). 타이어 폭 160mm → 반경 80mm → 권장 거리 ≤40mm (R/2). I2C 통신, Adafruit_TMP006 라이브러리 사용.
float objt = tmp006.readObjTempC(); // 대상 물체 온도 (타이어)
float diet = tmp006.readDieTempC(); // 센서 자체 온도 (외부 기온 대체 가능)
5단계: 외부 기온 - LM35DT
아날로그 출력, 10mV/°C 선형 특성. 아두이노 아날로그 핀으로 읽기.
int sensor = analogRead(A1);
float millivolts = (sensor / 1023.0) * 5000;
float celsius = millivolts / 10;
6단계: 쇽업소버 스트로크 - HC-SR04 초음파 (NewPing 라이브러리)
음파 왕복 시간으로 거리 측정. 신규 라이브러리 NewPing.h로 고성능 구현.
#include <NewPing.h>
NewPing sonar(2, 3, 200); // Trig, Echo, 최대거리(cm)
int ReadPositionPing() {
unsigned int uS = sonar.ping();
return sonar.convert_cm(uS);
}
UWP 앱 (윈도우 10 모바일)
데이터 프로토콜
아두이노 → 폰 전송 문자열 포맷 (파이프 구분, START/END 마커):
$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|
파싱 후 인덱스별 의미: 0=START, 1=위도, 2=N/S, 3=경도, 4=E/W, 5=월, 6=일, 7=년, 8=시각, 9=속도, 10=고도, 11=위성수, 12=HDOP, 13=롤, 14=피치, 15=Xg, 16=Yg, 17=Zg, 18=오디오(미사용), 19=거리, 20=외부온도, 21=타이어온도, 22=프론트쇽, 23=리어쇽, 24=END
UI 구성
좌측: 블루투스 연결 패널
중앙: 속도계, 린 각도, 윌리 각도 게이지
우측: 3축 G-포스, GPS 정보, 온도, 쇽 스트로크 수치 표시
윈도우 10 모바일 배포 (WinAppDeployCmd)
폰을 '개발자 모드'로 설정 (업데이트 및 보안 → 개발자용)
USB 연결 → PIN 코드 확인
비주얼 스튜디오 → 프로젝트 우클릭 → 스토어 → 앱 패키지 생성 → 로컬 패키지(ARM) 빌드
생성된 .appxbundle 파일 경로 복사
관리자 CMD에서 실행:
WinAppDeployCmd install -file "경로\파일.appxbundle" -ip 127.0.0.1 -pin PIN코드
애저 클라우드 구성
1. IoT 허브 생성
애저 포털 → 새로 만들기 → IoT Hub → 필드 입력 → 생성
호스트네임, 공유 액세스 정책(iothubowner) 연결 문자열 기록
2. 스트림 애널리틱스 작업 생성
입력: IoT 허브 선택
출력: SQL 애저 데이터베이스 테이블 지정
쿼리: SELECT * INTO SqlAzureMyTelemetry FROM MyTelemetryInputHub
작업 시작
3. 웹앱 + SQL 애저 생성
웹앱 + SQL (무료 F1 티어 가능)
SQL 서버/DB 생성, 관리자 자격증명 설정
스트림 애널리틱스 출력 대상 DB로 연결
4. 디바이스 ID 등록
콘솔 앱으로 Microsoft.Azure.Devices NuGet 패키지 사용해 디바이스 ID 생성 및 키 발급.
string connectionString = "IoT허브연결문자열";
string deviceId = "myDucatiMonsterDevice";
Device device = await registryManager.AddDeviceAsync(new Device(deviceId));
// device.Authentication.SymmetricKey.PrimaryKey 가 디바이스 키
웹 애플리케이션 (ASP.NET, 엔티티 프레임워크)
반응형 대시보드로 모든 텔레메트리 실시간 차트 표시. 데모 계정: demo / demo.
커스텀 도메인 구매/연결도 애저 포털에서 간단 설정 가능.
실차 장착 (두카티 몬스터 695)
타이어 온도 센서: 뒷바퀴 뒤쪽 브라켓에 장착 (거리 40mm 이내)
프론트 초음파: 헤드라이트 아래, 프론트 머드가드까지 거리 측정
리어 초음파: 시트 아래, 리어 타이어까지 거리 측정
메인 유닛(아두이노, GPS, 가속도계, 외부온도): 시트 뒤쪽에 방수 박스로 장착
머신러닝 (애저 ML 스튜디오)
학습 실험
SQL 애저 데이터 임포트 (불량 데이터 필터링: 속도>3, 쇽>0, 롤±60° 등)
Split Data로 학습/테스트 분할
Train Model: 타겟 필드(예: 주행 스타일 클래스) 지정, 알고리즘 선택
Score Model → Evaluate Model로 성능 평가
결과 : Two-Class Decision Forest 알고리즘이 Accuracy, Precision, Recall, F1 모두 1.0 근접으로 최적 성능.
예측 실험 (웹 서비스화)
학습 실험을 예측 실험으로 변환
Multiclass Decision Forest로 다중 클래스 분류 (예: SAFE DRIVING, HIGH STRESS HIGH SPEED 등)
웹 서비스 배포 → 테스트 버튼으로 실시간 추론 가능
발견된 인사이트
오른쪽 린(우회전) 선호, 린 각도는 타이어 온도/속도와 무관 → 타이어 품질 양호
타이어 온도 35°C 이상에서 윌리(앞바퀴 들림) 경향 증가
최종 결론 및 향후 개선 방향
60달러 미만 하드웨어 + 애저 서비스로 모토GP급 텔레메트리 구현 입증
개선 과제: 오프라인 버퍼링(네트워크 단절 시 로컬 저장 후 동기화), 크로스플랫폼 앱(자마린), 고정밀 센서, MKR1000로 소형화, 소셜 공유 웹앱, 스트림 애널리틱스 연동 ML 실시간 피드백
새 워크플로우: 속도>100km/h 시 이벤트 허브 → 클라우드 서비스 → ML 예측 → IoT 허브 → 디바이스(폰)로 경고 알림 푸시
질문과 피드백 환영합니다. 즐거운 메이킹 되세요! :-)
코드
회로도
MotorbikeProject.fzz (프리츠링 파일)