IoT4Car: Fahrzeug-Telemetrie erfassen & analysieren mit Arduino MKR1000 & OBD-II
Komponenten & Materialien
| Arduino MKR WiFi 1000 (oder MKR GSM 1400 für bessere Abdeckung) | ×1 |
| SparkFun Logic Level Converter (Bi-Directional) | ×1 |
| SparkFun OBD-II UART Board (STN1110 / ELM327 kompatibel) | ×1 |
| SparkFun OBD-II auf DB9 Kabel | ×1 |
| LCD 1602 (Parallel, optional für lokales Display) | ×1 |
Software & Cloud
- Arduino IDE
- dweet.io (einfacher IoT-Daten-Endpunkt)
- freeboard.io (Dashboard-Visualisierung)
Projektbeschreibung
Ein OBD-II-Dongle auf Arduino-Basis, der Fahrzeugdaten (Geschwindigkeit, Drehzahl, Tankfüllstand, Kühlmitteltemperatur) ausliest, auf einem LCD anzeigt und per WiFi (Handy-Hotspot) an die Cloud (dweet.io → freeboard.io) sendet. Demonstriert IoT-Fahrzeugüberwachung für Flottenmanagement, Fahrverhalten-Analyse, Predictive Maintenance.
Hardware-Architektur
- OBD-II UART Board: Übersetzt Fahrzeug-Bus (CAN, ISO9141, KWP, VPW, PWM) → UART (ELM327 AT-Befehle). STN1110 Chip.
- Level Shifter: OBD-Board = 5V Logik, MKR1000 = 3,3V Logik → Bidirektionaler Wandler nötig (TX/RX)!
- MKR1000: Serial1 (Pins 13=RX, 14=TX) ↔ Level Shifter ↔ OBD-Board. Serial (USB) ↔ PC (Debug).
- LCD 1602: 4-Bit Modus an D12, D11, D5, D4, D3, D2 (wie im Code).
- Stromversorgung: MKR1000 via USB oder OBD-Pin 16 (Batterie +) → Vin (max 5,5V!) – Spannungsteiler/Regler prüfen!
OBD-II Protokoll Grundlagen
- Dienst
01= Aktuelle Daten (Live Data) - PIDs (Parameter IDs):
0D= Fahrzeuggeschwindigkeit (km/h)0C= Motordrehzahl (RPM × 4)2F= Tankfüllstand (% × 2,55)05= Kühlmitteltemp (°C - 40)
- Befehl:
010D\r→ Antwort:>1 0D 00\r(letzte 2 Hex = Wert)
Arduino Sketch (Vollständig)
/* IoT4Car - OBD-II Telemetrie zu Cloud
Board: Arduino MKR WiFi 1000
Libraries: WiFi101, LiquidCrystal, SPI
*/
#include
#include
#include
// WiFi
char ssid[] = "DEIN_HOTSPOT_SSID";
char pass[] = "DEIN_HOTSPOT_PASS";
char server[] = "www.dweet.io";
WiFiClient client;
unsigned long lastPost = 0;
const unsigned long postInterval = 10000; // 10s
// LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// OBD UART (Serial1)
char rxData[20];
uint8_t rxIndex = 0;
String obdCmd;
int vSpeed = 0, vRPM = 0, vFuel = 0, vTemp = 0;
void setup() {
lcd.begin(16, 2);
lcd.clear();
lcd.print("Verbinde WLAN...");
// WiFi
while (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass);
delay(5000);
}
lcd.clear();
lcd.print("WLAN OK");
// Serial1 für OBD (Pins 13/14)
Serial1.begin(9600);
resetBuffer();
}
void loop() {
// WLAN Reconnect
if (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass);
delay(5000);
}
// Daten abfragen
getSpeed(); // 010D
getRPM(); // 010C
getFuel(); // 012F
getCoolTemp();// 0105
// Cloud Upload
if (millis() - lastPost > postInterval) {
httpRequest();
lastPost = millis();
}
}
// --- OBD Abfrage Funktionen ---
void sendObdCmd(const char* cmd) {
obdCmd = cmd;
Serial1.println(obdCmd);
delay(200);
getResponse();
}
void getSpeed() { sendObdCmd("010D"); vSpeed = strtol(&rxData[6], 0, 16); updateLCD(0, 0, vSpeed, "mph"); }
void getRPM() { sendObdCmd("010C"); vRPM = ((strtol(&rxData[6],0,16)*256) + strtol(&rxData[9],0,16))/4; updateLCD(8, 0, vRPM, "rpm"); }
void getFuel() { sendObdCmd("012F"); vFuel = strtol(&rxData[6],0,16) * 100 / 255; updateLCD(0, 1, vFuel, "%"); }
void getCoolTemp(){sendObdCmd("0105"); vTemp = strtol(&rxData[6],0,16) - 40; updateLCD(8, 1, vTemp, "C"); }
void updateLCD(int col, int row, int val, const char* unit) {
lcd.setCursor(col, row);
lcd.print(" "); // Clear
lcd.setCursor(col, row);
lcd.print(val);
lcd.print(unit);
}
// --- UART Response Parser ---
void getResponse() {
while (Serial1.available()) {
char c = Serial1.read();
if (c == '\r') {
rxData[rxIndex] = '\0';
rxIndex = 0;
break;
}
if (rxIndex < 19) rxData[rxIndex++] = c;
}
}
void resetBuffer() { for(int i=0;i<20;i++) rxData[i]=0; }
// --- Cloud Upload ---
void httpRequest() {
client.stop();
if (client.connect(server, 80)) {
String data = "POST /dweet/for/mkr1000?RPM=";
data += vRPM;
data += "&Speed="; data += vSpeed;
data += "&Fuel="; data += vFuel;
data += "&Temp="; data += vTemp;
client.println(data);
client.println("Host: www.dweet.io");
client.println("Connection: close");
client.println();
} else {
lcd.setCursor(0,0); lcd.print("Cloud Fail ");
}
}
Dashboard (freeboard.io)
- freeboard.io → Neues Dashboard
- Datasource: Type "dweet.io", Thing Name "mkr1000"
- Widgets: 4× Gauge (Speed, RPM, Fuel, Temp) an Datasource-Variablen binden
- Dashboard öffentlich teilen oder per API einbetten
Wichtige Hinweise
- Serial vs Serial1: MKR1000:
Serial= USB (Debug),Serial1= Pins 13/14 (Hardware UART für OBD). UNO/Nano haben nurSerial(Hardware) + SoftwareSerial. - Spannung: OBD-Pin 16 liefert 12V (Batterie). MKR1000 Vin max 5,5V! → DC-DC Wandler (12V→5V) oder USB-Powerbank nutzen.
- WiFi-Reichweite: MKR1000 nur WiFi. Für mobile Nutzung: Handy-Hotspot im Auto. Besser: MKR GSM 1400 (LTE-M/NB-IoT).
- Fahrzeug-Kompatibilität: Funktioniert ab Baujahr 1996 (US) / 2001 (EU Benzin) / 2004 (EU Diesel) mit OBD-II. Protokoll-Autodetektion im STN1110.
- Sicherheit: OBD-Port gibt Zugriff auf Steuergeräte. Nur an eigenen Fahrzeugen testen!
Erweiterungen
- GPS-Modul (NEO-6M) → Position + Speed-Logging
- Beschleunigungssensor (MPU6050) → Fahrstil-Analyse (hartes Bremsen, Kurven)
- CAN-Logger (MCP2515) für Roh-Daten & Reverse Engineering
- MQTT + InfluxDB + Grafana statt dweet/freeboard (lokal, privat, skalierbar)
- OTA-Updates (WiFi101OTA)
Schaltplan
Fritzing-Datei: frizling_schematics_M8kF26dafQ.fzz (im Artikel).
Fazit
Ein komplettes, funktionierendes Vehicle-Telematics-Projekt vom OBD-Bus bis zum Cloud-Dashboard. Zeigt die Stärke der MKR-Serie (WiFi/GSM onboard, 3,3V, klein). Der Code ist modular, gut dokumentiert und erweiterbar. Für Produktion: Robustes Gehäuse, Automotive-qualifizierte Bauteile, CAN-FD Support, Sicherheits-Hardening, Zertifizierung.
Herstellungsprozess
- Der umfassende Leitfaden zu Fahrzeugkennzeichen: Geschichte, Design und Zukunft
- Antiblockiersystem (ABS): Sicherheit auf rutschigen Straßen
- Antriebsstrang verstehen: Wie er Ihr Fahrzeug antreibt
- Lichtmaschine verstehen: Wie sie Ihr Auto mit Strom versorgt und Ausfallanzeichen
- KI-gestütztes Hindernisvermeidungssystem mit Arduino und Ultraschallsensoren
- DIY Arduino USB Gaming Controller – Bauen Sie Ihren eigenen High-Performance Gamepad
- DIY Wolken-Kostüm: LED-Streifen, Arduino Nano & SparkFun Teile
- Chassis-Erdung (Chassis Ground): Zweck, Funktion und Bedeutung
- Fahrgestell-Layout: Motorposition & Antriebskonfigurationen erklärt
- Fahrzeugverkabelung verstehen: Wichtige Konzepte für zuverlässige Automobil-Performance