Ziele des Projekts
- zwei Mikrocontroller unabhängig von einem bestehenden Router in einem eigenständigen WLAN-Netz betreiben
- mit beliebigen Temperatursensoren (hier DHT11/DHT22) an zwei verschiedenen Orten Temperatur und Luftfeuchtigkeit messen
- die ermittelten Messwerte in einem Webbrowser anzeigen
Benötigte Bauteile
- ESP32-Mikrocontroller oder ESP8266-Mikrocontroller in beliebiger Kombination
- DHT11/DHT22 Temperatursensoren
- Leitungsdrähte
Konfiguration der Mikrocontroller
Accesspoint-Modus (AP-Modus)
Beim AP-Modus bauen die ESPs ein vom heimischen Router unabhängiges eigenständiges Netz auf. Neben dem Namen des Routers und dem Passwort musst du dem ESP einige Daten mitteilen:
char Router[] = "ESPServer";
char Passwort[] = "espserver";
IPAddress ip(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0)
Der Name des Routers und das Passwort sind frei wählbar, allerdings muss das Passwort mindestens 8 Zeichen haben.
ip legt die statische IP-Adresse fest.
gateway ist das Gerät - in diesem Fall der ESP selbst - das die Kommunikation der verbundenen Geräte (der Klienten) untereinander regelt.
subnet ist der Adressbereich der zugelassenen IP-Adressen. 255 bedeutet, dass dieser Bereich jeweils unveränderlich ist, 0 am Ende heißt, dass die IP-Adressen variabel sind. Da die erste und die letzte IP-Adresse aus organisatorischen Gründen nicht vergeben werden darf, bleiben 254 IP-Adressen (192.168.4.1 bis 192.168.4.254).
Die neuere Schreibweise ist übrigens in diesem Fall 192.168.4/24.
Beachte, dass die Zahlenblöcke der IP-Adressen durch Kommata getrennt werden müssen.
Alle IP-Adressen, die mit 192.168. beginnen, sind als privat festgelegt, sie dürfen im Internet nicht verwendet werden. Die nächste Ziffer (4) bezeichnet das Subnetz. Hier sind maximal 256 Subnetze (192.168.0 bis 192.168.255) möglich. Die letzte Ziffer (1) ist die konkrete IP-Adresse des Geräts.
ip und gateway müssen gleich sein!
Du darfst kein Subnetz verwenden, das der Router für DHCP verwendet.
Du kannst dir mit einem Werkzeug einen Überblick über die im privaten Netz vorhandenen Geräte verschaffen und anhand der angezeigten IP-Adressen das vom Router für DHCP verwendete Subnetz herausfinden.
- Windows:
Eingabeaufforderung (cmd) öffnen
arp -n - Linux:
Konsole öffnen
arp -n zeigt alle über Ethernet verbundenen Geräte
arp-scan --localnet zeigt alle über WiFi und Ethernet verbundenen Geräte
Programm zum Aufbau des Netzes
// ESP32
#include "WiFi.h"
// ESP8266
// #include "ESP8266WWiFi.h"
// 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.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
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 Daten für Temperatur und Luftfeuchtigkeit. Der zweite Mikrocontroller (Host) misst ebenfalls Temperatur und Luftfeuchtigkeit. In regelmäßigen Abständen fragt der Server seine eigenen Daten und die des Hosts ab. Die Klienten zeigen die Daten auf der Webseite an.
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 des anderen ESP einsammeln und gleichzeitig als Klient ebenfalls Temperatur und Luftfeuchtigkeit messen.
Daher wird für die IP-Adresse und das Gateway die gleiche IP-Adresse verwendet.
// ESP8266
// #include "ESP8266WebServer.h"
// ESP32
#include "WebServer.h"
#include "WiFi.h"
#include "DHT.h"
// Pin des DHT-Sensors
int SENSOR_DHT = 19;
// Sensortyp festlegen
// DHT22 oder DHT11
#define SensorTyp DHT22
DHT dht(SENSOR_DHT, SensorTyp);
// Netzwerkname und Passwort des ESP
char Router[] = "ESPServer";
char Passwort[] = "espserver";
// ESP32
WebServer Server(80);
// ESP8266
// ESP8266WebServer Server(80);
// farbige Box mit CSS
String Seitenkopf =
"<head><style>"
".farbigeBox {"
"background-color: ivory;"
"color: black;"
"width: 480px;"
"padding: 20px;"
"text-align: left;"
"font-size: 40px;"
"font-family: arial;"
"}"
"</style>"
// refresh -> Seite automatisch aktualisieren
"<meta http-equiv=\"refresh\" content=\"30\"></head>";
// Wartezeit für die sichere Übermittlung der Daten
unsigned long Wartezeit = 5000;
// enthält die Daten des 2. ESPs
String Messung;
// IP-Adresse des 2. ESP
const char* host = "192.168.4.2";
// Konfiguration als Server und Host
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.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());
// Webserver starten
// / -> Aufruf der URL, SeiteBauen -> Aufruf der Funktion
Server.begin();
Server.on("/", SeiteBauen);
dht.begin();
}
void loop()
{
static unsigned long Startzeit = millis();
// auf Anfragen warten
Server.handleClient();
// Messdaten einsammeln
if ((millis() - Startzeit) > Wartezeit)
{
// Daten des 2. ESPs einsammeln
DatenHolen();
Startzeit = millis();
}
}
void SeiteBauen()
{
// Seite "zusammenbauen"
String Seite = "";
Seite += Seitenkopf;
Seite += "<h1>Messdaten</h1>";
Seite += "<hr>";
/*
Messung enthält die mit / getrennten Daten
String Messung mit substring am / trennen
Temperatur: von Position 0 bis zum / (indexOf)
Luftfeuchtigkeit von /+1 bis zur Länge des Strings (length)
*/
String TemperaturKlient = Messung.substring(0, Messung.indexOf("/"));
String LuftfeuchtigkeitKlient = Messung.substring(Messung.indexOf("/") + 1, Messung.length());
Seite += "<h2>Daten vom Klienten ...</h2>";
Seite += "<div class=\"farbigeBox\">";
Seite += "Temperatur: ";
Seite += TemperaturKlient;
Seite += "<br>";
Seite += "Luftfeuchtigkeit: ";
Seite += LuftfeuchtigkeitKlient;
Seite += "<br>";
Seite += "</div>";
// Messwerte des Servers ermitteln
// . durch , ersetzen
String TemperaturServer = String(dht.readTemperature());
TemperaturServer.replace(".", ",");
String LuftfeuchtigkeitServer = String(dht.readHumidity());
LuftfeuchtigkeitServer.replace(".", ",");
Seite += "<h2>Daten vom Server ...</h2>";
Seite += "<div class=\"farbigeBox\">";
Seite += "Temperatur: ";
Seite += TemperaturServer + "°C";
Seite += "<br>";
Seite += "Luftfeuchtigkeit: ";
Seite += LuftfeuchtigkeitServer + "%";
Seite += "</div>";
// Button aktualisieren
Seite += "<hr><button style=\"font-size:16pt; font-weight:bold;";
Seite += "background-color:#55A96B;";
Seite += "display:block; cursor:pointer;\">";
Seite += "</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 anzeigen
Server.send(200, "text/html", Seite);
}
void DatenHolen()
{
WiFiClient client;
// wenn Klient erfolgreich auf Port 80 verbunden wurde
// wenn nicht return -> neuer Versuch
if (!client.connect(host, 80)) return;
/*
GET-Anfrage senden
/Messung -> Adresse (URL) für die zu übermittelnden Werte
wird von den Klienten festgelegt
host -> IP-Adresse des 2. ESPs
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
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
// Messung enthält die vom 2. ESP übermittelten Daten
if(Daten != "")
{
Messung = Daten;
Serial.println(Daten);
}
}
}
Darstellung der GET-Anfrage im Seriellen Monitor
ESP als Host
// ESP8266
// #include "ESP8266WebServer.h"
// ESP32
#include "WebServer.h"
#include "WiFi.h"
#include "DHT.h"
// Pin des DHT-Sensors
int SENSOR_DHT = 19;
#define SensorTyp DHT22
// Sensor DHT einen Namen zuweisen
DHT dht(SENSOR_DHT, SensorTyp);
// ESP als AP
char Router[] = "ESPServer";
char Passwort[] = "espserver";
// IP des 2. ESPs
IPAddress ip(192, 168, 4, 2);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);
// ESP32
WebServer Server(80);
// ESP8266
// ESP8266WebServer Server(80);
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();
Serial.begin(9600);
// DHT starten
dht.begin();
}
void loop()
{
// auf Anfragen warten
Server.handleClient();
}
void SeiteBauen()
{
String Seite ="";
// Messwerte ermitteln
// . durch , ersetzen
String Temperatur = String(dht.readTemperature());
Temperatur.replace(".", ",");
String Luftfeuchtigkeit = String(dht.readHumidity());
Luftfeuchtigkeit.replace(".", ",");
// Seite zusammenbauen
// / Trennzeichen zwischen Temperatur und Luftfeuchtigkeit
Seite = Temperatur + "°C/";
Seite += Luftfeuchtigkeit + "%";
// Seite übermitteln
Server.send(200, "text/html", Seite);
}
Quellen
- Tablet/Smartphone von Pixaline
- Router/Laptop: openclipart.org
- ESP32 von fritzing
- Espressif WiFi-API
Letzte Aktualisierung: