WLAN mit ESP8266 und ESP32

Über den Beitrag

Das Thema WLAN bzw. Wi-Fi hatte ich zwar schon häufig, aber eher beiläufig behandelt, beispielsweise in meinen Beiträgen über den ESP32, den ESP8266, die Wemos Boards, IFTTT und einige mehr. In diesem Beitrag möchte ich nun tiefer in dieses spannende Thema einsteigen. Im Einzelnen behandele ich die folgenden Themen:

Ich habe versucht, das Thema detailliert und Schritt für Schritt aufzubereiten, um auch weniger Erfahrene „abzuholen“. Wer sich schon auskennt, kann sicherlich das eine oder andere überspringen.

Einführung / Grundbegriffe

Bevor es richtig losgeht, möchte ich zum besseren Verständnis ein paar Begriffe erklären. Man möge mir nachsehen, dass ich die Dinge teilweise vereinfacht darstelle.

Wi-Fi vs WLAN

Wi-Fi (im Englischen: WiFi ohne Bindestrich) bezeichnet sowohl das Firmenkonsortium Wi-Fi Alliance, das WLAN-Geräte zertifiziert, als auch die zugehörigen Markenbegriffe Wi-Fi 4, 5 und 6 (Quelle: Wikipedia). Die Abkürzung Wi-Fi steht für „Wireless Fidelity“. WLAN hingegen ist die Abkürzung für Wireless Local Area Network, also ein lokales, kabelloses Netzwerk. In nicht-deutschsprachigen Ländern wird Wi-Fi oft als Synonym für WLAN verwendet. 

HTTP

Die Grundlage für die Kommunikation im World Wide Web ist HTTP = Hypertext Transfer Protocol. Dieses Protokoll legt fest, wie die im WWW vernetzten Geräte miteinander sprechen. Damit ist es auch die Grundlage für die hier besprochene Kommunikation per WLAN.

Client und Server

Die Kommunikation per HTTP erfolgt nach dem Client-Server Prinzip. Vereinfacht ausgedrückt: Der Client fragt an, der Server antwortet. Das ist vergleichbar mit dem Master-Slave Prinzip, das ihr von I2C und SPI her kennt.

Host

„Ein Host kann in der IT im Grunde jede Ressource sein, die eine andere Ressource als Gast bei sich aufnehmen beziehungsweise die mit ihr verbundenen Clients mit bestimmten IT-Diensten versorgen kann“ (Quelle: Frings Informatic). Jeder Server ist somit ein Host, aber nicht jeder Host ein Server.

HTML und CSS

HTML ist die Abkürzung für „Hypertext Markup Language“. Es ist die textbasierte, universelle Sprache des WWW. CSS steht für „Cascading Style Sheets“ und baut auf HTML auf. CSS bringt Struktur und objektorientiertes Arbeiten in HTML. Man erstellt Vorlagen (Klassen), die man immer wieder verwenden kann. Die Grundlagen von HTML und CSS sind schnell erlernbar.

IP und Router

Die IP ist die eindeutige Adresse eines Gerätes innerhalb eines Computernetzwerkes nach dem Internetprotokoll. Nach dem IPv4 Standard besteht die IP aus 4 Bytes, die jeweils mit einem Punkt voneinander getrennt sind. Jedes Gerät, das direkt mit dem WWW verbunden ist, hat eine individuelle IP, so auch euer Router. „Hinter“ dem Router liegt euer Heimnetzwerk mit eigenen IPs. Diese sind meist nach dem Schema 192.168.x.y aufgebaut. Ein Router ist eine Schnittstelle zwischen zwei Netzwerken.

Port

Ports sind zwei Byte große Erweiterungen der Netzwerkadressen, welche die übertragenen Daten bestimmten Anwendungen zuordnen. So kann unterschieden werden, ob ein Datenpaket beispielsweise für das Mailprogramm oder den Browser (typischerweise 80) bestimmt ist. Der Port wird der IP angehängt, getrennt durch einen Doppelpunkt. Also z.B.: 87.184.193.186:80.

Subnetzmaske

Euer Router vergibt in der Regel IPs, die sich nur im letzten Byte unterscheiden. In meinem Heimnetzwerk lauten die Adressen beispielsweise 192.168.178.x. Wenn eine Adresse von diesem Schema abweicht, dann weiß der Router, dass sie außerhalb des Heimnetzwerkes liegt. Das wird mit der Subnetzmaske ausgedrückt. Sie ist für mein Heimnetzwerk 255.255.255.0. In binärer Schreibweise wird die Subnetzmaske von links nach rechts mit Einsen aufgefüllt. Dieser Bereich ist fest vergeben. Nur der Teil mit den Nullen kann für die Vergabe von Subnetzadressen frei genutzt werden.

Gateway

Ein Gateway ist ein Gerät, das zwei Netzwerke verbindet. In meinem Heimnetzwerk ist das der Router. Seine IP innerhalb meines Heimnetzwerkes ist 192.168.178.1.

DHCP

DHCP ist die Abkürzung für Dynamic Host Configuration Protocol. Auf eurem Router läuft ein DHCP Server, der dafür sorgt, dass ein jedes Gerät in eurem Netztwerk (Computer, Smartphone, Laptop, IP Kamera, usw.) automatisch eine IP zugewiesen bekommt.

Einrichten eines Webservers

Ich gehe davon aus, dass ihr euer WLAN fähiges Board schon in die Arduino IDE integriert habt. Es gibt dafür so viele Anleitungen, dass ich mir das in diesem Beitrag spare.

Wir beginnen ganz einfach mit der Einrichtung eines Webservers im Heimnetz. Ich zeige das hier am Beispiel eines ESP8266 (ESP8266-ESP01 oder Wemos D1 Mini). Für ein ESP32 Board müsst ihr nur zwei Zeilen ändern (siehe Kommentare).

#include <ESP8266WebServer.h> // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32
#define PORT 80

const char* ssid = "Your SSID";
const char* pass = "Your Password";

ESP8266WebServer server(PORT); // WebServer server(PORT); for ESP32
 
void setup(){
  Serial.begin(115200); 
  Serial.print("Connecting to: ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
   
  while(WiFi.status() != WL_CONNECTED){
    delay(500); 
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP-Address of ESP8266 module: ");
  Serial.println(WiFi.localIP());
  
  server.begin();
}
  
void loop(){
}

Erläuterung des Sketches:

  • Ihr bindet ESP8266WebServer.h ein.
  • Der Port für den Webserver ist 80.
  • „ssid“ (Service Set Indentifier) und „pass“ sind die Zugangsdaten eures Heimnetzwerkes.
  • ESP8266WebServer server(PORT); erzeugt ein Webserver Objekt.
  • WiFi.begin(ssid, pass) startet die WLAN-Verbindung.
  • Den Status eurer Verbindung erfahrt ihr über WiFi.status().
  • WiFi.localIP() liefert die IP, die der DHCP Server eures Routers für den ESP8266 vergeben hat.
  • server.begin() startet den WebServer, der hier aber noch absolut gar nichts tut.

Und so sieht das dann im seriellen Monitor aus. Mein Router hat dem ESP8266 die IP 192.168.178.47 gegeben:

Ausgabe von webserver_basic.ino
Ausgabe von webserver_basic.ino

IP selber festlegen

Ihr könnt mit WiFi.config() auch selbst bestimmen, welche IP der ESP8266 erhalten soll – vorausgesetzt, sie ist noch nicht vergeben. Dazu ergänzt ihr den Sketch folgendermaßen:

#include <ESP8266WebServer.h>  // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32
#define PORT 80

const char* ssid = "Your SSID";
const char* pass = "Your Password";

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(PORT); // WebServer server(PORT) for ESP32
 
void setup(){
  Serial.begin(115200); 
  Serial.print("Connecting to: ");
  Serial.println(ssid);
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, pass);
   
  while(WiFi.status() != WL_CONNECTED){
    delay(500); 
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP-Address of ESP8266 module: ");
  Serial.println(WiFi.localIP());
  
  server.begin();
}
  
void loop(){
}
webserver_basic_choose_IP.ino
Ausgabe von webserver_basic_choose_IP.ino

In den meisten Routern ist es möglich, Geräten eine feste IP zu geben. So „legt ihr euer Handtuch darauf“ und verhindert, dass die IP anderweitig vergeben wird.

Steuern eines Mikrocontrollers per WLAN und Browser

Im Folgenden möchte ich zeigen, wie ihr euer ESP8266- oder ESP32-Board per Browser vom PC, Laptop, Smartphone usw. steuert. Die konkrete Aufgabe ist die Schaltung von drei LEDs und das Auslesen eines Messwertes. Viele Wege führen nach Rom, so auch hier. Ich stelle zwei davon vor, die „server.on()-“ und die „client-Methode“.

Bis auf Weiteres werden die Beispiele im Heimnetz realisiert, d.h. die Kommunikation läuft über den Router:

MCU Board per WLAN über den Browser steuern
Den Mikrocontroller per Browser über WLAN steuern

Die Sketche sind für ein Wemos Board geschrieben. Bei Verwendung anderer Boards müsst ihr sie hinsichtlich der Pins noch anpassen. Wenn weitere Änderungen für ESP32 Boards notwendig sind, dann findet Ihr entsprechende Kommentare.

Die server.on()-Methode

Der Begriff „server.on()-Methode“ ist kein allgemein üblicher Begriff, zumal ihr euer Serverobjekt anstelle „server“ genauso gut „Pflaumenkuchen“ nennen könntet. Gleiches gilt für die „client-Methode“. Ich musste einfach nur Bezeichnungen festlegen, um die Methoden zu unterscheiden und etwas Besseres fiel mir nicht ein.

Eine LED per Browser schalten

Wir fangen erst einmal einfach an und schalten nur eine LED.  Verbindet die LED mit einem Pin eures Boards. Nehmt den folgenden Sketch und ladet ihn auf euer Board. Ggf. müsst ihr ihn hinsichtlich der IP und des Pins noch anpassen. Hier zunächst der Sketch:

#include <ESP8266WebServer.h>  // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32
#define LEDPIN D6  // choose an appropriate pin

const char* ssid = "Your SSID";
const char* pass = "Your Password";

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80); // WebServer server(80); for ESP32
 
String led1= "<a href=\"/led_on\">LED On</a>";
String led0= "<a href=\"/led_off\">LED Off</a>";

void setup(){
  pinMode(LEDPIN, OUTPUT);
  digitalWrite(LEDPIN, LOW);
  Serial.begin(115200); 
  Serial.println("Minimal Program to switch one LED");
  Serial.print("Connecting to: ");
  Serial.println(ssid);
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, pass);
  
  while(WiFi.status() != WL_CONNECTED){
    delay(500); 
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP-Address of ESP8266 module: ");
  Serial.println(WiFi.localIP());
  
  server.on("/",handleRoot);
  server.on("/led_on", ledon);
  server.on("/led_off", ledoff);
  server.begin();
}
  
void loop(){
  server.handleClient(); 
}

void handleRoot() {
  String message="<h1>Control your ESP8266 by your Browser</h1>";
  message += "Minimal version, just one LED</BR></BR>";
  message += led1;
  server.send(200, "text/html", message);
}

void ledon(){
  digitalWrite(LEDPIN, HIGH);
  server.send(200, "text/html", led0);
}

void ledoff(){
  digitalWrite(LEDPIN, LOW);
  server.send(200, "text/html", led1);
}

Nun ruft ihr den Browser eines Gerätes auf, das mit eurem Heimnetzwerk verbunden ist. Tippt dort die IP eures Boards ein, also in meinem Fall 192.168.178.110. Dann sollte es ungefähr so aussehen:

Steuern per WLAN: Bildschirmausgabe von ESP8266_ESP32_one_LED.ino
Bildschirmausgabe von ESP8266_ESP32_one_LED.ino

Wenn ihr nun auf den Link „LED On“ klickt, wird die LED angeschaltet und auf dem Bildschirm erscheint der Link „LED Off“. Außerdem seht ihr, dass sich die Adresszeile des Browsers ändert. In meinem Fall: 192.168.178.110/led_on. Jetzt könnt ihr die LED wieder ausschalten.

Steuern per WLAN: Bildschirmausgabe von ESP8266_ESP32_one_LED.ino, Pfad: /led_on
Bildschirmausgabe von ESP8266_ESP32_one_LED.ino, Pfad: /led_on

Erklärungen zum Sketch

Ich fange mal in der Mitte an, nämlich in loop(). Dort findet ihr lediglich die Funktion server.handleClient(). Sie fragt ab, ob Anfragen eines Clients vorliegen.

Der Aufruf von 192.168.178.110 führt in den Hauptpfad „/“. Genau genommen sendet der Browser dazu einen sogenannten Get-Request. Darauf komme ich später zurück.

Über die Funktion server.on("/", handleRoot) wurde zuvor festgelegt, dass bei Aufruf von „/“ die Funktion handleRoot() ausgeführt wird. Dort wird ein String („message“) definiert, der mittels server.send(200, „text/html“, message) an den Browser zurückgesendet wird. Die „200“ ist ein Fehlercode, der dem Browser sagt, dass alles OK ist. Ihr kennt vielleicht den Fehlercode „404 – page not found“.

„text/html“ besagt, dass Text und HTML Code gesendet wird. Alles in eckigen Klammern ist HTML. In den meisten Fällen sind HTML Anweisungen für einen bestimmten Bereich gültig. <Anweisung> ist der Beginn des Bereiches, </Anweisung> ist das Ende. <h1> leitet die größte Überschrift ein, </BR> bewirkt einen Zeilenumbruch und mit <a> beginnt ein Link. href ist das Linkziel. Wenn ihr mehr über HTML wissen wollt, findet ihr hier einen sehr kompakten Schnelleinstieg.

Bei einem Klick auf den Link „LED On“, wird die Seite 192.168.178.110/led_on aufgerufen. Durch server.on("/led_on", ledon) ist festgelegt, dass nun die Funktion ledon() aufgerufen wird. Dort wiederum wird zum einen die LED angeschaltet, zum anderen wird der Link zur Seite 192.168.178.110/led_off an den Browser gesendet und dort dargestellt.

Ihr könnt die LED natürlich auch anschalten, indem ihr die IP mit Pfad direkt in die Adresszeile des Browsers eingebt, also: 192.168.178.110/led_on.

Ich hoffe, dass damit das Prinzip dieser Methode klar geworden ist.

Drei LEDS schalten und einen Messwert auslesen

Jetzt steigern wir uns, indem wir drei LEDs steuern und einen Messwert auf die Ferne auslesen. Als Beispiel für einen Messwert lese ich die Spannung an einem analogen Eingang.

Den folgenden Sketch müsst ihr ggf. wieder etwas an euer Board anpassen.

#include <ESP8266WebServer.h> // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32

int led[3] = {D5,D6,D7}; // choose suitable pins
bool led_status[3] = {false};
const char* ssid = "Your SSID";
const char* pass = "Your Password";

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);  // WebServer server(80); for ESP32
 
String headAndTitle = "<head><meta http-equiv=\"refresh\" content=\"5\"></head>"
                      "<h1>Control your ESP8266 by Browser</h1>"
                      "Switch three LEDs and get a measured value, minimal version</BR></BR>";

String led0_1= "<a href=\"/led0_on\">LED0 On</a>";
String led0_0= "<a href=\"/led0_off\">LED0 Off</a>";
String led1_1= "</BR><a href=\"/led1_on\">LED1 On</a>";
String led1_0= "</BR><a href=\"/led1_off\">LED1 Off</a>";
String led2_1= "</BR><a href=\"/led2_on\">LED2 On</a>";
String led2_0= "</BR><a href=\"/led2_off\">LED2 Off</a>";


void setup(){
  pinMode(led[0], OUTPUT);
  digitalWrite(led[0], LOW);
  pinMode(led[1], OUTPUT);
  digitalWrite(led[1], LOW);
  pinMode(led[2], OUTPUT);
  digitalWrite(led[2], LOW);
  
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, pass);
   
  server.on("/",handleRoot);
  server.on("/led0_on", led0on);
  server.on("/led0_off", led0off);
  server.on("/led1_on", led1on);
  server.on("/led1_off", led1off);
  server.on("/led2_on", led2on);
  server.on("/led2_off", led2off);
  server.begin();
}
  
void loop(){
  server.handleClient(); 
}

void handleRoot() {
  led0off();
}

void led0on(){
  led_status[0] = true;
  switchLEDAndSend(0,1);
}

void led0off(){
  led_status[0] = false;
  switchLEDAndSend(0,0);
}

void led1on(){
  led_status[1] = true;
  switchLEDAndSend(1,1);
}

void led1off(){
  led_status[1] = false;
  switchLEDAndSend(1,0);
}

void led2on(){
  led_status[2] = true;
  switchLEDAndSend(2,1);
}

void led2off(){
  led_status[2] = false;
  switchLEDAndSend(2,0);
}

void switchLEDAndSend(int num, bool state){
  String message = "";
  message += headAndTitle;
  
  digitalWrite(led[num], state);
  (led_status[0]==true)?(message += led0_0):(message += led0_1); // short version for if..then..else
  (led_status[1]==true)?(message += led1_0):(message += led1_1);
  (led_status[2]==true)?(message += led2_0):(message += led2_1);
  
  float measuredValue = analogRead(A0)/1024.0 * 3.3; // adjust to your board
  message += "</BR></BR>Voltage [V]: ";
  message += String(measuredValue, 2); // float to String, two decimal places
  server.send(200, "text/html", message); 
}

 

Und so sieht das Ergebnis im Browser aus:

Steuern per WLAN - Bildschirmausgabe von ESP8266_ESP32_three_LEDs.ino
Bildschirmausgabe von ESP8266_ESP32_three_LEDs.ino

Da wir hier drei LEDs an- und ausschalten, benötigen wir dafür sechs server.on() Funktionen plus eine weitere für die Hauptseite. Und wir müssen uns den Status der LEDs „merken“. Dafür habe ich das Array „led_status“ definiert. Ansonsten macht der Sketch hinsichtlich der LEDs nichts Neues, er ist nur länger.

Neu ist, dass wir hier noch einen Messwert auslesen, in einen String umwandeln und an den Browser senden. Nun möchtet ihr wahrscheinlich die Seite nicht immer wieder neu aufrufen, um Änderungen des Messwertes zu verfolgen. Für ein regelmäßiges Update sorgt deshalb in Zeile 14: <head><meta http-equiv=\"refresh\" content=\"5\"></head>. Dadurch wird die Webseite alle 5 Sekunden neu aufgerufen.

Hübscher mit HTML und CSS

Unsere Webseite ist optisch noch nicht besonders ansprechend. Tauscht einmal die Zeilen 18-23 gegen die folgenden Zeilen aus:

String led0_1= "<a href=\"/led0_on\"><button style=\"background: green; color: white; font-size: x-large; \">LED0 On</button></a>";
String led0_0= "<a href=\"/led0_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED0 Off</button></a>";
String led1_1= "</BR></BR><a href=\"/led1_on\"><button style=\"background: green; color: white; font-size: x-large;\">LED1 On</button></a>";
String led1_0= "</BR></BR><a href=\"/led1_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED1 Off</button></a>";
String led2_1= "</BR></BR><a href=\"/led2_on\"><button style=\"background: green; color: white; font-size: x-large; \">LED2 On</button></a>";
String led2_0= "</BR></BR><a href=\"/led2_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED2 Off</button></a>";

Das Ergebnis ist schon ein wenig netter:

Bildschirmausgabe, verbessert
Bildschirmausgabe, verbessert

Oder hier nochmal der ganze Sketch mit CSS Elementen:

#include <ESP8266WebServer.h> // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32

int led[3] = {D5,D6,D7};
bool led_status[3] = {false};
const char* ssid = "Your SSID";
const char* pass = "Your Password";

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);  // WebServer server(80); for ESP32
 
String headAndTitle = "<head><style>"
                        ".button {"
                          "border: none;"
                          "color: white;"
                          "width: 350px;"
                          "padding: 20px;"
                          "text-align: center;"
                          "margin: 20px 200px;"
                        "}"
                        ".greenButton {background-color: green; font-size: 64px;}"
                        ".greenButton:hover {background-color: darkgreen; font-size: 64px;}"
                        ".redButton {background-color: red; font-size: 64px;}"
                        ".redButton:hover {background-color: darkred; font-size: 64px;}"
                        ".blueBox {"
                          "background-color: blue;"
                          "color: white;"
                          "width: 350px;" 
                          "padding: 20px;"
                          "text-align: center;"
                          "font-size: 50px;"
                          "font-family: arial;"
                          "margin: 20px 200px;"
                        "}"
                      "</style>"
                      "</head><meta http-equiv=\"refresh\" content=\"5\"></head>"
                      "</BR></BR><h1 align=\"center\">Control your ESP8266 by Browser</h1></div>"
                      "<div align=\"center\">Control three LEDs and get measured value, nicer with CSS</BR></BR></div>";

String led0_1= "<a href=\"/led0_on\"><button class=\"button greenButton\">LED0 On</button></a>";
String led0_0= "<a href=\"/led0_off\"><button class=\"button redButton\">LED0 Off</button></a>";
String led1_1= "</BR><a href=\"/led1_on\"><button class=\"button greenButton\">LED1 On</button></a>";
String led1_0= "</BR><a href=\"/led1_off\"><button class=\"button redButton\">LED1 Off</button></a>";
String led2_1= "</BR><a href=\"/led2_on\"><button class=\"button greenButton\">LED2 On</button></a>";
String led2_0= "</BR><a href=\"/led2_off\"><button class=\"button redButton\">LED2 Off</button></a>";

void setup(){
  pinMode(led[0], OUTPUT);
  digitalWrite(led[0], LOW);
  pinMode(led[1], OUTPUT);
  digitalWrite(led[1], LOW);
  pinMode(led[2], OUTPUT);
  digitalWrite(led[2], LOW);
  
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, pass);

  server.on("/",handleRoot);
  server.on("/led0_on", led0on);
  server.on("/led0_off", led0off);
  server.on("/led1_on", led1on);
  server.on("/led1_off", led1off);
  server.on("/led2_on", led2on);
  server.on("/led2_off", led2off);
  server.begin();
}
  
void loop(){
  server.handleClient(); 
}

void handleRoot() {
  led0off();
}

void led0on(){
  led_status[0] = true;
  switchLEDAndSend(0,1);
}

void led0off(){
  led_status[0] = false;
  switchLEDAndSend(0,0);
}

void led1on(){
  led_status[1] = true;
  switchLEDAndSend(1,1);
}

void led1off(){
  led_status[1] = false;
  switchLEDAndSend(1,0);
}

void led2on(){
  led_status[2] = true;
  switchLEDAndSend(2,1);
}

void led2off(){
  led_status[2] = false;
  switchLEDAndSend(2,0);
}

void switchLEDAndSend(int num, bool state){
  String message = "";
  message += headAndTitle;
  message += "<div align=\"center\";>";
  
  digitalWrite(led[num], state);
  (led_status[0]==true)?(message += led0_0):(message += led0_1);
  (led_status[1]==true)?(message += led1_0):(message += led1_1);
  (led_status[2]==true)?(message += led2_0):(message += led2_1);
  
  float measuredValue = analogRead(A0)/1024.0 * 3.3;
  message += "</BR><div class=\"blueBox\">";
  message += "Voltage [V]: </BR>";
  message += String(measuredValue, 2);
  message += "</div>";
  message += "</div>";
  server.send(200, "text/html", message); 
}

 

Die Darstellung ist etwas großzügiger und deshalb auch gut auf dem Smartphone nutzbar:

Drei LEDs per WLAN steuern: ESP8266_ESP32_three_LEDs_nice.ino auf dem PC Bildschirm
ESP8266_ESP32_three_LEDs_nice.ino auf dem PC Bildschirm….
Drei LEDs per WLAN steuern: ESP8266_ESP32_three_LEDs_nice.ino auf dem Smartphone
…und auf dem Smartphone

Tiefer in CSS einzusteigen, würde den Beitrag sprengen. Eine kompakte Einführung findet ihr hier.

Die client-Methode

Eine Alternative zum Auswerten der Clientanfrage über server.on() ist die client-Methode. Wie schon erwähnt, ist das keine offizielle Bezeichnung. Hier wird ein Client-Objekt geschaffen, das über Read- und Printfunktionen Client-Requests liest oder Nachrichten an den Client sendet. Das ist ähnlich wie bei einem Serial-Objekt. 

#include "ESP8266WebServer.h" // use "WebServer.h" for ESP32
// #include <WiFi.h> // for ESP32
 
int led[3] = {D5,D6,D7};  // choose suitable pins
int analogPin = A0;
bool led_status[3] = {false};
const char* ssid = "Your SSID";
const char* password = "Your Password";

String headAndTitle = "<head><meta http-equiv=\"refresh\" content=\"5\"></head>"
                      "<h1>Control your ESP8266 by Browser</h1>"
                      "Control three LEDs and get measured value, client method</BR></BR>";

String led0_1= "<a href=\"/led0_on\"><button style=\"background: green; color: white; font-size: x-large; \">LED0 On</button></a>";
String led0_0= "<a href=\"/led0_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED0 Off</button></a>";
String led1_1= "</BR></BR><a href=\"/led1_on\"><button style=\"background: green; color: white; font-size: x-large;\">LED1 On</button></a>";
String led1_0= "</BR></BR><a href=\"/led1_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED1 Off</button></a>";
String led2_1= "</BR></BR><a href=\"/led2_on\"><button style=\"background: green; color: white; font-size: x-large; \">LED2 On</button></a>";
String led2_0= "</BR></BR><a href=\"/led2_off\"><button style=\"background: red; color: white; font-size: x-large; \">LED2 Off</button></a>";

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);
 
WiFiServer server(80);
WiFiClient client;
 
void setup() {
  pinMode(led[0], OUTPUT);
  digitalWrite(led[0], LOW);
  pinMode(led[1], OUTPUT);
  digitalWrite(led[1], LOW);
  pinMode(led[2], OUTPUT);
  digitalWrite(led[2], LOW);
  
  Serial.begin(115200);
  while(!Serial) {}
   
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
   
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, password);
   
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP()); 
  server.begin();
}
 
void loop(){
  client = server.available();
  if(client){
    Serial.println("New client");
    boolean currentLineIsBlank = true;
    String clientMessage = "";
    
    while(client.connected()){     
      if(client.available()){
        char c = client.read();
        // Serial.write(c); //uncomment to print the request
        if(clientMessage.length()<50){
          clientMessage += c;
        }
        if(c == '\n' && currentLineIsBlank){
          evaluateClientMessage(clientMessage);
          break;
        }
        if(c == '\n'){
          currentLineIsBlank = true;
        } 
        else if(c != '\r'){
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client disconnected");
  }
}

void evaluateClientMessage(String &msg){
   
  if(msg.indexOf("led0_off") > 0){
    led_status[0] = false;
  }
  else if(msg.indexOf("led0_on") > 0){
    led_status[0] = true;
  }
  else if(msg.indexOf("led1_off") > 0){
    led_status[1] = false;
  }
  else if(msg.indexOf("led1_on") > 0){
    led_status[1] = true;
  }
  else if(msg.indexOf("led2_off") > 0){
    led_status[2] = false;
  }
  else if(msg.indexOf("led2_on") > 0){
    led_status[2] = true;
  }

  for(int i=0; i<3; i++){
    digitalWrite(led[i], led_status[i]);
  }

  String ledString = "";
  (led_status[0]==true)?(ledString += led0_0):(ledString += led0_1);
  (led_status[1]==true)?(ledString += led1_0):(ledString += led1_1);
  (led_status[2]==true)?(ledString += led2_0):(ledString += led2_1);

  float measuredValue = analogRead(analogPin)/1024.0 * 3.3;
    
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("Connection: close"); 
  client.println(); // this line is not redundant!
  client.println(headAndTitle);
  client.println(ledString);
  client.println("</BR></BR></BR><span style=\"font-family: Arial; background: blue; color: white; font-size: x-large;\">&nbsp; Voltage [V]: ");
  client.println(String(measuredValue,2));
  client.println("&nbsp;</span>");
}

Ich gehe nur auf die wesentlichen Teile des Sketches ein. In der loop-Schleife wird fortlaufend geprüft, ob der Client einen Get-Request sendet. Wenn das der Fall ist, wird der Get-Request zeichenweise mit client.read() ausgelesen und zu dem String „clientMessage“ zusammengesetzt. Der Get-Request endet mit einer Leerzeile (if(c == '\n' && currentLineIsBlank){...}). ‚\n‘ ist die Escape-Sequenz für den Zeilenvorschub (new line), ‚\r‘ ist die Escape-Sequenz für den Wagenrücklauf (carriage return). Die entscheidende Information befindet sich im ersten Teil des Requests, deswegen nehmen wir nur die ersten 50 Zeichen auf. 

Wenn ihr die Zeile 66 entkommentiert, könnt ihr den ganzen Request auf dem seriellen Monitor sehen:

Get-Request des Clients (hier: "/led2_off")
Get-Request des Clients (hier: „/led2_off“)

Nun, da wir den relevanten Teil des Get-Requests in dem String „clientMessage“ gespeichert haben, durchsuchen wir ihn nach den Schlüsselwörtern led0_on, led0_off, led1_on, usw. Dafür gibt es die praktische Funktion indexOf(searchstring), die die Position des gesuchten Teilstrings zurückliefert. Wenn der gesuchte Teilstring nicht vorhanden ist, dann liefert indexOf() den Wert -1 zurück. 

Der Rest ist den vorherigen Sketchen ähnlich. Nur wird die Information nicht mit server.send(), sondern mit client.println() an den Client gesendet. Das Ergebnis ist dasselbe.

Station (STA) und Access point (AP) WLAN Modi

Bei den bisherigen Beispielen hat sich das Mikrocontroller-Board in ein vorhandenes WLAN Netzwerk eingeklinkt. Das ist der sogenannte STA („Station“) Modus. Mit geringen Änderungen kann das Mikrocontroller-Board selbst zum Access Point (= Zugangspunkt oder Hot Spot) gemacht werden. Dies ist der AP Modus, mit dem ihr euch von eurem Router unabhägig macht. 

ESP8266 im WLAN Modus AP
Der ESP8266 im WLAN Modus AP

Die folgenden Zeilen machen den Unterschied:

IPAddress ip(192,168,4,1);
IPAddress gateway(192,168,4,1); 
IPAddress subnet(255,255,255,0);
....
....
WiFi.softAPConfig(ip, gateway, subnet);
Wifi.softAP(ssid, pass);

Und hier der ganze Sketch:

#include <ESP8266WebServer.h>  // <WebServer.h> for ESP32  
// #include <WiFi.h> // for ESP32

int led[3] = {D5,D6,D7};
bool led_status[3] = {false};
const char* ssid = "ESP8266_Server";  // choose a name
const char* pass = "blablablabla"; // must be >= 8 characters (at least for the ESP32)!

IPAddress ip(192,168,4,1); // should be 192.168.4.x
IPAddress gateway(192,168,4,1);  // should be 192.168.4.x
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);  // WebServer server(80); for ESP32
 
String headAndTitle = "<head><style>"
                        ".button {"
                          "border: none;"
                          "color: white;"
                          "width: 350px;"
                          "padding: 20px;"
                          "text-align: center;"
                          "margin: 20px 200px;"
                        "}"
                        ".greenButton {background-color: green; font-size: 64px;}"
                        ".redButton {background-color: red; font-size: 64px;}"
                        ".blueButton {background-color: blue; font-size: 50px;}"
                      "</style>"
                      "</head><meta http-equiv=\"refresh\" content=\"5\"></head>"
                      "</BR></BR><h1 align=\"center\">Control your ESP8266 by Browser</h1></div>"
                      "<div align=\"center\">Control three LEDs and get measured value, AP - ModeS</BR></BR></div>";

String led0_1= "<a href=\"/led0_on\"><button class=\"button greenButton\">LED0 On</button></a>";
String led0_0= "<a href=\"/led0_off\"><button class=\"button redButton\">LED0 Off</button></a>";
String led1_1= "</BR><a href=\"/led1_on\"><button class=\"button greenButton\">LED1 On</button></a>";
String led1_0= "</BR><a href=\"/led1_off\"><button class=\"button redButton\">LED1 Off</button></a>";
String led2_1= "</BR><a href=\"/led2_on\"><button class=\"button greenButton\">LED2 On</button></a>";
String led2_0= "</BR><a href=\"/led2_off\"><button class=\"button redButton\">LED2 Off</button></a>";

void setup(){
  pinMode(led[0], OUTPUT);
  digitalWrite(led[0], LOW);
  pinMode(led[1], OUTPUT);
  digitalWrite(led[1], LOW);
  pinMode(led[2], OUTPUT);
  digitalWrite(led[2], LOW);
  
  WiFi.softAPConfig(ip, gateway, subnet); 
  WiFi.softAP(ssid, pass);  
 
  delay(500); 

  server.on("/",handleRoot);
  server.on("/led0_on", led0on);
  server.on("/led0_off", led0off);
  server.on("/led1_on", led1on);
  server.on("/led1_off", led1off);
  server.on("/led2_on", led2on);
  server.on("/led2_off", led2off);
  server.begin();
}
  
void loop(){
  server.handleClient(); 
}

void handleRoot() {
  led0off();
}

void led0on(){
  led_status[0] = true;
  switchLEDAndSend(0,1);
}

void led0off(){
  led_status[0] = false;
  switchLEDAndSend(0,0);
}

void led1on(){
  led_status[1] = true;
  switchLEDAndSend(1,1);
}

void led1off(){
  led_status[1] = false;
  switchLEDAndSend(1,0);
}

void led2on(){
  led_status[2] = true;
  switchLEDAndSend(2,1);
}

void led2off(){
  led_status[2] = false;
  switchLEDAndSend(2,0);
}

void switchLEDAndSend(int num, bool state){
  String message = "";
  message += headAndTitle;
  message += "<div align=\"center\";>";
  
  digitalWrite(led[num], state);
  (led_status[0]==true)?(message += led0_0):(message += led0_1);
  (led_status[1]==true)?(message += led1_0):(message += led1_1);
  (led_status[2]==true)?(message += led2_0):(message += led2_1);
  
  float measuredValue = analogRead(A0)/1024.0 * 3.3; // adjust for your board
  message += "</BR><button class=\"button blueButton\">";
  message += "Voltage [V]: </BR>";
  message += String(measuredValue, 2);
  message += "</button>";
  message += "</div>";
  server.send(200, "text/html", message); 
}

Ihr müsst euch hier mit eurem PC/Laptop/Smartphone/Tablet in das WLAN Netzwerk der MCU einklinken und nicht in das Netzwerk eures Routers. An der Darstellung im Browser ändert sich nichts.

Mehrere Mikrocontroller per WLAN vernetzen

Mehrere Mikrocontroller (kurz: MCU für Microcontroller Unit) in einem WLAN Netzwerk anzumelden, ist natürlich auch kein Problem. In diesem Abschnitt geht es vielmehr darum, wie die teilnehmenden MCUs untereinander kommunizieren können.

Eine typische Anwendung wäre: Ihr habt in eurem Heim mehrere MCUs im Einsatz, die irgendetwas messen (Temperatur, Luftfeuchte, o. ä.). Dann möchtet ihr wahrscheinlich nicht jede Station einzeln abfragen, sondern die Werte auf einem Server sammeln und auf einer einzigen Website ausgeben.

Einstieg: Einen Get-Request an einen Server senden

Wir setzen das Vorhaben um, indem die „sammelnde“ MCU (Client) die Daten von den anderen MCUs über Get-Requests anfordert. Wie das vom Prinzip her funktioniert, zeige ich erst einmal mithilfe dieses einfachen Setups:

Wir fügen dem bisherigen Aufbau also einen weiteren Mikrocontroller als Client hinzu, der über den Router mit dem WLAN Netzwerk verbunden ist. Diese Client MCU fordert über einen Get-Request die Hauptseite „/“ des Servers an (so wie es der Browser des PCs auch tut, wenn er die Seite aufruft).

Auf der Server MCU läuft der Sketch ESP8266_ESP32_three_LEDs.ino. Hier der Sketch für den Client:

#include <ESP8266WiFi.h>  // use "WebServer.h" for ESP32
// #include <WiFi.h> // for ESP32
 
const char* ssid     = "Your SSID";
const char* password = "Your Password";
const char* host = "192.168.178.110";

IPAddress ip(192,168,178,111);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);
 
void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.config(ip, gateway, subnet); 
  WiFi.begin(ssid, password);
   
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println();
}
 
void loop() {
  Serial.print("connecting to ");
  Serial.println(host);
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  String url = "/";
  Serial.print("Requesting URL: ");
  Serial.println(url);
   
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long lasttime = millis();
  
  while (!client.available() && ((millis() - lasttime) < 3000)){
    delay(1);
  }  
  while (client.available()) {
    String line = client.readStringUntil('\r');
    Serial.println(line);
  }
  Serial.println();
  Serial.println("closing connection");
  delay(60000);
}

 

Die wesentlichen Punkte sind:

  • Die Client MCU klinkt sich mit der IP-Adresse 192.168.178.111 in das WLAN Netzwerk ein.
  • Der Client verbindet sich mit dem Server („host“):
    • client.connect(host, httpPort)
  • Dann sendet der Client einen Get-Request.
  • Er wartet bis zu drei Sekunden darauf, dass eine Antwort kommt:
    • while (!client.available() && ((millis() - lasttime) < 3000)){
    • Eine Wartezeit ist wichtig, da der Host unter Umständen gerade einen anderen Client (hier: der PC) bedient.
  • Die Antwort des Hosts wird zeilenweise ausgelesen und auf dem seriellen Monitor ausgegeben:
Ausgabe von get_request_to_another_mcu.ino

Jetzt könnten wir die Nachricht weiter auswerten und den analogen Messwert extrahieren. Das tun wir aber nicht, denn dieser Sketch sollte nur das Prinzip verdeutlichen.

Mehrere MCUs vernetzen mit MCU als Access Point

Die Aufgabenstellung:

  • Drei Mikrocontroller messen Spannungen an analogen Eingängen
  • Einer der Mikrocontroller dient als Access Point, die beiden anderen laufen im STA Modus
  • Die beiden Mikrocontroller im STA Modus senden ihre Messwerte an den AP Mikrocontroller, von wo aus sie im Browser eines PCs, Smartphones, Tablets, usw. ausgegeben werden können.
 MCU WLAN Netzwerk mit MCU als Access Point
MCU WLAN Netzwerk mit MCU als Access Point

Ich habe hier zur Illustration drei Wemos D1 Mini Boards gewählt. Ihr könnt aber genauso gut – HTTP sei Dank – eine Mischung verschiedener MCUs verwenden.

Damit ihr nicht durcheinanderkommt, auf welches Board ihr welchen Sketch ladet, empfehle ich, die Arduino IDE mehrfach zu öffnen („mehrere Instanzen erzeugen“). Dann kann man für jede Instanz einen eigenen seriellen Port auswählen. Ich jedenfalls finde das einfacher, als immer den Port innerhalb einer Instanz zu wechseln.

Server Sketch

Die Sketche für die Server (Hosts) können wir ganz einfach halten, da die MCU lediglich ihren Messwert übermitteln sollen.

#include <ESP8266WebServer.h>  // use <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32

const char* ssid = "ESP8266_Server";
const char* pass = "blablablabla";

IPAddress ip(192,168,4,2);  // ip(192,168,4,3); for second host
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80); // WebServer server(80); for ESP32
 
void setup(){
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, pass);
  
  server.on("/voltage",voltage); 
  server.begin();
}

void loop(){
  server.handleClient();
}

void voltage(){
  float measuredValue_1 = analogRead(A0)/1024.0 * 3.3;
  String message = String(measuredValue_1, 2);
  server.send(200, "text/html", message);
}

 

Sketch für den Access Point MCU (Client und Server)

Hier ist die Besonderheit, dass dieses Mitglied des Netzwerkes ein Client in Bezug auf die beiden Hosts und ein Server in Bezug auf den PC ist.

Der PC schickt alle 10 Sekunden einen Get-Request an die AP MCU, da ich das über „refresh“ so eingestellt habe. In „echten“ Projekten sollte man die Frequenz besser nicht so hoch wählen.

Alle 15 Sekunden schickt die AP MCU ihrerseits Get-Requests zu den Hosts, um die Messwerte einzusammeln. Auch das ist eine recht hohe Frequenz. Senkt sie auf das Maß ab, das ihr benötigt. Das spart Strom und vermeidet „Kollisionen“.

Über den Browser könnt ihr euch dann schließlich alle Messwerte anschauen. Oben rechts seht Ihr, wie die das Ergebnis auf meinem Smartphone ausschaut.

Und hier nun der Sketch:

#include <ESP8266WebServer.h> // use <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32
#define HOST_1 0
#define HOST_2 1

const char* ssid = "ESP8266_Server";
const char* pass = "blablablabla";

const char* host_1 = "192.168.4.2";
const char* host_2 = "192.168.4.3";

String voltage[2] = {"",""};
unsigned long requestPeriod = 15000;

IPAddress ip(192,168,4,1);
IPAddress gateway(192,168,4,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80); // WebServer server(80); for ESP32
 
String headAndTitle = "<head><style>"
                        ".blueBox {"
                          "background-color: blue;"
                          "color: white;"
                          "width: 350px;" 
                          "padding: 20px;"
                          "text-align: center;"
                          "font-size: 50px;"
                          "font-family: arial;"
                        "}"
                      "</style>"
                      "</head><meta http-equiv=\"refresh\" content=\"10\"></head>"
                      "</BR></BR><h1 align=\"center\">Get data from other ESP8266 modules</h1></div>"
                      "<div align=\"center\">AP Mode, get measured values from two hosts</BR></BR></div>";

void setup(){
  WiFi.softAPConfig(ip, gateway, subnet);
  WiFi.softAP(ssid, pass);
  
  
  server.on("/",handleRoot);
  server.begin();
}

void loop(){
  static unsigned long startTime = millis();
  server.handleClient();
  if ((millis() - startTime) > requestPeriod){
    requestESP8266(HOST_1);
    requestESP8266(HOST_2);
    startTime = millis();
  }
}

void handleRoot(){
  String message = "";
  message += headAndTitle;
  message += "<div align=\"center\";>";
  float measuredValue_1 = analogRead(A0)/1024.0 * 3.3;
  
  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_1 [V]: </BR>";
  message += String(measuredValue_1, 2);
  message += "</div>";

  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_2 [V]: </BR>";
  message += voltage[HOST_1];
  message += "</div>";
  
  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_3 [V]: </BR>";
  message += voltage[HOST_2];
  message += "</div></div>";
  server.send(200, "text/html", message); 
}

void requestESP8266(int hostNo){
  WiFiClient client;
  String host = "";
  if(hostNo == HOST_1){
    if (!client.connect(host_1, 80)) {
      host = host_1;
      return;
    }
  }
  if(hostNo == HOST_2){
    if (!client.connect(host_2, 80)) {
      host = host_2;
      return;
    }
  }
  String url = "/voltage";
    
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long lasttime = millis();
  while (!client.available() && ((millis() - lasttime) < 3000)){
    delay(1);
  }  
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if(line != ""){
      voltage[hostNo] = line;
    }
  }
}

 

Der Sketch enthält eigentlich nichts Neues. Ich hoffe, dass er halbwegs nachvollziehbar ist.

Mehrere MCUs vernetzen mit Router als Access Point

Jetzt modifizieren wir die letzte Version noch dahin gehend, dass der Router der Access Point ist. Außerdem soll auch die direkte Abfrage der beiden Host MCUs ein ansprechendes Bild im Browser erzeugen. Die MCU, die die Werte von den Hosts einsammelt, habe ich hier „Main“ genannt:

MCU WLAN Netzwerk mit Router als Access Point
MCU WLAN Netzwerk mit Router als Access Point

Sketch für die Host MCUs

#include <ESP8266WebServer.h>  // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32

const char* ssid = "Your SSID";
const char* pass = "Your Password";

IPAddress ip(192,168,178,111); // ip(192,168,178,112); for second host
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80); // WebServer server(80); for ESP32
 
String headAndTitle = "<head><style>"
                        ".blueButton {"
                          "border: none;"
                          "color: white;"
                          "width: 400px;"
                          "padding: 20px;"
                          "text-align: center;"
                          "margin: 20px 200px;"
                          "background-color: blue;"
                          "font-size: 50px;"
                        "}"
                      "</style>"
                      "</head><meta http-equiv=\"refresh\" content=\"15\"></head>"
                      "</BR></BR><h1 align=\"center\">ESP8266 Host 1</h1></div>";

void setup(){
  WiFi.begin(ssid, pass);
  WiFi.config(ip, gateway, subnet);
  
  server.on("/",handleRoot);
  server.on("/voltage",voltage); 
  server.begin();
}

void loop(){
  server.handleClient();
}

void handleRoot(){
  String message = "";
  message += headAndTitle;
  message += "<div align=\"center\";>";
  float measuredValue_1 = analogRead(A0)/1024.0 * 3.3;
  message += "</BR><button class=\"button blueButton\">";
  message += "Voltage_2 [V]: </BR>";
  message += String(measuredValue_1, 2);
  message += "</button>";
  message += "</div>";
  server.send(200, "text/html", message); 
}

void voltage(){
  float measuredValue_1 = analogRead(A0)/1024.0 * 3.3;
  String message = String(measuredValue_1, 2);
  server.send(200, "text/html", message);
}

 

Die Host MCUs stellen hier also zwei Seiten zur Verfügung. Bei Aufruf des Hauptpfades wird die „angehübschte“ Seite übermittelt, bei Aufruf von „/voltage“ wird einfach nur der blanke Messwert übergeben.

Sketch für die „main“ MCU

#include <ESP8266WebServer.h>  // <WebServer.h> for ESP32
// #include <WiFi.h> // for ESP32
#define HOST_1 0
#define HOST_2 1

const char* ssid = "Your SSID";
const char* pass = "Your Password";

const char* host_1 = "192.168.178.111";
const char* host_2 = "192.168.178.112";

String voltage[2] = {"",""};
unsigned long requestPeriod = 15000;

IPAddress ip(192,168,178,110);
IPAddress gateway(192,168,178,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);  // WebServer server(80); for ESP32
 
String headAndTitle = "<head><style>"
                        ".blueBox {"
                          "background-color: blue;"
                          "color: white;"
                          "width: 350px;" 
                          "padding: 20px;"
                          "text-align: center;"
                          "font-size: 50px;"
                          "font-family: arial;"
                        "}"
                      "</style>"
                      "</head><meta http-equiv=\"refresh\" content=\"10\"></head>"
                      "</BR></BR><h1 align=\"center\">Get data from other ESP8266 modules</h1></div>"
                      "<div align=\"center\">STA Mode, get measured values from two hosts</BR></BR></div>";

void setup(){
  Serial.begin(115200);
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, pass);
 
  server.on("/",handleRoot);
  server.begin();
}

void loop(){
  static unsigned long startTime = millis();
  server.handleClient();
  if ((millis() - startTime) > requestPeriod){
    requestESP8266(HOST_1);
    requestESP8266(HOST_2);
    startTime = millis();
  }
}

void handleRoot(){
  String message = "";
  message += headAndTitle;
  message += "<div align=\"center\";>";
  float measuredValue_1 = analogRead(A0)/1024.0 * 3.3;
  
  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_1 [V]: </BR>";
  message += String(measuredValue_1, 2);
  message += "</div>";

  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_2 [V]: </BR>";
  message += voltage[HOST_1];
  message += "</div>";
  
  message += "</BR><div class=\"blueBox\">";
  message += "Voltage_3 [V]: </BR>";
  message += voltage[HOST_2];
  message += "</div></div>";
  server.send(200, "text/html", message); 
}

void requestESP8266(int hostNo){
  WiFiClient client;
  String host = "";
  if(hostNo == HOST_1){
    if (!client.connect(host_1, 80)) {
      Serial.println("connection failed to host 2");
      host = host_1;
      return;
    }
  }
  if(hostNo == HOST_2){
    if (!client.connect(host_2, 80)) {
      Serial.println("connection failed to host 3");
      host = host_2;
      return;
    }
  }
  String url = "/voltage";
  Serial.print("Requesting URL: ");
  Serial.println(url);
   
  
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long lasttime = millis();
  while (!client.available() && ((millis() - lasttime) < 3000)){
    delay(1);
  }  
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if(line != ""){
      voltage[hostNo] = line;
    }
  }
  Serial.println();
  Serial.println("closing connection to ESP8266");
}

 

Nun könnt ihr euch die gesammelten Messwerte, den Hauptpfad der Hosts oder einfach nur den unformatierten Messwert eines Hosts anschauen. Ich habe hier einmal alle drei Varianten parallel aufgerufen:

MCU WLAN Netzwerk, links: "Main MCU", Mitte: Host (Hauptseite), rechts: Host ("/voltage")
MCU WLAN Netzwerk, links: „Main MCU“, Mitte: Host (Hauptseite), rechts: Host („/voltage“)

