Praxis

 

Praxis 17: ESP32 als Webserver

 

Benötigtes Material:

  • ESP32 Dev Modul mit USB-Kabel
  • Breadboard
  • zwei Kabelstück (männlich↔männlich)
  • drei Kabelstücke (weiblich↔männlich)
  • zwei Widerstände mit je 220 Ohm
  • je eine LED in rot und gelb

 

 

 

 

Der ESP32 kann über das integrierte WLAN-Modul auch Verbindung zu einem WLAN-Netz herstellen. Außerdem verfügt das Modul über ausreichend Speicher, um eine einfache Webseite zu hosten.

Als „Einstieg“ sollen sich zwei LEDs am ESP32 über eine Webseite schalten lassen.

#include <Arduino.h>
/* -------------------------------------
    Praxis 17
    ESP32-Webserver mit zwei LEDs
  -----------------------------------*/

#include <WiFi.h>
// WLAN Zugangsdaten (SSID & Kennwort)
const char* ssid = "Labornetz";
const char* password = "ITLabor2024!";
// Port für den Webserver
WiFiServer server(80);
// Variable für den Header-String bereitstellen
String header;
// Strings für den Zustand der LED GPIOs
String output26State = "aus";
String output27State = "aus";
// Festlegen der GPIO pins für die LEDs
const int output26 = 26;
const int output27 = 27;
// Aktuelle Zeit
unsigned long currentTime = millis();
// Letzte Zeit
unsigned long previousTime = 0;
// Festlegen der TimeOut Zeit (Hier: 2000ms = 2s)
const long timeoutTime = 2000;

void setup() {
  Serial.begin(115200);
  // Die LED-Pins auf Ausgang setzen
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Sicherstellen, dass die LEDs ausgeschaltet sind
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);
  // Versuchen mit dem WLAN-Netz zu verbinden
  Serial.print("Verbindung zu WLAN ");
  Serial.print(ssid);
  Serial.println(" aufbauen:");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Wenn die Verbindung steht, IP-Adresse ausgeben und Server starten
  Serial.println("");
  Serial.print("Verbunden mit ");
  Serial.println(ssid);
  Serial.print("IP Adresse: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Auf Anfragen hören
  if (client) {                             // Bei der Anfrage eines Clients
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("Neuer Client.");        // Wird dieser auf der Konsole angekündigt.
    String currentLine = "";
    while (client.connected() && currentTime - previousTime <= timeoutTime) {
                                            // Solange der Client verbunden ist
      currentTime = millis();
      if (client.available()) {      // wird geprüft, ob Daten von diesem kommen.
        char c = client.read();      // Diese werden gelesen und
        Serial.write(c);             // auf der seriellen Konsole ausgegeben.
        header += c;
        if (c == '\n') {             // Ist die Anfrage abgeschlossen
          if (currentLine.length() == 0) {  // Dem Client antworten
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
             // Hier wird die "Anfrage" des Clients ausgewertet:
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 an");
              output26State = "an";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 aus");
              output26State = "aus";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 an");
              output27State = "an";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 aus");
              output27State = "aus";
              digitalWrite(output27, LOW);
            }
            // Nun wird dem Client die angepasste/veränderte Webseite übermittelt
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            client.println("<body><h1>ESP32 Web Server</h1>");
            client.println("<h2>CPS an der BS Obernburg (Elter/Rink/Bayer)</h2>");
            client.println("<p>GPIO 26 - LED " + output26State + "</p>");
            if (output26State=="aus") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">AN</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">AUS</button></a></p>");
            }
            client.println("<p>GPIO 27 - LED " + output27State + "</p>");
            if (output27State=="aus") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">AN</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">AUS</button></a></p>");
            }
            client.println("</body></html>");
            client.println();
            break;
          } else { // Sollte ein einfacher Zeilenumbruch ankommen
            currentLine = "";
          }
        } else if (c != '\r') {  // Alle übrigen Zeichen werden
          currentLine += c;      // der Anfrage hinzugefügt
        }
      }
    }
    header = "";                 // Die Variable leeren
    client.stop();               // und die Verbindung trennen.
    Serial.println("Client getrennt.");
    Serial.println("");
  }
}

Zu Begin wird die Bibliothek „Wifi.h“ eingebunden #include<WiFi.h>(Zeile 7). Diese stellt eine Verwaltung des im ESP32 eingebauten WLAN-Moduls zur Verfügung.

In den folgenden Zeilen (9 und 10) sind die Zugangsdaten zum WLAN-Netz hinterlegt.

Zeile 12 legt den TCP/IP Port für den Webserver fest.

In den Zeilen 16 und 17 werden die Variablen für die LED-Zustände angelegt und mit den Ausgangswerten vorbelegt. In den Zeilen 19 und 20 werden die GPIOs für die beiden LEDs festgelegt.

Die Zeilen 22, 24 und 26 legen Variablen für das Timing fest.

In den while-Schleife im setup-Teil (Zeilen 40 bis 43) wird versucht eine Verbindung zum WLAN-Netz herzustellen. Danach wird im Erfolgsfall die IP-Adresse über den seriellen Monitor ausgegeben.

Mit server.begin(); (Zeile 51) wird der Webserverdienst gestartet.

Im loop-Teil wird geprüft, ob eine neue Anfrage an den Server vorliegt (Zeile 55 und 56). Solange keine Anfragen vorliegen, passiert nichts weiter.

Die Zeilen 57 bis 63 sorgen hauptsächlich dafür, dass eine Anfrage nach spätestens zwei Sekunden beendet wird oder wenn der Client keine Anfrage mehr sendet.

Solange Zeichen kommen (Zeile 64), werden diese Zeichen für Zeichen zu dem String header hinzugefügt (Zeilen 65 bis 67 und 118 bis 123).

Wenn die Anfrage vollständig übernommen wurde (Zeile 66) wird zunächst dem Client geantwortet (Zeilen 69 bis 73). Anschließend wird die Anfrage ausgewertet. Wenn einer der Buttons betätigt wurde, wird die entsprechenden LED umgeschaltet und die Variablen für deren Zustand neu gesetzt (Zeilen 74 bis 91).

Zum Schluss wird die Webseite an den Client gesendet (Zeilen 93 bis 115) und die Verbindung beendet (Zeile 126).

 

Aufgaben

  1. Bauen Sie die die Schaltung mit den LEDs auf einem Breadboard auf.
    Beachten Sie dabei die Polung der LEDs.
  2. Geben Sie den Sketch in die IDE ein. Kompilieren und Übertragen Sie die Daten auf den ESP32. Achten Sie darauf, dass man beim ESP32 das Programmieren des Speichers durch Drücken des BOOT-Knopfes bestätigen muss.
  3. Öffnen Sie den seriellen Monitor bzw. Das Terminal und prüfen Sie, ob eine Verbindung mit dem WLAN-Netz aufgebaut wurde:
    Sollten sich, statt einer sinnvollen Ausgabe, seltsame Zeichen aneinanderfügen, muss die Baudrate gegebenenfalls noch auf 115200 Baud eingestellt werden. Unter VS-Code erhalten Sie das Terminal über das „Stecker“-Symbol in der PlatformIO-Menüleiste. Die Baudrate können Sie in der „platformio.ini“ des Projekts eintragen.
  4. Wurde die Verbindung erfolgreich aufgebaut, starten Sie einen Webbrowser und geben die IP-Adresse des ESP32 ein:

    Betrachten Sie auch die Ausgabe auf der seriellen Konsole:
  5. Sollte die Webseite nicht angezeigt werden kann man zunächst versuchen das Timeout (Zeile 26) zu erhöhen.
  6. Experimentieren Sie mit Änderungen am Layout der Webseite.