Based on Pflichtenheft v2.2, documents the full system design including daemon, API, frontend, and infrastructure with agreed deviations (Axum 0.8, SQLx 0.8, Vite 6, Tailwind 4). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
HC-SR04 Ultraschallsensor mit LoRaWAN (LilyGO LoRa32 T3 V1.6.1)
Dieses Projekt liest Distanzmessungen vom HC-SR04 Ultraschallsensor aus und sendet die Daten über LoRaWAN. Die Messwerte werden zusätzlich auf einem OLED-Display angezeigt.
Hardware-Komponenten
- LilyGO LoRa32 T3 V1.6.1 (ESP32 mit SX1276/SX1278 LoRa-Modul)
- HC-SR04 Ultraschallsensor
- OLED Display 128x64 (I2C, SSD1306)
Anschlussplan
HC-SR04 Ultraschallsensor
HC-SR04 LilyGO LoRa32 T3 V1.6.1
-------- -----------------------
VCC <--> 5V (Pin mit 5V-Label)
TRIG <--> GPIO 12
ECHO <--> GPIO 13
GND <--> GND
Wichtig:
- Der HC-SR04 sollte mit 5V betrieben werden für beste Ergebnisse
- Das ECHO-Signal gibt 5V aus! Um den ESP32 zu schützen, verwende einen Spannungsteiler:
- ECHO → 1kΩ Widerstand → GPIO 13 → 2kΩ Widerstand → GND
- Alternativ: Viele HC-SR04 Module haben bereits einen integrierten Spannungsregler
- GPIO 13 ist als INPUT sicher, solange das Signal nicht über 3.6V geht
OLED Display (SSD1306, 128x64, I2C)
OLED Display LilyGO LoRa32 T3 V1.6.1
------------ -----------------------
VCC <--> 3.3V
GND <--> GND
SDA <--> GPIO 21
SCL <--> GPIO 22
Hinweis: Beim LilyGO LoRa32 T3 V1.6.1 sind die I2C-Pins standardmäßig:
- SDA: GPIO 21
- SCL: GPIO 22
LoRa-Modul (bereits auf Board integriert)
Das LoRa-Modul SX1276/SX1278 ist bereits auf dem LilyGO Board integriert und nutzt folgende Pins:
LoRa SX1276 ESP32
----------- -----
NSS (CS) <--> GPIO 18
RST <--> GPIO 23
DIO0 <--> GPIO 26
DIO1 <--> GPIO 33
DIO2 <--> GPIO 32
MOSI <--> GPIO 27
MISO <--> GPIO 19
SCK <--> GPIO 5
Pinout-Übersicht LilyGO LoRa32 T3 V1.6.1
+------------------------+
| LilyGO LoRa32 T3 V1.6 |
| (ESP32) |
+------------------------+
| |
HC-SR04 TRIG -> | GPIO 12 GPIO 21| <- OLED SDA
HC-SR04 ECHO -> | GPIO 13 GPIO 22| <- OLED SCL
| GPIO 15 GPIO 23| <- LoRa RST
| GPIO 2 GPIO 5| <- LoRa SCK
| GPIO 4 GPIO 19| <- LoRa MISO
| GND GPIO 27| <- LoRa MOSI
| 3.3V GPIO 18| <- LoRa NSS
| 5V (VIN) GPIO 26| <- LoRa DIO0
| GPIO 33| <- LoRa DIO1
| GPIO 32| <- LoRa DIO2
+------------------------+
Verfügbare freie GPIOs (falls du weitere Sensoren anschließen möchtest):
- GPIO 2, 4, 15, 25, 34, 35, 36, 39 (36/39 nur Input)
LoRaWAN-Konfiguration
1. The Things Network (TTN) / ChirpStack einrichten
Application erstellen
- Melde dich bei TTN oder deinem ChirpStack-Server an
- Erstelle eine neue Application
Device registrieren
- Erstelle ein neues Device in deiner Application
- Wähle OTAA (Over-The-Air Activation)
- Notiere die folgenden Keys:
- Device EUI (DevEUI) - 8 Bytes
- Application EUI (AppEUI) - 8 Bytes
- Application Key (AppKey) - 16 Bytes
2. Keys im Code eintragen
Öffne die Datei src/main.cpp und trage deine Keys ein:
// LoRaWAN Keys (hier deine echten Werte eintragen)
static const u1_t PROGMEM APPEUI[8] = { 0x01, 0x00, 0x00, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
static const u1_t PROGMEM DEVEUI[8] = { 0xB2, 0xA1, 0x05, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
static const u1_t PROGMEM APPKEY[16] = { 0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x07, 0x18, 0x29, 0x38, 0x47, 0x56, 0xAB, 0xCD, 0xEF, 0x12 };
Wichtig: Die Keys müssen in LSB (Least Significant Byte) Format eingetragen werden!
Beispiel: TTN Keys konvertieren
Wenn TTN dir die Keys so anzeigt:
DevEUI: 70B3D57ED005A1B2
AppEUI: 0000000000000001
AppKey: A1B2C3D4E5F6071829...
Dann musst du sie für LMIC umkehren (LSB):
// DevEUI: 70B3D57ED005A1B2 -> LSB
static const u1_t PROGMEM DEVEUI[8] = { 0xB2, 0xA1, 0x05, 0xD0, 0x7E, 0xD5, 0xB3, 0x70 };
// AppEUI: 0000000000000001 -> LSB
static const u1_t PROGMEM APPEUI[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// AppKey: bleibt in MSB Format (wird nicht umgedreht)
static const u1_t PROGMEM APPKEY[16] = { 0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x07, 0x18, ... };
3. Sendeintervall anpassen
Das Sendeintervall kann in src/main.cpp:32 angepasst werden:
const unsigned TX_INTERVAL = 30; // Sendeintervall in Sekunden
Payload-Format
Der Sensor sendet die Distanz als 2 Bytes (uint16_t):
| Byte | Beschreibung |
|---|---|
| 0 | High Byte (Distanz in mm) |
| 1 | Low Byte (Distanz in mm) |
Beispiel:
- Distanz: 123.4 cm = 1234 mm
- Hex:
0x04D2 - Payload:
04 D2
Messbereich: 0 - 65535 mm (0 - 65.5 m)
ChirpStack Decoder
Füge folgenden Decoder in ChirpStack unter Device Profile → Codec ein:
JavaScript Decoder (ChirpStack v3)
function Decode(fPort, bytes) {
// Decoder für HC-SR04 Ultraschallsensor
// Payload: 2 Bytes - Distanz in Millimeter (uint16_t)
if (bytes.length !== 2) {
return {
error: "Invalid payload length"
};
}
// Distanz aus 2 Bytes (Big Endian) auslesen
var distanceMm = (bytes[0] << 8) | bytes[1];
// Umrechnung in verschiedene Einheiten
var distanceCm = distanceMm / 10.0;
var distanceM = distanceMm / 1000.0;
return {
distance_mm: distanceMm,
distance_cm: distanceCm,
distance_m: distanceM
};
}
JavaScript Decoder (ChirpStack v4)
function decodeUplink(input) {
// Decoder für HC-SR04 Ultraschallsensor
// Payload: 2 Bytes - Distanz in Millimeter (uint16_t)
var bytes = input.bytes;
if (bytes.length !== 2) {
return {
errors: ["Invalid payload length"]
};
}
// Distanz aus 2 Bytes (Big Endian) auslesen
var distanceMm = (bytes[0] << 8) | bytes[1];
// Umrechnung in verschiedene Einheiten
var distanceCm = distanceMm / 10.0;
var distanceM = distanceMm / 1000.0;
return {
data: {
distance_mm: distanceMm,
distance_cm: distanceCm,
distance_m: distanceM
}
};
}
Decoder testen
Test-Payload: 04 D2 (1234 mm)
Erwartetes Ergebnis:
{
"distance_mm": 1234,
"distance_cm": 123.4,
"distance_m": 1.234
}
The Things Network (TTN) Payload Formatter
Für TTN unter Applications → Payload Formatters → Uplink:
function decodeUplink(input) {
var bytes = input.bytes;
if (bytes.length !== 2) {
return {
errors: ["Invalid payload length"]
};
}
// Distanz aus 2 Bytes (Big Endian) auslesen
var distanceMm = (bytes[0] << 8) | bytes[1];
return {
data: {
distance_mm: distanceMm,
distance_cm: distanceMm / 10.0,
distance_m: distanceMm / 1000.0
}
};
}
Installation und Verwendung
Voraussetzungen
- PlatformIO (VS Code Extension oder CLI)
- USB-Treiber für CP2102 (falls nicht installiert)
Projekt kompilieren und hochladen
# Projekt bauen
pio run
# Auf Board hochladen
pio run --target upload
# Serial Monitor öffnen
pio device monitor
Serial Monitor Ausgabe
Nach dem Upload solltest du folgende Ausgabe sehen:
Starte HC-SR04 + OLED + LoRa
Beitritt läuft...
Netzwerkbeitritt erfolgreich
Distanz gesendet:
Distanz: 123.4 cm
Distanz: 1234.0 mm
Nachricht übertragen.
Bibliotheken
Die benötigten Bibliotheken werden automatisch über PlatformIO installiert (siehe platformio.ini):
gamegine/HCSR04 ultrasonic sensor- HC-SR04 Treiberadafruit/Adafruit SSD1306- OLED Displayadafruit/Adafruit GFX Library- Grafik-Bibliothekmcci-catena/MCCI LoRaWAN LMIC library- LoRaWAN Stack (wird automatisch vom Framework geladen)
Fehlerbehebung
Device joint nicht
- Überprüfe die Keys (DevEUI, AppEUI, AppKey)
- Achte auf LSB-Format bei DevEUI und AppEUI
- Prüfe die LoRaWAN-Frequenz (EU868, US915, etc.)
- Stelle sicher, dass ein Gateway in Reichweite ist
HC-SR04 liefert -1 oder fehlerhafte Werte
- Überprüfe die Verkabelung (TRIG → GPIO 15, ECHO → GPIO 13)
- Prüfe die Stromversorgung (min. 5V für HC-SR04 empfohlen)
- Halte Hindernisse im Messbereich (2 cm - 4 m)
- Verwende ggf. einen Spannungsteiler für ECHO (5V → 3.3V)
OLED Display zeigt nichts an
- Überprüfe die I2C-Verbindung (SDA → GPIO 21, SCL → GPIO 22)
- Prüfe die I2C-Adresse (Standard: 0x3C)
- Stelle sicher, dass die richtigen I2C-Pins verwendet werden (LilyGO T3 V1.6.1 nutzt GPIO 21/22)
- Verwende einen I2C-Scanner zur Diagnose
Kompilierungsfehler
# Cache löschen und neu bauen
pio run --target clean
pio run
Energieverbrauch
- Deep Sleep: Nicht implementiert (kontinuierlicher Betrieb)
- Stromverbrauch: ~100-150 mA (ESP32 + LoRa TX)
- Empfehlung: Für batteriebetriebenen Einsatz Deep Sleep zwischen Messungen implementieren
Lizenz
Dieses Projekt ist Open Source und steht unter der MIT-Lizenz.