Danksagung

Auch für diesen Beitrag habe ich mich wieder fleißig bei den Bildern auf Pixabay bedient:

90 thoughts on “WLAN mit ESP8266 und ESP32

  1. Hallo Wolfgang,
    eine prinzipelle Frage zur maximalen Geschwindigkeit von Datenübertragungen. Was sollte z.B. bei Übertragung von Spg. und Strom mittels ESP32 überhaupt machbar sein? D.h. welche „Abtastrate“ wäre bei direkter Übertragung (geringer Abstand, keine Hindernisse, etc.) möglich?
    Falls bereits dazu ein Post besteht, reicht ein Hinweis/Link.
    Danke schon mal.

    1. Hallo Roland,

      ich kann dir die Frage so nicht beantworten. Die theoretische Datenrate per Wifi beträgt für die meisten ESP32 150 MBit/s. Allerdings hängt es nicht nur von Gegebenheiten, wie Abständen und Hindernissen ab, wieviel Date du tatsächlich überträgt, sondern auch wie du das machst, also z.B. per der hier vorgestellten Methoden, Bluetooth, MQTT, ESP-NOW usw. Alle Methoden haben einen unterschiedlichen „Overhead“, also Daten die ausgetauscht werden, um die Kommunikation überhaupt erst ermöglichen. Tut mir leid, mehr kann ich dir spontan nicht sagen.
      VG, Wolfgang

  2. Hallo Wolfgang,
    sehr interessante Webseite, vielen Dank.
    Der Webserver mit ESP32 über meinen Router klappt prima, auch mit selbst festgelegter IP-Adresse.
    Die Variante ohne Router über Access Point bekomme ich allerdings überhaupt nicht zum Laufen. Mit der Adresse 192.168.4.x (oder auch andere Endziffern) bekomme ich einfach keine Verbindung zu meinem Firefox auf Windows 10. Kann es sein, dass eine Einstellung in Firefox oder in der Windows Firewall die Verbindung verhindert? Oder hast du sonst eine Idee?
    Vielen Dank. Konrad

    1. Hallo Konrad,
      vielleicht liegt hier ein Missverständnis vor. Der ESP32, der als Access Point fungiert, ist dein Router. D.h. du verbindest deinen PC nicht mit dem WLAN deines Routers, sondern mit dem des ESP32. Gehe in die Liste der verfügbaren WLAN-Netzwerke. Dort sollte das ESP32 WLAN mit dem Namen auftauchen, den du ihm mit const char* ssid = „…“ gegeben hast. Wähle dieses Netzwerk aus und wenn du nach ein paar Sekunden verbunden bist, gehst du in den Browser deiner Wahl und tippst dort die IP-Adresse ein. Ich habe es erfolgreiche auf einem Windows 11 Laptop und Firefox probiert. Alternativ kannst du dein Smartphone verwenden.
      VG, Wolfgang

      1. Hallo Wolfgang,
        danke für die schnelle Antwort. Da war ich wohl ziemlich daneben. Habe mich eh schon gewundert, wozu man Name und Passwort braucht und wie die Verbindung zwischen ESP32 und Windows überhaupt zustande kommt …
        Nach deiner Anleitung klappt das wunderbar, auch vom Smartphone.
        Übrigens, Respekt für deine Webseite bzw. den Blog insgesamt. Das macht alles einen sehr professionellen Eindruck und da steckt bestimmt viel Arbeit drin.
        LG, Konrad

        1. Hi Konrad,
          für mich ein Zeichen, dass ich das vielleicht noch etwas deutlicher schreiben muss. Deswegen: danke für den Kommentar.
          Und danke fürs Lob!
          VG, Wolfgang

  3. Hallo Wolfgang,
    erstmal ein großes Lob an Deine tolle Seite bzw. sehr hilfreichen Ausführungen zum Thema ESP8266 mit Webserver und AP.
    Bei meinem Projekt betreibe ich einen ESP8266 als Treiber für eine Geschwindigkeitsanzeige. Der ESP läuft zusätzlich als AP und soll bei Bedarf über ein Handy angesprochen werden können – in meinem Fall, um z.B. die Helligkeit der Anzeige zu ändern bzw. auch, um Schwellwerte zu setzen, bei denen sich die Farbe der Anzeige je nach Geschwindigkeit ändert. Meine Frage wäre jetzt also, wie ich im Webinterface Variablen definieren kann, die per Handy manipuliert werden können. Nach der Manipulation sollten die Werte im Sketch entsprechend verwendet werden bzw. auch gespeichert, um nach einem Spannungsausfall weiterhin zur Verfügung zu stehen.
    Vielen Dank für Deine Mühe.

    1. Hallo Dirk, du möchtest also Daten auf dem Handy eingeben, die dann im auf dem ESP8266 verarbeitet werden. Eine fertige Lösung kann ich dir nicht anbieten. Daten eingeben ließen sich per HTML Formular:

      https://wiki.selfhtml.org/wiki/HTML/Tutorials/Formulare/Was_ist_ein_Webformular%3F

      Nur wie man die Eingabe dann als Variable im Sketch weiterverarbeitet, da habe ich spontan keine Idee. Daten über einen Spannungsausfall hinaus zu erhalten, ist kein Problem. Dafür kann man den EEPROM nutzen.

      1. Danke für den Denkanstoß – in die HTML Formulare werd ich mich mal reinlesen.
        Ansonsten konnt ich Deine Programmbeispiele schon super für mein Projekt verwenden.

        1. Hallo Dirk,
          es geht auch einfacher als mit der Formular-Methode wenn du die get-Methode mit Parameter(n) aufrufst. Als Beispiel habe ich die beiden Handler aus Wolfgangs Beispiel mit „ledon“ und „ledoff“ in einen Handler „switchled“ geändert. Der Client benutzt dann die URL „/switch_led?value=ON“ oder eben mit value=OFF.
          In deinem Sketch kannst du den Wert von „value“ abfragen mit ‚String val=server.arg(„value“);‘

  4. Sehr interessantes Projekt. Derzeit habe ich eine Wetterstation im WLAN, die Daten an einen Wetterserver im Internet sendet. Da die Daten im MESH vorhanden sind, die IP-Adresse des Absenders (Wetterstation) bekannt sind, müßten sich die Daten doch auslesen und mit Auswerte-Sketchen z.B. eine Relaisgruppe ansteuern lassen.
    Hintergrund: Der Solarantrieb der Markise von Schellenberg hat eine Fernbedienung (die habe ich schon auf Zigbee umgebaut). Jetzt soll die Wetterststation ihre Daten liefern (Sonnenschein + Temperatur = ausfahren; Wind/Regen/keine Sonne = einfahren) und mit den Relais den Tastendruck auf der Fernbedienung simulieren.
    Meinst Du das klappt?

    1. Theoretisch kann man jede unverschlüsselte Datenübertragung per WLAN mitlesen. Deswegen sollte man in öffentlichen, ungeschützten WLANs auch immer VPN nutzen. Wie man das Mitlesen bewerkstelligt, kann ich dir aber nicht verraten. Die hier genannten Techniken basieren darauf, dass Daten konkret abgefragt mit klar definierten Rollen als Server und Client. Du willst, wenn ich richtig verstanden habe, „mitlauschen“. Wie das funktioniert, das weiß ich nicht.

      1. Mit der Wetterstation habe ich mich noch nicht näher beschäftigt, mal sehen ob ich die IP des Wetterservers auf die WLAN-Arduiono IP ändern kann, das wäre eine direkte Adressierung, das wäre einfacher..

  5. Wolfgang, da es Dir darum geht, Interessierten einen Überblick zu geben: Bevor ich überhaupt anfange, da gibt es für wenig Geld eine fertige Hardware „SenseCAP Indicator D1“ basierend auf ESP32 mit Display und WLAN Schnittstelle u.a., siehe https://www.seeedstudio.com/SenseCAP-Indicator-D1-p-5643.html. Gehe ich da richtig, dass ich diese Hardware mit der Arduino IDE freeware von meinem Linux Laptop aus programmieren könnte, dumm gefragt? Es soll ja nur per WLAN ein paar Statusdaten regelmäßig aus dem Heimnetz bzw. vom Homecenter ziehen und anzeigen … bei Fibaro z.B. gibt es ein solches fertiges device nicht, es wäre also gut, man könnte sich mit dem SenseCAP Indicator eine Lösung schneidern, ein paar Programmierkenntnisse vorausgesetzt.

    1. Interessantes Spielzeug (meine ich nicht abfällig!). Ich habe das Manual mal quergelesen und es hat mir den Eindruck vermittelt, dass man das gute Teil mit der Arduino IDE programmieren kann. Wie gut das funktioniert, kann ich dir leider absolut nicht sagen. VG, Wolfgang

  6. Hallo Wolfgang,
    programmiert mit den ESP32 hab ich schon einiges, deine Anleitung hat mir nun auch den Einstieg zum Webserver erstellen erleichtert – vielen Dank dafür 🙂

    Ich möchte aber über den Server nichts Steuern, sondern nur Daten empfangen.
    Das Projekt habe ich mir nun schon erfolgreich umgebaut und es funktioniert – jedoch immer nur für knapp über eine Minute, dann friert das Bild ein und die Werte verändern sich nicht mehr.
    Ich nehme an, dass die Messung innerhalb des ESP32 noch läuft, der Server aber nicht mehr aktuelle Werte anfragt. Kann ich das irgendwie Steuern dass der Server alle x Sekunden sich die neuen Werte holt?

    Eine Zweite Frage hab ich auch noch auch wenn ich diese mit einen Workaround lösen konnte: Wie sende ich einen INT zu den server?
    Ich habe diese Zeile verwendet: message += String(sec,0); und wenn sec ein integer ist, wird dieser in Binär ausgegeben. Ich habe es mal so gelöst, dass ich Daten die ich Senden mag zu einen float mache, aber das kann ja nicht die endgültige Lösung sein.

    Vielen Dank für deine Hilfe
    Isaak

    1. Hi Isaak,
      den automatischen Refresh erzielt man, indem man diese Kopfzeile einfügt:
      „<head><meta http-equiv=\“refresh\“ content=\“5\“></head>“
      Die „5“ bedeutet: Refresh nach 5 Sekunden. Das findest du in einigen Beispielsketchen. Auf der Serverseite musst du natürlich auch dafür sorgen, dass ein aktueller Wert bereit steht.

      Zu anderen Frage: lass einfach die 0 weg. Wenn sec ein float ist, dann gibt der zweite Parameter für String() die Nachkommastellen an. Wenn es hingegen ein Integer ist, dann gibt der zweite Parameter das Zahlensystem an, also z.B. BIN (bzw. 2) für binär oder HEX (bzw. 16) für hexadezimal. Voreinstellung ist DEC (=10), also „normal“. Mich wundert, dass du mit 0 überhaupt eine Ausgabe erhältst, da es ja kein 0er-System gibt.

      VG, Wolfgang

          1. Hallo Wolfgang,
            habe Boardpaket und USB-Treiber neu installiert.
            Jetzt funktionierts auch mit Windows11.
            Danke Dir.Tolle Seite.
            SG, J.Rehm

  7. Hallo Wolfgang,
    tolle Seite 🙂
    Endlich bin ich der Steuerung über Webseite ein wenig näher gekommen.

    Station (STA) und Access point (AP) WLAN Modi

    Allerdings scheitere ich daran, einen Timer ein zu bauen.
    Möchte eine Nachlaufsteuerung LED1 einbauen.
    Außenlicht (was innerhalb der Hütte geschaltet wird) : Licht soll nachleuchten und per Handy schaltbar sein.

  8. Hallo Wolfgang,
    tolles Thema und genau meinen Nerv getroffen! Echt gut.
    Leider hänge ich nun seit Wochen an der Stelle „Mehrere MCUs vernetzen mit Router als Access Point“.
    Daher mein Hilferuf.
    Der Sketch an sich läuft bei mir perfekt. Nun möchte ich aber von den Hosts mehrere Daten abrufen (wie Temperatur, Luftfeuchte, Helligkeit, etc.).
    Dafür habe ich die „entsprechenden“ Ergänzungen vorgenommen, bekomme aber die gewünschten Daten vom Browser nicht angezeigt. Die Boxen und die sonstigen Daten darin, wie z.B. „Spannung 1 … V“ über message-Befehle kommen alle, nur eben die Meßwert fehlen.
    Lediglich der erste Wert jedes Hosts, den ich mit url und GET abgerufen habe ist vorhanden.
    Für den zweiten Wert habe ich ein Block mit einem GET dafür angelegt, der wird auch vom Programm durchlaufen, aber ansonsten ignoriert.
    Damit bin ich offensichtlich auf dem Holzweg.
    Kannst du mir bitte noch Tipps für die Lösung mit mehreren Meßwerten geben?
    Zum Verständnis: Was bedeutet/besagt der „String Voltage[2] = {„“,““};“ eigentlich?
    Beste Grüße
    Alois

    1. Hallo Alois,
      pro Host brauchst du nur eine GET Anweisung auf der „Main MCU“. Das Verzeichnis würde ich dann nicht mehr „voltage“ sondern „measured_values“ (Messwerte) o. ä. nennen. Die Messwerte fragst du dann alle „in einem Rutsch“ ab. D.h. auf der Host-Seite verpackst du alle Messwerte in dem String „message“. Du könnest die Messwerte z.B. durch Semikolons trennen. Also, in etwa:

      String message = String(Messwert1);
      message += „;“;
      String messwert2 = String(Messwert2);
      message += messwert2
      usw.
      Auf der Hostseite pulst du die Messwerte wieder auseinander. Um Strings nach Zeichen zu durchsuchen und enstprechen zu zerlegen, gibt es Funktionen, die du hier findest:

      https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/

      Ich hoffe du verstehst, was ich meine.

      String voltage[2] = {„“,““}; definiert ein zweidimensionales String-Array namens voltage, das zunächst zwei leere Strings enthält. Später nutze ich dieses Array für voltage[HOST_1] und voltage[Host2].

      Ich hoffe, dich bringt das ungefähr auf die richtige Spur und verwirrt dich nicht völlig!

      VG, Wolfgang

  9. Hallo Wolfgang,
    vielen Dank für die ausgezeichnet strukturierten und detaillierten Informationen, die Du hier anbietest.
    Der Punkt „Mehrere MCUs vernetzen mit Router als Access Point“ trifft fast genau meinen Anwendungsfall: Allerdings laufen die Sensoren (ESPs) im Batteriebetrieb und wachen nur alle x Minuten aus dem Deep Sleep auf, um eine Messung durchzuführen und das Ergebnis an eine Zentrale zu versenden; dann legen sie sich gleich wieder schlafen.
    Diese Messergebnisse würde ich aber gerne am PC im Browser angezeigt bekommen.
    Hättest Du für mich auch einen Lösungsvorschlag?

    Vielen Dank und viele Grüße,
    Wolfgang F.

    1. Hallo Wolfgang,
      der Deep Sleep hat leider keine Wake on WiFi Funktion, also müssen die ESPs, von denen du Daten abrufen willst, wach sein. Timer Interrupts können einen ESP wecken. Man könnte also darüber organisieren, dass alle zur selben Zeit wach sind und in der Zeit der „datensammelnde“ ESP („Main“) seine Arbeit tut. Problematisch ist dann aber die Abfrage vom PC. Wenn der Browser versucht, die Seite aufzurufen, die von dem Main ESP bereitgestellt wird und der schläft, dann bekommst du eine Fehlermeldung. Also muss zumindest der Main ESP dauerhaft laufen. Eine andere Möglichkeit fällt mir nicht ein.
      VG, Wolfgang

      1. Hallo Wolfgang,
        wiederum vielen Dank für Deine schnelle Antwort.

        Da hatte ich mich wohl missverständlich ausgedrückt: nur die Sensor-ESPs sind batteriebetrieben; der Daten einsammelnde ESP hängt am Stromnetz und darf ständig lauschen und arbeiten.

        Dadurch sind Rollen der beteiligten ESPs dummerweise andere, als in Deinem Artikel beschrieben: da sie ja nur kurz aufwachen, können die Sensoren keine Server sondern können nur Clients sein – dementsprechend müsste der Daten einsammelnde ESP der Server sein. Genau in diesem Punkt schwimme ich leider hilflos: Wie kann ein Client seine Messwerte auf den Server schieben?

        Oder wäre da vielleicht MQTT eine Lösung? Die Sensoren versenden ihre Daten per MQTT, und der Server pollt den MQTT-Server (evtl geht das auch per Interrupt) um diese Daten dann aufzuarbeiten und wiederum in einem weiteren Server dem PC als HTML Seite anzubieten.

        1. Hallo Wolfgang,
          mit einem POST request müsstest Du die Daten von den Sensor ESPs senden können. Ich kann Dir aber nicht konkret sagen, wie das funktioniert. Dazu gibt es einiges im Netz, aber mir fehlt momentan die Zeit, das auszuprobieren. Mit MQTT sollte das auch funktionieren, ausprobiert habe ich MQTT bisher aber nicht. Deswegen kann ich auch da keine große Hilfe sein.
          VG, Wolfgang

          1. Hallo Wolfgang,
            vielen Dank! Deine Antwort gibt mir bereits genügend Zuversicht, dass ich nicht völlig falsch liege.

            Nochmals herzlichen Dank und viele Grüße,
            Wolfgang F.

  10. Hi Wolfgang,

    ich bin letzte Woche auf dein ausführliches Tutorial hier gestoßen und habe es heute durchgearbeitet. Ich finde, dass du dem Ganzen eine wirklich gute Struktur gegeben hast, die in sich schlüssig ist. Der von dir aufgeführte Code ist verständlich, wenn man auch bereit ist, sich in das Thema einzuarbeiten. Tolle Arbeit.

    Viele Grüße

  11. Hallo,
    Danke für die Anleitung. Vielen Dank.
    Ich habe ein Problem. Ich will die GPIO’s über ein eigenes PC-Programm schalten. Also nicht über eine Website. Die Verbindung mit meinem ESP32 funktioniert ohne Problem, nur weiß ich nicht, wie ich den Sende-Befehl vom PC zum ESP32 aufbauen soll.
    Könntest du mir bitte den Aufbau des Befehls mitteilen?
    Mein Projekt soll über den PC die GPIO’s ansteuern und so verschiedene Module steuern, sowie Messdaten empfangen.
    Vielen Dank für deine Mühe

    1. Diese Frage ist nicht so leicht beantwortbar. Die erste Frage ist, womit du programmieren möchtest. Wenn du mit C++ direkt auf den WLAN-Adapter zugreifen möchtest, dann musst du dich schon ziemlich gut auskennen. Also ich habe damit jedenfalls keine Erfahrung. Vielleicht funktioniert es auch irgendwie über ein Powershell Skript, da kann ich aber auch nicht weiterhelfen. Unter Linux gibt es noch ganz gute Möglichkeiten:
      https://superuser.com/questions/709649/whats-needed-to-have-a-shell-script-run-via-http-post-request
      Einfachere Kommunikationsmöglichkeiten wären über den seriellen Monitor (leider dann per Kabel), oder über Bluetooth mit einem Terminal Programm.
      Relativ einfach ist auch die Bluetooth-Programmierung per Smartphone mit App Inventor. Erfordert aber auch Einarbeitung.
      Tut mir leid, etwas ganz Einfaches kenne ich nicht. Vielleicht liest das ja noch jemand, der eine bessere Idee hat.
      VG, Wolfgang

  12. Hallo Wolfgang,
    vielen Dank für deine tollen Ausführungen!
    Obwohl ich absoluter Anfänger bin, konnte ich schon vieles „nachbauen“.
    Aktuell habe ich aber Schwierigkeiten mit der Anordnung „Mehrere MCUs vernetzen mit MCU als access point“, obwohl ich leider genau diese für meine Anwendung benötige.
    Ich arbeite mit zwei ESP32 und habe die scetches entsprechend abgeändert. Ferner arbeite ich aktuell nur mit einem Host (sprich: insgesamt sind zwei MCU in Betrieb. Einer als Server/Client und einer als Host)
    Am Laptop wird mir aber nur der Ausgabewert des Server/Client angezeigt, nicht aber der Ausgabewert des Hosts, der ja vom Server/Client abgefragt werden sollte.
    In Verdacht habe ich Zeile 77 des Server/Client-scetches. Wie sollte diese Zeile für den ESP32 aussehen?

    Viele Grüße
    Markus

    1. Hallo Markus, ich habe es gerade mit 12 ESP32-WROOM-32 basierten Development Boards ausprobiert und es hat funktioniert. Die einzigen Änderungen, die vorgenommen habe, waren die zwei Stellen, an denen ESP8266WebServer durch WebServer ersetzt wird. Allerdings funktionierte es erst (zuverlässig), als ich mit den USB-Anschlüssen der Boards von der PC-Buchse an meinen USB-Hub umgezogen bin, der eine extra Stromversorgung hat. Könnte es so etwas auch bei dir sein? Oder hast du noch mehr bei den Sketchen verändert?
      VG, Wolfgang

      1. Hallo Wolfgang,
        vielen Dank für dein tolles Engagement!
        Ich hatte tatsächlich den SSID-Namen in den Zeilen 3, bzw. 5 und das Passwort in beiden Sketchen geändert.
        Heute habe ich nochmals neu überspielt und nur die von dir angegebenen Zeilen verändert. Dann funktioniert es! Sobald ich aber (auch nur) das Passwort im Host-Sketch ändere, dann wird der Wert für den Host nicht mehr angezeigt. Die ganze Zeile für den Zahlenwert von Voltage_2 verschwindet dann. Die Änderung des Passworts im Server/Client-Sketch hat hingegen scheinbar keinen Einfluss. (Das Passwort wird beim Einloggen auch nicht erfragt/gefordert.)
        Was mich auch irritiert: Wenn ich am Smartphone die Detailansicht des Netzwerks anschaue, so steht dort unter IP-Adresse 192.168.4.2; erwartet hätte ich 4.1.
        Wie es auch sei: Es funktioniert, ich werde mich weiterhin damit beschäftigen und hoffentlich dazulernen.
        Nochmals vielen, vielen Dank und viele Grüße
        Markus

  13. hallo wolfgang,

    vielen dank für die umfangreiche einfühung in das thema. es war sehr interessant und lehrreich.
    bin blutiger anfänger und gerade dabei mich in das wlan thema einzuarbeiten. wäre beinahe am einrichten des webservers gescheitert…….meine boards ( D1 mini; ESP32 und ESP 8266 ) sind alle beim verbinden mit dem router
    hängen geblieben und würden warscheinlich jetzt noch suchen.
    deshalb meine bitte für uns anfänger das thema PORT noch etwas zu vertiefen. bin durch zufall in einem anderen sketch über eine andere bezeichnung des PORTES gestossen und schon läuft es……..ich muss den PORT die definition 8088 geben. Ja die anfänger scheitern meistens an kleinigkeiten.

    vielen dank für ihre immer wieder interessanten themen, machen sie weiter so.

    MfG Mirko

    1. Hallo Mirko,
      danke, so ein Feedback hilft mir. Das der Port 80 nicht funktioniert, ist recht ungewöhnlich. Normalerweise ist das der voreingestellte Port für Webserver, den man auch nicht in der Form xxx.xxx.xxx.xxx:80 (mit 80 als Port angeben muss. Eigentlich muss man schon aktiv etwas dafür tun, damit Port 80 nicht funktioniert. Musst du dann beim Aufruf per Browser die 8088 mit angeben, also xxx.xxx.xxx.xxx:8088 ? Im Prinzip kannst du dir als Port aussuchen, was du willst, z.B. 1234 oder 4711, sofern du die Portnummer dann hinten dranhängst. Und ich gehe davon aus, dass du deine Boards über das Heimnetz mit dem Router verbunden hast und nicht von außen zugreifst, richtig?
      VG, Wolfgang

  14. Hallo,
    ich bin bei ersten Gehversuchen mit Arduino auf diese Seiten gestoßen und bin stark beeindruckt. Schon mal besten Dank für die ausführlichen Informationen.
    Zunächst habe ich mich mit WLAN mit ESP8266 und ESP32 und dabei mit der server.on-Lösung mit CSS-Elementen beschäftigt und für mein Projekt angepasst, z.Zt. auf die Ansteuerung eines einzelnen Relais mit dem D1-mini, Anzeige eines Analogwertes und einer Relais-Zustandsanzeige. Funktioniert alles über PC/ Smartphone.
    Jetzt würde ich gern das Relais mit dem ON-Button einschalten (wie bisher) und nach einer definierten Zeit ausschalten und danach den ON-Button wieder freigeben. Der OFF-Button könnte dann während der Einschaltzeit die Meldung „Relais EIN“ anzeigen.
    Meine Versuche über eine if-Anweisung das Relais nach einer Zeit (ohne „delay“) auszuschalten, greifen nicht, da das Relais nicht dauerhaft ausgeschaltet bleibt und unregelmäßig ein- und ausschaltet.
    Ich hoffe, falls es den Rahmen hier nicht sprengt, auf eine einfache Lösung meines Problems.
    Vorab schon mal besten Dank.

    1. Hallo,
      schwierig zu sagen, warum das Relais unregelmäßig und ohne dein Zutun schaltet. Dafür muss es ja einen Grund geben. Das Relais wird in irgendeiner Form durch einen Pin des ESP32 oder ESP8266 geschaltet. Ich gehe davon aus: wenn Pin HIGH dann Relais auf, wenn Pin LOW dann Relais zu bzw. andersherum, richtig? Hast du vielleicht einen undefinierten Zustand an dem Pin? Das könnte passieren, wenn du ihn INPUT/LOW schaltest, denn dann bräuchtest du einen Pull-Down Widerstand. Könnte es so etwas sein?

      Und du sagst, du verwendest kein delay, was ja sehr löblich ist. Wie steuerst du die Zeit dann? Machst du es dann? Mit millis? Ist vielleicht da irgendwo das Problem? Vielleicht kannst du das genauer beschreiben.
      VG, Wolfgang

  15. Hallo Ewald,
    ich finde Deine Erklärungen und Dein Engagement richtig toll!
    Vielleicht kannst Du mir auch einen Denkamstoß geben, habe mich etwas „festgerannt“?
    Ich möchte die ESP32-Cam via Webserver (AP-Mode) über einen ESP32 Client (auch AP-Mode, aber ohne Internet/vorhandenes WLAN) ansprechen.
    Einsatz wäre eine Video-Haustürkamera, die in mehreren Stockwerken/Wohnungen funktioniert. Daher möchte ich auch keinen STA-Mode verwenden.
    Leider habe ich beim bisherigen Suchen im Internet nichts gefunden, was mir weiterhelfen könnte.
    Habt Ihr eine Idee, wie ich das bewerkstelligen könnte? Geht das überhaupt?

    Herzlichen Dank für Eure Ideen!
    Gruß
    Joachim

    1. Hi, die nächsten Tage habe ich keine Zeit, mich mit dem Problem auseinander zu setzen. Da muss ich mich ein wenig „hineindenken“.
      VG,Wolfgang

  16. Hallo Wolfgang Ewald
    tolle Anleitung – hat bei mir alles auf Anhieb funktioniert, nach den Anpassungen auf mein System (ESP32 Lolin).
    Nun habe ich paar Fragen:
    > zwei meiner drei LEDs haben einen Transistor als Endstufe und schalten also entgegengesetzt zu der LED auf dem Board (die ja direkt am Port angeschlossen ist). Wie kann ich im Code den Pegel der LEDs invertieren, so dass trotzdem alles richtig schaltet?
    > warum muss man sich den Status der LEDs in einem Array merken, kann man den nicht aus den Ports direkt auslesen?
    >ich will mehrere Temperatursensoren (DS18B20) auslesen und genauso wie die Spannung in farbigen Boxen anzeigen lassen. Wie füge ich die weiteren Boxen hinzu?
    > wie kann man einen Sicherheitscode einbauen, da das Ganze ja völlig offen ist und jeder per Webseite auf die Schalter und Messwerte zugreifen kann?

    Danke im Voraus

    1. Hallo,
      zu den vier Fragen:
      1) In switchLEDAndSend beim Aufruf von digitalWrite state in !state ändern. Und natürlich in setup den Ausgangszustand ändern.
      2) Geht auch, ich fand es so aber besser als bei jedem Schalten alle Zustände abzufragen. Aber globale Variablen einzusparen ist auch gut.
      3) Ich kann hier im Rahmen der Kommentare kein HTML Tutorial geben. Um einfach noch eine Box dranhängen, muss man im Prinzip nur den entsprechenden Code für die erste Box kopieren und hinten dran hängen.
      4) Die durch den ESP32 oder ESP8266 bereitgestellten Webseiten sind nur im lokalen Netzwerk (Heimnetz) erreichbar, welches von außen normalerweise nicht zugänglich ist (höchstens über VPN). Das Heimnetz selbst ist über ein Passwort geschützt. Also stellt sich die Frage eigentlich nicht, es sei denn, du möchtest auch anderen Nutzern deines lokalen Netzes den Zugang verwehren. Das führt hier aber zu weit.

      VG, Wolfgang

      1. danke für die schnelle Antwort – das mit den LEDs funktioniert soweit.
        nun habe ich zu der blueBox noch eine yellowBox definiert mit den selben Parametern nur Boxfarbe yellow statt blue und Schriftfarbe schwarz anstatt weiß. Die Box wird auch so dargestellt mit dem Wert des DS18B20 darin.
        Aber beide boxen lassen sich nicht untereinander anordnen – die blaue überlagert die gelbe box (es muss was mit dem Textfluss float zu tun haben) Ich hab versucht Aufklärung zu finden aber die CSS-Anleitungen sagen mit nichts.
        Wie kann ich also die yellowBox (und später weitere Boxen oder Buttons) unter die blueBox positionieren?

        hier der Auszug aus meinem Code:
        //Akkuspannung
        float measuredValue1 = analogRead(35)/955.0; //Spannungsteiler Akkuspannung und ADC justiert
        message += „“;
        message += „Akku-Spannung [V]: „;
        message += String(measuredValue1, 2); //zwei Nachkommastellen
        message += „“;
        message += „“;
        server.send(200, „text/html“, message);

        //Tempsensor1
        float measuredValue2 = (tempSensor1); //DS18B20 auslesen
        message += „“;
        message += „Temp [ºC]: „;
        message += String(measuredValue2, 1); //eine Nachkommastelle
        message += „“;
        message += „“;
        server.send(200, „text/html“, message);

        1. Die Kommentarfelder verstehen HTML und interpretieren deshalb alle Eingaben zwischen „kleiner als“ und „größer als“ als HTML-Code. Deswegen wird Code hier nicht richtig dargestellt. Außerdem werden Einrückungen ignoriert. Das kann ich nicht abstellen. Da muss man dann die HTML Anweisungen zur Darstellung dieser Zeichen nehmen. Führt zu weit hier. Du kannst den Code schicken an wolfgang.ewald@wolles-elektonikkiste.de.

          Zeilenumbrüche werden mit </BR> eingefügt und jede Box muss in eine eigene div Umgebung <div>….</div> .

  17. Hallo Wolfgang,
    erstmal auch von mir herzlichen Dank für Deine Tollen Beispiele zum Webserver. Für mich als Laie zu dem Thema waren diese sehr gut zu verstehen. Leider funktionieren die Beispiele nicht für meine Anwendung oder ich bin noch nicht auf den geeigneten Workaround gekommen. Zum einen möchte ich auf meiner Seite Sensor Werte anzeigen, zum anderen einen Sollwert via zwei Button (+ / -) um ein Inkrement nach oben oder unten verändern. Da die Seiten aber immer wieder aktualisiert werden verändert sich der Wert nach der ersten Betätigung ständig je nachdem welche Taste (+ / -) zuletzt gedrückt wurde. Eine Enter Taste würde Abhilfe schaffen ist aber nicht sehr schön in der Anwendung. Vielleicht hast Du ja eine Idee?
    Viele Grüße und Danke schonmal. Daniel

    1. Hallo Daniel,
      interessante Frage – und diese Einleitung heißt, dass ich selber erst einmal ins Grübeln kam. Ich habe es mal nachvollzogen und bin auf dasselbe Problem gestoßen. Die Lösung ist, dass du von den + und – Seiten auf die Hauptseite umleitest. Dazu habe ich das „one LED“ Beispiel genommen und für das + definiert:

      server.on(„/plus“, add); mit „/plus“ anstelle von ledon

      Den Wert, der inkrementiert werden soll, habe ich target genannt. Mein ESP32 Modul hat die Adresse 192.168.18.115. Dann ist die add-Funktion:

      void add(){
        target++;
        String message = "<head><meta http-equiv=\"refresh\" content=\"0; URL=//192.168.178.115\"></head>";
        server.send(200, "text/html", message);
      }
      

      Mit Firefox und Edge hat das problemlos funktioniert.

      Sprich, wenn du auf das Plus drückst, wirst du automatisch zur Hauptseite zurückgeleitet. Ich sende dir den ganzen Sketch per mail.
      VG, Wolfgang

  18. Hallo Wolfgang,
    erst einmal vielen Dank für eine ausführliche Anleitung, sie ist sehr gut verständlich. Ich möchte in meinem Projekt mehrere ESP8266 über einen Router vebinden und diese mit einem ESP32 fernsteuern. Da die ESP8266 nur jeweils zwei Relais schalten sollen, habe ich mich für die server.on() Methode entschieden, weil dabei keiner der Teilnehmer Traffic erzeugt, wenn nichts geschalten werden soll. Der Sketch auf dem ESP8266 ist fertig und funktioniert über den Browser. Mir ist nur nicht klar, wie dann der ESP32 den Befehl (z.b. LED0_on an den ESP8266 senden soll. Der ESP8266 ist dann Server und der ESP32 Clinet, oder? Vielen Dank im Voraus!

    1. Hallo Michael,

      ja, so würde ich es machen. Die ESP8266 als Server und den ESP32 als Client. Im Prinzip ist das der Aufbau aus dem letzten Abschnitt „Mehrere MCUs vernetzen mit Router als Access Point“. Dann nimmst du den Sketch main_mcu_setup_with_router.ino und änderst ihn ab. In Zeile 94 wird der Nachricht an die Server „\voltage“ zugefügt. Das musst du dann entsprechend umschreiben, so dass du „\led0_on“ oder „\led0_off“ wahlweise versenden kannst. Ich hoffe, es is ungefähr klar?! Ich muss mich da übrigens auch immer wieder neu reindenken!

      VG, Wolfgang

      1. Hallo Wolfgang,
        Vielen Dank für deine Erklärung, meist genügt ein Kick in die richtige Richtung:-) Hab es ausprobiert, funktioniert! Ich brauche eigentlich die Antwortfunktion des Servers nicht, werd es aber trotzden als Bestätigung verwenden, dass das Relais geschalten wurde.

      2. Hallo Wolfgang,
        Danke für Deine Anleitungen. Ich bin nun Tag 2 gespannt vor dem PC und probiere das Gelernte mit meinen ESP8266 D1 mini etc. aus. Heute erwarte ich die nächste Lieferung und dann kann ich meine ESP Familie mit Aufgaben versehen. Es ist toll, am PC, per Tablet oder mit dem Handy den Überblick zu behalten, über Sensordaten inclusive Spannungen bei externen Aufbauten. Ich werde das für meine mini Solartechnik (im ‚kleinen‘ Balkonkraftwerk ohne Einspeisung, aber mit mehreren Powerboxen und weiteren Speichern) und mehr nutzen. Damit wird ein langjähriger Wunsch wahr. Es ist aufregend und toll, vielen Dank!

  19. Hallo 🙂 Ich muss das Thema nochmals hochholen und hoffe auf Antwort .
    Ich bin in der Firma ins kalte wasser gschmissen worden und muß ein az delivery esp32-wroom-32 ins wlan reinbekommen um überhaupt mit meinem projekt weiter zu kommen .
    Da habe ich aber schon das problem das ich das schon nicht hinbekomme .
    Wie wäre da die einstellungen ?
    const char* ssid = „Your SSID“;
    const char* pass = „Your Password“;

    1. Hallo, „Your SSID“ ist der Platzhalter für den Namen des WLANs, „Your Password“ ist der Platzhalter für das Passwort des WLANs. Die Zugangsdaten des WLANs deiner Firma kenne ich natürlich nicht. Falls du sie auch nicht kennen solltest, musst du den IT-Experten bei euch fragen. Die Anführungszeichen musst du beibehalten. Hoffe, das hilft….

  20. Hallo Wolfgang, ich bin begeistert was alles mit dem ESP8266 geht und wie du das gut rüber bringst.
    Vielen dank für die guten Beispiele.
    LG, Martin

  21. Guten Morgen Wolfgang,
    ich habe bereits erfolgreich mit Deinen Anleitungen hier und aus dem HX711 Beitrag eine Körperschwerpunktwaage gebaut die von einem ESP8266 ausgewertet und als Webseite ausgeliefert wird. Da ich ständig 2 oder mehr Deiner Anleitungen verwende ist es etwas schwierig für mich die Richtige Anleitung für meine Frage auszuwählen.
    Ich versuche es aber mal hier, weil es nicht um die Messung sondern die Übertragung geht :
    Ich möchte nun die Abtastrate des HX711 auf 80Hz ändern und 5 Sekunden messen. Macht 80×5=400 Messerwerte pro HX711. Ich verwende derer 4 also kommen 1600 Messwerte a 24bit in 5 Sekunden zusammen. Die möchte ich in einem Rutsch via HTTP übertragen. Weder das Übertragen, noch das Auslesen macht mir Sorge. Die Frage ist wo sammle ich diese 1600 Werte und speichere sie zwischen? 24bit = 3 Byte, macht 4,8KiB. Kann man das einfach in eine Variable Packen und dann raussenden? Oder müsste ich die Daten irgendwie abspeichern?
    VG Leif

    1. Hallo Leif,

      für 24 Bit brauchst du ein long oder unsigned long. Ich war mir nicht sicher, wie weit man mit der Größe von Arrays auf dem ESP8266 gehen kann, also habe ich gerade einmal folgendes ausprobiert:

      unsigned long test[1600] ;
      for(int i=0; i<1600; i++){
      test[i] = 16000000 + i;
      }
      und konnte dann auf ausgewählte Element zugreifen. Ein AVR basierter Arduino könnte das nicht, da der Speicher nicht ausreicht.

      Eine long Variable belegt 4 Byte und damit verschenkst du ein Byte pro Wert. Wenn du das nicht möchtest könntest du alternativ ein Array von 4800 bytes erzeugen, also
      uint8_t test[4800];
      Dann nimmst du die Messwerte, „zerhackst“ sie in einzelne Bytes und schiebst sie in das Array. Nach dem Übertragen müsstest du daraus dann wieder long oder unsigned long Werte basteln.
      Viel Erfolg!
      VG, Wolfgang

  22. sehr coole Anleitung
    ich bin momentan gerade mit dem ESP32 am rumprobieren aber finde die Library nicht. Es gibt tausende die Webserver heißen und unter Webserver.h finde ich gar nichts. kannst du evtl. noch durchgeben welche Library du für das ESP32 verwendet hast? 😀 vielen Dank schonmal im voraus 🙂

      1. Vielen dank für die Antwort. Ja da hab ich wohl das ESP32 falsch implementiert. Mitlerweile funktionierts 😍

  23. Hallo!
    Die Seiten sind wirklich eine Bereicherung für Arduino, ESP etc. Es ist alles sehr gut strukturiert und ausreichend erklärt ohne irgendwelche Besserwisser-Kommentare. Ich habe aber ein kleines Problem. Als Modul habe ich einen ESP8266 (Board: NodeMCU1.0(ESP-12E Module) )und eine Arduino IDE 1.8.19. Der erste Sketch (web_server_basic_choose_IP.ino), bei dem ein Webserver eingerichtet wird, funktioniert so wie angegeben. Es wird über den seriellen Monotor die IP_ Adresse ausgegeben (bei mir: 192.168.1.108). Beim 2.Beispiel (ESP8266_ESP32_one_LED.ino) gibt es folgendes Problem: Das Hochladen ist o.k. Ruft man den seriellen Monitor auf; so erscheint auch die Meldung: Connecting to: (Anzeige ist meine ssid), dann erscheinen Punkte, deren Anzahl nicht endet, d.h. die Verbindung kann nicht stattfinden?? Passwort und ssid stimmen, mit einem ESP32 klappt es.
    Kann mir geholfen werden?
    Dank im voraus.

    1. Hallo Heinz,

      erst mal vielen Dank für das Lob – geht runter wiel Öl!

      Ich habe gerade den Sketch, der bei dir nicht funktioniert, auf einem NodeMCU 1.0(ESP-12F) Modul getestet. Also anstelle 12E steht auf meinem Modul 12F. In der Arduino IDE habe ich aber die „E“ Version ausgewählt. Bis auf die Zugangsdaten und die IP Adresse habe ich nichts verändert. Das Modul verbindet sich ohne Probleme. E oder F sollte eigentlich keine Rolle spielen. Was mich wundert ist, dass es mit dem ESP32 geht und nicht mit dem NodeMCU. Ist die IP Adresse im Router vielleicht fest vergeben an den ESP32? Ich habe eine FritzBox, da kann man Geräten eine feste IP zuordnen, und die könnte man dann auch nicht anderweitig vergeben. Aber bevor du lange in den Router Menüs suchst, was passiert denn, wenn du einfach eine andere IP Adresse eingibst? Z.B. die ….109 oder ….107? Und hast du bei der IP Adresse außer der letzten Zahl auch die vorletzte (178 in meinem Beispiel) auf 1 geändert? Also bei dir müsste es heißen:
      IPAddress ip(192,168,1,108);
      IPAddress gateway(192,168,1,1);
      Anderseits dürfte es dann auch nicht mit dem ESP32 funktionieren. Also, probiere am besten mal ein paar IP Adressen aus.
      Du kannst dich ja nochmal melden, wenn es immer noch nicht geht.
      VG, Wolfgang

  24. Hallo,

    sehr gute Erklärung….
    Ich als Anfänger kann mehr solche Gute Infos benötigen.

    Versuche das nachzubauen mit einer RGB LED und einem ESP32.
    Besten Dank für die ausführlichen Erklärungen

  25. Ein sehr schöner Beitrag, der auch Grundlagen für Client Server Projekte liefert.

    Ich versuche -als ein blutiger Anfänger – ein Projekt zu realisieren, in dem ein Wemo D1 Mini beim Schließen eines Kontaktes (GPIO) eine Seite auf einem Server(Raspberry Pi) aufruft.
    Der Raspberry macht schon was ich will.

    Dir eine gute Zeit und bleib gesund.
    Martin

    1. Danke für’s Feedback und viel Erfolg mit dem Projekt. Wenn es irgendwo hakt, dann kannst du dich ja noch einmal melden. Bleib auch gesund!

  26. Hallo,
    pmmernoch sehr gut!
    Aber Vorsicht! Uch habe es unter Linux installiert, dabei wurden aber nicht alle Bibliotheken eingebunden.
    Als ich es später unter Kleinweich 10 installierte ging es! Danach nochmals mit Linux und nachgeladenen Bibliotheken. Jetzt geht es.
    Bei Linux wird leider nicht angezeigt, welche Bibliotheken fehlen.
    Das Problem ist dabei die Arduino-IDE. Unter Kleinweich ist es besser ausgeführt, Warum?

    1. Hi, ich kann dir nicht sagen, wieso es unter „Kleinweich“ (nette Bezeichnung für Microsoft) läuft und nicht unter Linux. Vielleicht funktionieren die älteren Arduino IDE Versionen unter Linux? Die 2.0.0 ist ja noch im Beta Stadium, vielleicht wird an der Stelle noch gebastelt.

  27. ich bekomme folgende Fehlermeldung:

    oot ERROR Error from plugin host: Channel closed
    root ERROR Error from plugin host: Channel closed
    daemon INFO inventory.Store.ConfigFileUsed() /home/bernd/.arduino15/inventory.yaml
    daemon INFO inventory.Store.ConfigFileUsed() /home/bernd/.arduino15/inventory.yaml
    daemon INFO Searching tools required for board esp8266:esp8266:nodemcuv2
    daemon INFO Required tool [tool: {ToolName:“mklittlefs“,ToolVersion:“3.0.4-gcc10.3-1757bed“,ToolPackager:“esp8266″}]
    daemon INFO Required tool [tool: {ToolName:“mkspiffs“,ToolVersion:“3.0.4-gcc10.3-1757bed“,ToolPackager:“esp8266″}]
    daemon INFO Required tool [tool: {ToolName:“python3″,ToolVersion:“3.7.2-post1″,ToolPackager:“esp8266″}]
    daemon INFO Required tool [tool: {ToolName:“xtensa-lx106-elf-gcc“,ToolVersion:“3.0.4-gcc10.3-1757bed“,ToolPackager:“esp8266″}]
    daemon INFO Adding libraries dir [dir: /home/bernd/.arduino15/packages/esp8266/hardware/esp8266/3.0.2/libraries, location: platform]
    daemon INFO Adding libraries dir [dir: /home/bernd/Arduino/libraries, location: user]
    daemon INFO Resolving include ESP8266WiFi.h for arch esp8266
    daemon INFO found better lib [lib: ESP8266WiFi, prio: 5E8]
    root ERROR Request upload failed with error: 2 UNKNOWN: exit status 1
    root ERROR Error from plugin host: Channel closed

    1. Hallo,
      in deinem ersten Kommentar hast du geschrieben, dass du einen ESP32 verwendest – in deiner Fehlermeldung steht aber nur etwas von ESP8266. Bist du irgendwie mit den Boards durcheinander gekommen? Welches Board verwendest du? Welchen Sketch? Welche IDE?
      VG, Wolfgang

  28. Moin
    wie immer – sehr ausführlich und informativ. Vielen Dank.

    Hätte zum Thema WLan und WiFi auch OTA (over the Air) gepasst?
    Gerade für den ESP-01/ESP-01S sehr interessant.

    Gruß
    Robert

    1. Ja, sicherlich. Danke für die Anregung. Vielleicht mache ich dazu nochmal was. VG, Wolfgang

  29. Sehr gute Erklärung. Schön strukturiert. Besten Dank dafür.
    Selten eine so gute Seite im Web gefunden!

  30. Vielen Dank für die Super Erklärungen und die tollen Beispiele.
    Besondern Danke noch für den Beitrag über DCF77 funktioniert super.
    Ich bin noch am Anfang mit Arduino usw. aber durch deine Beschreibungen mache es sehr viel
    spaß und man kommt sehr gut voran.
    Bin gerade dran meinen Smoker endlich auf WiFi umzubauen ( UDP ).
    Bin mir noch nicht ganz sicher auf welchem Weg ich die Daten schicken soll.
    Da hat mir dein Beitrag schon sehr viel geholfen.

  31. Auch von mir ein herzliches Danke und bei der Gelegenheit gesegnete Weihnachten.
    Endlich eine Seite, auf der es so gut erklärt wird, das auch ein Anfänger den Fuß in die Tür bekommt.
    Es ist extrem schwer wenn man sich selbst alles beibringen muß und auch Bücher sind oft nicht hilfreich.
    Da bin ich froh, wenn sich jemand solche Mühe macht und man Perlen wie diese findet.

    1. Hi Wolfgang,

      erst mal danke für die tollen Beiträge zum D1 Mini ! Ich stehe mit meinem aktuellen Projekt ein wenig auf dem Schlauch. Ich will Messdaten eines Ultraschallsensors mittels eines D1 mini an einen anderen D1 mini übertragen und dort an ein OLED Display ausgeben. Über die Espnow-Funktion ist mir das auch schon gelungen. Jetzt habe ich allerdings einige Störquellen die den Wlan-Einsatz erschweren. Daher wollte ich jetzt mithilfe von zwei W5500 Ethernet Modulen eine Lan-Verbindung herstellen. Das ganze gestaltet sich aber um einiges komplizierter. Mir ist bewusst, dass es hier bessere Boards gibt, aber ich möchte die Wlan-Funktionalität nicht aufgeben. Hattest du bereits damit gearbeitet und kannst mir eventuell ein paar Denkanstöße geben ? Gibt es etwas essentielles zu beachten bei der Verkabelung oder im Code bei der Verwendung solcher Ethernet-Module ? Danke schon mal im Voraus und viele Grüße !!

      1. Hallo Eric, ist schon etwas her, dass ich mit W5500 Modulen gearbeitet habe. Aber dabei habe ich nicht probiert, zwei Mikrocontrollerboards zu verbinden. Da kann ich leider nicht weiterhelfen und habe auch nach kurzer Google Recherche nichts gefunden. Wenn du einfach nur per Kabel zwischen zwei Boards kommunizieren möchtest, würde ich dafür Serial (HardwareSerial oder SoftwareSerial) verwenden. Wie weit man damit übertragen kann, hängt u.a. von dem verwendeten Kabel und der Baudrate ab. Für weite Strecken kann man zwei MAX3232 Adapter (RS232 zu TTL) dazwischen setzen. Ausprobiert habe ich es allerdings nicht.
        VG, Wolfgang

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert