
Ziel des Projekts
- bis zu drei Mikrocontroller unabhängig von einem bestehenden Router in einem eigenen WLAN-Netz betreiben
alternativ: die Mikrocontroller in das vorhandenen WLAN einbinden - mit beliebigen Temperatursensoren (hier DHT11/DHT22) an bis zu drei verschiedenen Orten die Temperatur messen
- die ermittelten Messwerte in einem Webbrowser anzeigen
![]() | ![]() |
Die beiden Ansichten unterscheiden sich lediglich durch den verwendeten Netzwerkmodus und damit der verwendeten IP-Adresse:
links wird der ⇒Stationsmodus, rechts der ⇒Access-Point-Modus verwendet

Benötigte Bauteile
- ESP32-Mikrocontroller oder ESP8266-Mikrocontroller in beliebiger Kombination
- DHT11/DHT22 Temperatursensoren
- Leitungsdrähte
Konfiguration der Mikrocontroller
Netzwerkmodi der ESP-Mikrocontroller
Stations-Modus
Stations-Modus mit DHCP
Im Stations-Modus (STA) verwendet der Mikrocontroller das WLAN-Netz der Routers und erhält von dort eine IP-Adresse. Diese wird dynamisch zugewiesen, es kann jedes Mal eine andere sein (DHCP = Dynamic Host Configuration Protocol).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#ifdef ESP8266 #include "ESP8266WiFi.h" #else #include "WiFi.h" #endif char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxxx"; void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial); delay(1000); WiFi.mode(WIFI_STA); WiFi.begin(Router, Passwort); while (WiFi.status() != WL_CONNECTED) { delay(200); Serial.print("."); } // SSID des Routers anzeigen Serial.println(); Serial.print("Verbunden mit "); Serial.println(WiFi.SSID()); Serial.print("IP-Adresse: "); Serial.println(WiFi.localIP()); } void loop() { // bleibt leer, das Programm läuft nur einmal } |

Stations-Modus mit statischer IP-Adresse
Für dieses Projekt wird aber eine statische IP-Adresse benötigt, sie soll ja im Klient aufgerufen werden.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#ifdef ESP8266 #include "ESP8266WiFi.h" #else #include "WiFi.h" #endif char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxxx"; // statische IP-Adresse IPAddress ip(192, 168, 1, 5); IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial); delay(1000); WiFi.mode(WIFI_STA); WiFi.config(ip, gateway, subnet); WiFi.begin(Router, Passwort); // SSID des Routers anzeigen Serial.println(); Serial.print("Verbunden mit "); Serial.println(WiFi.SSID()); Serial.println(); Serial.print("IP-Adresse: "); Serial.println(WiFi.localIP()); } void loop() { // bleibt leer, das Programm läuft nur einmal } |

AP-Modus (Accesspoint-Modus)
Beim AP-Modus bauen die ESPs ein eigenes Netz auf, du musst ihnen neben dem Namen des Routers und dem Passwort einige Daten mitteilen:
IPAddress ip(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#ifdef ESP8266 #include "ESP8266WiFi.h" #else #include "WiFi.h" #endif // Netzwerkname und Passwort des ESP char Router[] = "ESPServer"; char Passwort[] = "espserver"; // Server und Klient IPAddress ip(192, 168, 4, 1); IPAddress gateway(192, 168, 4, 1); IPAddress subnet(255, 255, 255, 0); void setup() { Serial.begin(9600); // auf serielle Verbindung warten while (!Serial); delay(1000); // ESP als Access-Point (AP) konfigurieren WiFi.softAPConfig(ip, gateway, subnet); // Access-Point starten WiFi.mode(WIFI_AP); WiFi.softAP(Router, Passwort); // SSID des Routers anzeigen Serial.println(); Serial.print("Verbunden mit "); Serial.println(WiFi.softAPSSID()); Serial.print("IP-Adresse: "); Serial.println(WiFi.softAPIP()); } void loop() { // bleibt leer, das Programm läuft nur einmal } |


Ein Smartphone sucht über das mobile Netz im Internet nach der IP-Adresse des ESPServers (192.168.4.1). Da kein DNS-Server erreichbar ist, kann die Seite nicht angezeigt werden. Verwende stattdessen
http://192.168.4.1
ESP im AP-Modus verwenden
Aufbau des AP-Netzes
Als Klienten können alle WLAN-fähigen Geräte verwendet werden.

Das Schaubild zeigt den Aufbau des Netzes und die Kommunikation der Geräte untereinander. Ich habe einen ESP32-WROOM gewählt, du kannst aber auch eine beliebige Kombination von ESP32 oder ESP8266-Mikrocontrollern verwenden.
Der Mikrocontroller mit der IP 192.168.4.1 baut das WLAN-Netz auf und erhebt gleichzeitig auch Temperaturdaten. Die Mikrocontroller Host 1 und Host 2 messen ebenfalls die Temperatur. In regelmäßigen Abständen fragt der Server diese Messdaten ab. Die Klienten zeigen die Daten an.
Änderungen bei zwei Hosts
Solltest du nur zwei Mikrocontroller zur Verfügung haben, kannst du das Programm leicht anpassen.
Du musst nur im Programm für den ⇒Server in den Zeilen 96, 123 und 124 // davor setzen.
Manuelle Konfiguration des Klienten
Den Klienten werden keine IP-Adressen automatisch zugeteilt. Daher muss die Konfiguration händisch erledigt werden.
Zunächst musst du das als „ESPServer“ angezeigte WLAN auswählen und anschließend die Konfiguration anpassen.
Wenn du mehrere Klienten verwenden willst, musst du jeweils eine andere IP-Adresse verwenden (z. B. 192.168.4.5). Die Adresse des Routers bleibt unverändert.
iOS
Android
Windows 10



ESP als Server und Klient
Ein ESP soll als Server die Daten der anderen ESPs einsammeln und gleichzeitig als Klient ebenfalls die Temperatur messen.
Daher wird für die IP-Adresse und das Gateway die gleiche IP verwendet.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
#ifdef ESP8266 #include "ESP8266WebServer.h" ESP8266WebServer Server(80); #else #include "WiFi.h" #include "WebServer.h" WebServer Server(80); #endif #include "DHT.h" // Pin des DHT-Sensors int SENSOR_DHT = 19; // Sensortyp festlegen // DHT22 oder DHT11 #define SensorTyp DHT11 // Sensor DHT einen Namen zuweisen DHT dht(SENSOR_DHT, SensorTyp); // unterscheiden der Hosts #define HOST_1 0 #define HOST_2 1 // IP-Adressen der Hosts const char* host_1 = "192.168.4.2"; const char* host_2 = "192.168.4.3"; // Array für die Messung String Messung[2] = {"",""}; unsigned long Wartezeit = 15000; // Netzwerkname und Passwort des ESP char Router[] = "ESPServer"; char Passwort[] = "espserver"; // Konfiguration als Server und Klient IPAddress ip(192, 168, 4, 1); IPAddress gateway(192, 168, 4, 1); IPAddress subnet(255, 255, 255, 0); // farbiger Button mit CSS String Seitenkopf = "<head><style>" ".farbigeBox {" "background-color: ivory;" "color: black;" "width: 450px;" "padding: 20px;" "text-align: left;" "font-size: 40px;" "font-family: arial;" "}" "</style>" // refresh -> Seite automatisch aktualisieren "<meta http-equiv=\"refresh\" content=\"30\"></head>"; void setup() { // ESP als Access-Point (AP) konfigurieren WiFi.mode(WIFI_AP); WiFi.softAPConfig(ip, gateway, subnet); // Access-Point starten WiFi.softAP(Router, Passwort); // / -> Aufruf der URL, SeiteBauen -> Aufruf der Funktion Server.on("/", SeiteBauen); Server.begin(); Serial.begin(9600); // DHT starten dht.begin(); } void loop() { static unsigned long Startzeit = millis(); // auf Anfragen warten Server.handleClient(); // Messdaten einsammeln if ((millis() - Startzeit) > Wartezeit) { // Daten der Hosts einsammeln DatenHolen(HOST_1); // wenn nur 2 ESPs -> // davor setzen DatenHolen(HOST_2); Startzeit = millis(); } } void SeiteBauen() { // Messwert ermitteln // . durch , ersetzen String Temperatur = String(dht.readTemperature()); Temperatur.replace(".", ","); // Seite zusammen bauen String Seite = ""; Seite += Seitenkopf; Seite += "<h1 align=\"left\">Raumtemperatur</h1>"; Seite += "<div align=\"left\";>"; Seite += "<div class=\"farbigeBox\">"; Seite += "Bad: "; Seite += Temperatur + " °C"; Seite += "<br>"; Seite += "Wohnzimmer:"; Seite += String(Messung[HOST_1]); Seite += "<br>"; // wenn nur 2 ESPs // vor die nächsten Zeilen setzen Seite += "Esszimmer:"; Seite += String(Messung[HOST_2]); Seite += "</div>"; // Button aktualisieren Seite += "<hr><input style=\"font-size:16pt; font-weight:bold;"; Seite += "background-color:#55A96B;"; Seite += "display:block; cursor:pointer;\"type=\"button\""; // IP für den Button aktualisieren (location.href) // muss mit dem Wert für IPAdress übereinstimmen (. statt ,) Seite += " onClick =\"location.href='http://192.168.4.1'\" value=\"aktualisieren\">"; Seite += "<hr>"; // Seite übermitteln Server.send(200, "text/html", Seite); } void DatenHolen(int hostNo) { WiFiClient client; String host = ""; // Namen des Host zuweisen (host_1) if(hostNo == HOST_1) { host = host_1; // wenn der Host nicht verbunden werden kann // zurück zur aufgerufenen Funktion if (!client.connect(host_1, 80)) return; } // Namen des Host zuweisen (host_2) if(hostNo == HOST_2) { host = host_2; // wenn der Host nicht verbunden werden kann // zurück zur aufrufenden Funktion if (!client.connect(host_2, 80)) return; } /* GET-Anfrage senden /Messung -> Adresse (URL) für die zu übermittelnden Werte wird von den Klienten festgelegt host -> der jeweilige Klient HTTP/1.1 -> Abfrageprotokoll \r\n -> return mit anschließender neuer Zeile */ client.print(String("GET ") + "/Messung" + " HTTP/1.1\r\n" + host + "\r\n"); unsigned long LetzteZeit = millis(); // Wartezeit zwischen den Abfragen der Klienten while (!client.available() && ((millis() - LetzteZeit) < 3000)) { delay(1); } // der Klient ist verfügbar while (client.available()) { // den mit GET erhaltenen String bis zum return (\r) lesen String Daten = client.readStringUntil('\r'); // wenn Daten vorhanden sind if(Daten != "") { Messung[hostNo] = Daten; Serial.println(Daten); } } } |
Darstellung der GET-Anfrage im Seriellen Monitor

ESP als Host
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#ifdef ESP8266 #include "ESP8266WebServer.h" ESP8266WebServer Server(80); #else #include "WiFi.h" #include "WebServer.h" WebServer Server(80); #endif // Bibliothek für DHT einbinden #include "DHT.h" // Pin des DHT-Sensors int SENSOR_DHT = 19; // Sensortyp festlegen // DHT22 oder DHT11 #define SensorTyp DHT22 // Sensor DHT einen Namen zuweisen DHT dht(SENSOR_DHT, SensorTyp); // ESP als AP char Router[] = "ESPServer"; char Passwort[] = "espserver"; // IP des Klienten ESP als AP IPAddress ip(192, 168, 4, 2); IPAddress gateway(192, 168, 4, 1); IPAddress subnet(255, 255, 255, 0); void setup() { // WiFi starten WiFi.config(ip, gateway, subnet); WiFi.begin(Router, Passwort); // Adresse (URL)festlegen (/Messung) // SeiteBauen -> zu übermittelnde Daten Server.on("/Messung", SeiteBauen); Server.begin(); // DHT starten dht.begin(); } void loop() { // auf Anfragen warten Server.handleClient(); } void SeiteBauen() { // Messwerte ermitteln // . durch , ersetzen String Temperatur = String(dht.readTemperature()); Temperatur.replace(".", ","); // Seite zusammenbauen String Seite = Temperatur + " °C"; // Seite übermitteln Server.send(200, "text/html", Seite); } |
Das Heimnetz verwenden
Das Programm für den zweiten Host unterscheidet sich in Zeile 26. Sie muss lauten:
IPAddress ip(192, 168, 4, 3);
Die Mikrocontroller sollen direkt ins heimische Netz eingebunden werden. Hierzu musst du die IP-Adresse des Routers feststellen und dann die IP-Adressen der Mikrocontroller anpassen. Diese müssen sich im gleichen Adressbereich befinden. Außerdem musst du beachten, dass sich diese Adressen außerhalb des Bereichs befinden, das vom DHCP-Server des Routers reserviert ist. Die IP-Adressen der Klienten werden vom Router dynamisch vergeben.
ESP als Server und Klient
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
#ifdef ESP8266 #include "ESP8266WebServer.h" ESP8266WebServer Server(80); #else #include "WiFi.h" #include "WebServer.h" WebServer Server(80); #endif #include "DHT.h" // Pin des DHT-Sensors int SENSOR_DHT = D1; // Sensortyp festlegen // DHT22 oder DHT11 #define SensorTyp DHT11 // Sensor DHT einen Namen zuweisen DHT dht(SENSOR_DHT, SensorTyp); #define HOST_1 0 #define HOST_2 1 // Router als AP const char* host_1 = "192.168.1.7"; const char* host_2 = "192.168.1.8"; String Messung[2] = {"",""}; unsigned long Wartezeit = 15000; char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxxx"; // MCU als Server und Klient IPAddress ip(192, 168, 1, 6); // IP-Adresse des Routers IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); // farbiger Button mit CSS String Seitenkopf = "<head><style>" // farbiger Button mit CSS ".farbigeBox {" "background-color: ivory;" "color: black;" "width: 450px;" "padding: 20px;" "text-align: left;" "font-size: 40px;" "font-family: arial;" "}" "</style>" // refresh -> Seite automatisch aktualisieren "<meta http-equiv=\"refresh\" content=\"30\"></head>"; void setup() { // Router als AP WiFi.mode(WIFI_STA); WiFi.config(ip, gateway, subnet); WiFi.begin(Router, Passwort); // / -> Aufruf der URL, SeiteBauen -> Aufruf der Funktion Server.on("/", SeiteBauen); Server.begin(); Serial.begin(9600); // DHT starten dht.begin(); } void loop() { static unsigned long Startzeit = millis(); // auf Anfragen warten Server.handleClient(); // Messdaten einsammeln if ((millis() - Startzeit) > Wartezeit) { // Daten der Hosts einsammeln DatenHolen(HOST_1); DatenHolen(HOST_2); Startzeit = millis(); } } void SeiteBauen() { // Messwert ermitteln // . durch , ersetzen String Temperatur = String(dht.readTemperature()); Temperatur.replace(".", ","); // Seite zusammen bauen String Seite = ""; Seite += Seitenkopf; Seite += "<h1 align=\"left\">Raumtemperatur</h1>"; Seite += "<div align=\"left\";>"; Seite += "<div class=\"farbigeBox\">"; Seite += "Bad: "; Seite += Temperatur + " °C"; Seite += "<br>"; Seite += "Wohnzimmer:"; Seite += String(Messung[HOST_1]); Seite += "<br>"; Seite += "Esszimmer:"; Seite += String(Messung[HOST_2]); Seite += "</div>"; // Button aktualisieren Seite += "<hr><input style=\"font-size:16pt; font-weight:bold;"; Seite += "background-color:#55A96B;"; Seite += "display:block; cursor:pointer;\"type=\"button\""; // IP für den Button aktualisieren (location.href) // muss mit dem Wert für IPAdress übereinstimmen (. statt ,) Seite += " onClick =\"location.href='http://192.168.1.6'\" value=\"aktualisieren\">"; Seite += "<hr>"; // Seite übermitteln Server.send(200, "text/html", Seite); } void DatenHolen(int hostNo) { WiFiClient client; String host = ""; // Namen des Host zuweisen (host_1) if(hostNo == HOST_1) { host = host_1; // wenn der Host nicht verbunden werden kann // zurück zur aufrufenden Funktion if (!client.connect(host_1, 80)) return; } // Namen des Host zuweisen (host_2) if(hostNo == HOST_2) { host = host_2; // wenn der Host nicht verbunden werden kann // zurück zur aufgerufenen Funktion if (!client.connect(host_2, 80)) return; } /* GET-Anfrage senden /Messung -> Adresse (URL) für die zu übermittelnden Werte wird von den Klienten festgelegt host -> der jeweilige Klient HTTP/1.1 -> Abfrageprotokoll \r\n -> return mit anschließender neuer Zeile */ client.print(String("GET ") + "/Messung" + " HTTP/1.1\r\n" + host + "\r\n"); unsigned long LetzteZeit = millis(); // Wartezeit zwischen den Abfragen der Klienten while (!client.available() && ((millis() - LetzteZeit) < 5000)) { delay(1); } // der Klient ist verfügbar while (client.available()) { // den mit GET erhaltenen String bis zum return (\r) lesen String Daten = client.readStringUntil('\r'); // wenn Daten vorhanden sind if(Daten != "") { Messung[hostNo] = Daten; Serial.println(Daten); } } } |
ESP als Host
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#ifdef ESP8266 #include "ESP8266WebServer.h" ESP8266WebServer Server(80); #else #include "WiFi.h" #include "WebServer.h" WebServer Server(80); #endif #include "DHT.h" // Pin des DHT-Sensors int SENSOR_DHT = 19; // Sensortyp festlegen // DHT22 oder DHT11 #define SensorTyp DHT22 // Sensor DHT einen Namen zuweisen DHT dht(SENSOR_DHT, SensorTyp); // Router als AP char Router[] = "Router_SSID"; char Passwort[] = "xxxxxxxx"; // IP des Klienten Router als AP IPAddress ip(192, 168, 1, 8); // IP-Adresse des Routers IPAddress gateway(192, 168, 1, 1); IPAddress subnet(255, 255, 255, 0); void setup() { WiFi.mode(WIFI_STA); WiFi.config(ip, gateway, subnet); WiFi.begin(Router, Passwort); Server.on("/Messung", SeiteBauen); Server.begin(); dht.begin(); } void loop() { // auf Anfragen warten Server.handleClient(); } void SeiteBauen() { // Messwerte ermitteln // . durch , ersetzen String Temperatur = String(dht.readTemperature()); Temperatur.replace(".", ","); // Seite zusammen bauen String Seite = Temperatur + " °C"; // Seite übermitteln Server.send(200, "text/html", Seite); } |
Quellen
- Tablet/Smartphone von Pixaline
- Router/Laptop: openclipart.org
- ESP32 von fritzing
- Beitrag von Wolfgang Ewald zu vernetzten Mikrocontrollern
- Espressif WiFi-API
Letzte Aktualisierung:

