4. Project4 - Esp32 verbindung mit Meshnetzwerk¶
4.1. Projektaufbau¶
Eines der letzten Projekte behandelte das Thema MQTT und das Broker Netzwerk, welches ein gerne genutztes Protokoll für IoT Gerätekommunikation ist. Dieses mal soll es um eine weitere Vernetzungsmöglichkeit für IoT Geräte gehen - Ein Mesh Netzwerk. Um das Mesh-Netzwerk zu testen, werden vier ESP32 verwendet. Es gibt eine Collector Node, die eine LED-Diode mit dem IO-Port 02 verbunden hat. Diese Node erwartet ein Ein- und Ausschaltsignal für diese Diode sowie Temperaturwerte, die dann im seriellen Output geloggt werden. Zum Senden des Ein- und Ausschaltsignals und der Temperatur werden jeweils zwei weitere Nodes verwendet. Zur Verdeutlichung des Mesh-Netzwerks sind die beiden Nodes, die Daten senden, weiter entfernt, und die vierte Node dient zur Überbrückung der Distanz.
4.2. Meshnetzwerk¶
Ein Meshnetzwerk ist ein Netzwerk, in dem alle Geräte bzw. Knoten direkt oder indirekt miteinander kommunizieren können – ohne einen zentralen Router. Jeder Knoten kann: - Daten empfangen und senden - Nachrichten an andere Knoten weiterleiten (Relay-Funktion) - Neue Verbindungen automatisch aufbauen, wenn Knoten sich verbinden oder trennen
4.3. Verwendete Techniken¶
4.3.1. Painless Mesh¶
Überblick
painlessMesh ist eine Arduino-kompatible Bibliothek zur einfachen Erstellung von dynamischen Mesh-Netzwerken
mit ESP8266- und ESP32-Mikrocontrollern.
Die Bibliothek verwaltet automatisch: - die Verbindungsstruktur zwischen Knoten - Routing von Nachrichten - Wiederverbindungen bei Netzänderungen
Grundfunktionen
Netzwerkaufbau ohne zentralen Server oder Gateway
Automatische Adressierung und Weiterleitung von Nachrichten
Unterstützung für Broadcast- und direkte Kommunikation
Kompatibel mit ESP8266 und ESP32
Unterstützung für Task-Scheduling über Scheduler
Nutzung
#include <painlessMesh.h>
painlessMesh mesh;
void setup() {
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION); // Optional: Debug-Ausgaben aktivieren
mesh.init("NetzwerkName", "Passwort", 5555, WIFI_AP_STA, 6); // Initialisierung
mesh.onReceive([](uint32_t from, String &msg) {
Serial.println("Nachricht empfangen: " + msg); //Ausgabe von empfangenen Nachrichten
});
}
void loop() {
mesh.update(); // Muss regelmäßig aufgerufen werden
}
Nutzung mit Scheduler Mit einem Scheduler-Objekt können wiederkehrende Aufgaben eingeplant werden:
Scheduler userScheduler; // Scheduler-Objekt für benutzerdefinierte periodische Tasks
Task blinkTask(1000, TASK_FOREVER, []() { // Definition eines Tasks, der alle 1000 ms (1 Sekunde) ausgeführt wird
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // Onboard-LED an- und ausschalten
});
void setup() {
mesh.init("NetzwerkName", "Passwort", &userScheduler, 5555, WIFI_AP_STA, 6); // Initialisierung mit scheduler
userScheduler.addTask(blinkTask); // Fügt den blinkTask dem Scheduler hinzu
blinkTask.enable(); // Aktiviert den Task, sodass er automatisch im Hintergrund läuft
}
Vorteile - Keine zentrale Steuerung notwendig (keine Single Points of Failure) - Skalierbar durch automatische Topologieanpassung - Ideal für mobile oder instabile Funkverbindungen - Geeignet für dezentrale IoT-Netze
Einschränkungen - Keine Ende-zu-Ende-Verschlüsselung eingebaut - Keine Authentifizierung einzelner Nodes - Begrenzte Reichweite und Bandbreite durch WiFi-Basis
4.3.2. Arduino IDE¶
Die Arduino IDE ist eine plattformübergreifende Entwicklungsumgebung zur Programmierung von Mikrocontrollern. Mit ihr kann auch der ESP32 programmiert, konfiguriert und überwacht werden. Sie bietet Funktionen zum Editieren, Kompilieren, Hochladen von Code sowie zur seriellen Kommunikation mit dem Gerät.
Zur verwendung von ESP32 muss die Boardunterstützung zuerst über den Boardverwalter hinzugefügt werden.
Nach dem Verbinden per USB Kabel muss auch noch der jeweilige USB Port in der IDE ausgewählt werden.
Das schreiben, kompilieren und hochladen des Codes ist ebenfalls sehr einfach:
#. Schreibe den Code in eine .ino-Datei in der IDE.
#. Klicke auf das Hochladen-Symbol (Pfeil nach rechts).
#. Die IDE kompiliert den den Code und lädt ihn auf den ESP32.
#. Beim hochladen des Codes muss die BOOT-Taste des ESP32 gedrückt gehalten werden.
Sobald der ESP32 den Code ausführt kann man sich die seriellen Logs direkt in der IDE direkt anzeigen lassen. Hierzu muss man lediglich den Serial Montor unter Tools öffnen und die Baudrate vor dem verbinden richtig einstellen.
4.4. Knoten¶
Im Folgenden werden die einzelnen Knoten mit ihrer jeweiligen Funktion erläutert.
4.4.1. Node_Bridge¶
Funktion: Diese Node dient als Brücke zwischen der collector Node und den beiden Sender Nodes.
Code: Starten die serielle Verbindung zum Computer mit 115200 Baud:
Serial.begin(115200);
Folgender Code dient zur Ausgabe von Texten im seriellen Monitor:
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
Zeigt bestimmte Debug-Nachrichten:
ERROR: Fehler
STARTUP: Startinformationen
CONNECTION: Verbindungsstatus
Starten und Verbinden mit Hilfe der PainlessMesh Bibliothek: .. code-block:: cpp
mesh.init(„espMesh“, „password123“, 5555, WIFI_AP_STA, 6);
verwendete Parameter: - „espMesh“: Name (SSID) des Mesh-Netzwerks – muss bei allen Knoten gleich sein - „password123“: Passwort des Netzwerks - 5555: Port, über den kommuniziert wird (bei allen Knoten gleich) - WIFI_AP_STA: WLAN-Modus (Access Point + Station) für Mesh-Funktion - 6: WLAN-Kanal – muss bei allen Knoten gleich sein
Bei erfolgreicher Verbindung weiterer Nodes erscheinen folgende Nachrichten in den Logs:
CONNECTION: eventScanDoneHandler: ARDUINO_EVENT_WIFI_SCAN_DONE
CONNECTION: scanComplete(): Scan finished
CONNECTION: scanComplete():--> Cleared old APs.
CONNECTION: scanComplete(): num = 26
CONNECTION: found : espMesh, -57dBm
CONNECTION: found : espMesh, -57dBm
CONNECTION: Found 2 nodes
CONNECTION: connectToAP(): No unknown nodes found scan rate set to normal
Hier sieht man wie viele Nodes Verbunden sind und deren Verbindungsstärke.
4.4.2. Node_Collector¶
Funktion: Dieser Knoten empfängt Nachrichten von anderen Geräten und:
Schaltet eine verbundene LED an oder aus (erwartete Signale: LED_ON / LED_OFF)
Gibt eine Meldung aus, wenn Temperaturdaten empfangen werden
Logged jede Nachricht mit Zeitstempel
Code: Erstellung der Zeit-Angabe:
void receivedCallback(uint32_t from, String &msg) {
String timestamp = String(hour()) + ":" + String(minute()) + ":" + String(second());
logMessages += "[" + timestamp + "] From " + String(from) + ": " + msg + "\n";
}
LED-Reaktion:
if (msg == "LED_ON") {
digitalWrite(LED_PIN, HIGH);
}
else if (msg == "LED_OFF") {
digitalWrite(LED_PIN, LOW);
}
Temperaturerkennung:
else if (msg.indexOf("Temp") != -1) {
Serial.println("warm:");
}
Zeitstempel setzen für das Logging:
setTime(12, 0, 0, 1, 1, 2025);
Auch hier die Mesh-Initialisierung (mit userScheduler):
mesh.init("espMesh", "password123", &userScheduler, 5555, WIFI_AP_STA, 6);
Timeoutwarnung mit Scheduler:
Task checkTimeoutTask(10000, TASK_FOREVER, []() {
if (millis() - lastMessageTime > 15000) {
Serial.println("WARNUNG: Keine Nachricht seit 15 Sekunden! Bitte Verbindung zu Sendern prüfen.");
}
});
Variablen:
#define LED_PIN 2 - Deklaration der Pin, über die die LED gesteuert wird
String logMessages = „“; - String zur Ausgabe der Logs
bool ledState = false; - LED zu beginn auf „OFF“
Hier ist ein Beispiel der Log Meldungen aus dem Serial Monitor:
LOG: [12:0:25] From 4234133741: {"temp": 20.80}
LOG: [12:0:25] From 4234133741: {"temp": 29.50}
LOG: [12:0:25] From 4234133741: {"temp": 24.60}
LOG: [12:0:26] From 3520580029: LED_ON
LOG: [12:0:26] From 4234133741: {"temp": 21.20}
LOG: [12:0:27] From 4234133741: {"temp": 29.60}
LOG: [12:0:28] From 4234133741: {"temp": 23.20}
LOG: [12:0:29] From 4234133741: {"temp": 27.10}
LOG: [12:0:30] From 4234133741: {"temp": 29.60}
LOG: [12:0:31] From 3520580029: LED_OFF
4.4.3. Node_Led_Signal¶
Funktion: Dieser Knoten sendet alle 5 Sekunden eine Nachricht basierend auf dem internen Zustand: - „LED_ON“ wenn die LED ausgeschaltet war - „LED_OFF“ wenn die LED an war
Code: Das Senden der Nachrichten passiert über einen Task (repetitive Funktion):
Task sendMessageTask(SEND_INTERVAL, TASK_FOREVER, []() {
ledState = !ledState;
String msg = ledState ? "LED_ON" : "LED_OFF";
mesh.sendBroadcast(msg);
});
Die Messagetask wird anhand von Scheduler aktualisiert, hierfür muss man den Task aktivieren:
userScheduler.addTask(sendMessageTask);
sendMessageTask.enable();
Empfangsbestätigung der Nachricht:
mesh.onReceive([](uint32_t from, String &msg) {
Serial.println("Received something: " + msg);
});
Variablen: bool ledState = false; - Intern gespeicherter Zustand der LED
4.4.4. Node_Temperature¶
Dieser Knoten simuliert eine Temperaturmessung und sendet sie jede Sekunde als Nachricht:
float fakeTemp = random(200, 300) / 10.0;
String msg = "{\"temp\": " + String(fakeTemp) + "}";
mesh.sendBroadcast(msg);
Auch hier wird ein Task verwendet, damit der Code unabhängig von loop() regelmäßig läuft.
userScheduler.addTask(taskSendTemp);
taskSendTemp.enable();
4.5. Vergleich Mesh und MQTT-Broker¶
Struktur
Mesh-Netzwerk: Dezentral, jeder ist Knoten
MQTT mit zentralem Broker: Zentraler Server (Broker)
Kommunikation
Mesh-Netzwerk: Direkt oder über Relais-Knoten
MQTT mit zentralem Broker: Über definierte Topics via Broker
Abhängigkeit
Mesh-Netzwerk: Kein zentraler Punkt
MQTT mit zentralem Broker: Broker als zentraler Punkt notwendig
Robustheit
Mesh-Netzwerk: Hoch (Selbstheilung möglich)
MQTT mit zentralem Broker: Geringer bei Ausfall des Broker
Einrichtung
Mesh-Netzwerk: Bibliothek + einfache Initialisierung
MQTT mit zentralem Broker: Komplexer (hostapd, DHCP, Broker)
Beobachtung / Logging
Mesh-Netzwerk: Lokale Logs auf Geräten
MQTT mit zentralem Broker: Zentrale Protokollierung über Broker
Beispielhafte Anwendung
Mesh-Netzwerk: LED-Steuerung, Temperaturwarnung
MQTT mit zentralem Broker: Schaltbefehle über Weboberfläche
4.6. Meshnetzwerk-Test¶
4.6.1. Ziel des Tests¶
Überprüfung der Reichweite und Funktionalität der automatischen Nachrichtenweiterleitung im Mesh-Netzwerk mithilfe von painlessMesh.
4.6.2. Testaufbau¶
Drei ESP32-Boards wurden wie folgt verwendet:
Gerät A: Sender-Node
Gerät B: Empfänger-Node
Gerät C: Diente als Brücke (Relay-Knoten), also eine Repeater-Funktion im Mesh
4.6.3. Ablauf¶
Startkonfiguration: Alle drei Geräte befinden sich in Funkreichweite zueinander. Gerät A sendet Temperaturdaten. Gerät B empfängt und loggt die Daten korrekt.
Entfernungstest: Gerät A wurde schrittweise vom restlichen Aufbau entfernt. Sobald Gerät A außer Reichweite von Gerät B war, festgestellt durch Timeoutwarnung, kam es zu Nachrichtenausfällen – die Temperaturdaten wurden nicht mehr empfangen.
Mesh-Wiederherstellung: Gerät C wurde nun zwischen A und B positioniert – auf halber Strecke, sodass beide Geräte wieder Reichweite zu Gerät C hatten. Sofort nach der neuen Positionierung wurde das Netzwerk dynamisch reorganisiert. Die Nachrichten von A konnten über Gerät C an B weitergeleitet werden. Die Logs auf Gerät B zeigten erneut die Temperaturdaten von Gerät A – das Mesh funktionierte wieder zuverlässig.
4.6.4. Beobachtungen¶
Ohne Relay-Gerät: keine Verbindung zwischen A und B bei zu großer Entfernung
Mit Relay-Gerät: Netzwerk funktionierte wie gewünscht – automatische Weiterleitung durch dynamische Mesh-Struktur
Die Umorganisation dauerte nur wenige Sekunden – dies zeigt die Selbstheilungsfähigkeit des Meshnetzwerks
4.6.5. Schlussfolgerung¶
Der Test demonstrierte anschaulich die Stärke eines Meshnetzwerks:
Flexible Topologie
Keine Notwendigkeit fester Infrastruktur
Dynamische Anpassung an die Umgebung und Funkreichweite
Die praktische Umsetzung zeigte, dass painlessMesh auch unter realen Bedingungen mit Entfernung und Hindernissen zuverlässige Kommunikation sicherstellen kann – vorausgesetzt, ein Relay-Gerät ist innerhalb der erforderlichen Reichweite vorhanden.
4.7. Fazit¶
painlessMesh vereinfacht das Erstellen stabiler Meshnetzwerke mit ESP32. Die Kombination aus Scheduler, onReceive() und sendBroadcast() erlaubt: - Automatische Nachrichtenverarbeitung - Wiederholte Aufgaben ohne die Haupt-Loop zu blockieren Die Knoten können verschiedenste Rollen übernehmen: Sender, Empfänger, Relais, Logger usw.
4.8. Quellen¶
[PainlessMesh](https://gitlab.com/painlessMesh/painlessMesh)
[ArduinoIDE](https://www.arduino.cc/en/software/)
[ESP32](https://www.az-delivery.de/products/esp32-developmentboard)