HTML Buttons für den ESP Webserver - AZ-Delivery

Hallo und herzlich willkommen zu unserem heutigen Beitrag.

 

Nachdem es gestern um HTML und eckigen Klammern ging, wollen wir uns heute anhand einer kleinen Schaltung anschauen was man mit ein wenig HTML und einem kleinen Skript umsetzen kann.

Dazu benötigen wir folgende Bauteile:

Ein Microcontroller mit ESP8266-Chip wie z.B. das Amica V2
Ein Relais Modul wie unser 2-Relais Modul
Ein DC-DC Step-Up Modul, da der Amica nur 3,3V liefert, unser Relais aber 5V benötigt
Ein Breadboard mit Jumper-Kabel, wie z.B. unser beliebtes Set

Natürlich kann man das Relais-Modul auch direkt mit einem 5V versorgen, und das Step-Up Modul einsparen. Dies macht für ein fertiges Projekt in einem Gehäuse mehr Sinn, da mit dem gleichen Netzteil auch der Amica versorgt werden kann.

Wie man das Step-Up Modul verwendet und einstellt haben wir bereits in unserem Blog-Beitrag "MT3608 Step-Up DC-DC Spannungsregler" beschrieben.

Wir verbinden die Bauteile wie folgt:

Amica V2

MT3608

Relais

3V3

IN+

 

GND

IN-

 

 

OUT+

VCC

 

OUT-

GND

D1

 

IN1

D2

 

IN2

 

 

Im letzten Beitrag wurde schon darauf eingegangen wie wir den ESP mit einem bestehenden WLAN verbinden, und wie wir eine Anfrage vom Browser beantworten, inklusive der Ausgabe einer kleinen HTML-Datei.

Ich hatte bei einigen HTML-Tags erwähnt dass diese Seit HTML5 nicht mehr verwendet werden sollten. Bei modernen Webseiten wird die Gestaltung oftmals mittels Cascading Stylesheets (CSS) verwirklicht.

Bevor jetzt alle weglaufen mit der Furcht dass nun ein CSS-Kurs kommt, sei erwähnt dass es mittels CSS möglich ist schöne Buttons, Texte, Slider und Formulare zu gestalten.

Wenn man bei der Google Bildersuche nach "css buttons" sucht, tauchen einige Beispiele auf.

Nun geht es um die Umsetzung - welchen Code laden wir nun auf unseren ESP hoch?

Wir nehmen als Basis den Code aus dem Tutorial von https://randomnerdtutorials.com/esp8266-web-server/ und passen den Code an:

 

 

/*********
  Rui Santos
  Complete project details at http://randomnerdtutorials.com  
*********/

// Wir laden die uns schon bekannte WiFi Bibliothek
#include <ESP8266WiFi.h>

// Hier geben wir den WLAN Namen (SSID) und den Zugansschlüssel ein
const char* ssid     = "MeineFritzBox";
const char* password = "MeinWLANSchlüssel";

// Wir setzen den Webserver auf Port 80
WiFiServer server(80);

// Eine Variable um den HTTP Request zu speichern
String header;

// Hier wird der aktuelle Status des Relais festgehalten
String output5State = "off";
String output4State = "off";

// Die verwendeted GPIO Pins
// D1 = GPIO5 und D2 = GPIO4 - einfach bei Google nach "Amica Pinout" suchen  
const int output5 = 5;
const int output4 = 4;

void setup() {
  Serial.begin(115200);
  // Die definierten GPIO Pins als output definieren ...
  pinMode(output5, OUTPUT);
  pinMode(output4, OUTPUT);
  // ... und erstmal auf LOW setzen
  digitalWrite(output5, LOW);
  digitalWrite(output4, LOW);

  // Per WLAN mit dem Netzwerk verbinden
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Die IP vom Webserver auf dem seriellen Monitor ausgeben
  Serial.println("");
  Serial.println("WLAN verbunden.");
  Serial.println("IP Adresse: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Hört auf Anfragen von Clients

  if (client) {                             // Falls sich ein neuer Client verbindet,
    Serial.println("Neuer Client.");          // Ausgabe auf den seriellen Monitor
    String currentLine = "";                // erstelle einen String mit den eingehenden Daten vom Client
    while (client.connected()) {            // wiederholen so lange der Client verbunden ist
      if (client.available()) {             // Fall ein Byte zum lesen da ist,
        char c = client.read();             // lese das Byte, und dann
        Serial.write(c);                    // gebe es auf dem seriellen Monitor aus
        header += c;
        if (c == '\n') {                    // wenn das Byte eine Neue-Zeile Char ist
          // wenn die aktuelle Zeile leer ist, kamen 2 in folge.
          // dies ist das Ende der HTTP-Anfrage vom Client, also senden wir eine Antwort:
          if (currentLine.length() == 0) {
            // HTTP-Header fangen immer mit einem Response-Code an (z.B. HTTP/1.1 200 OK)
            // gefolgt vom Content-Type damit der Client weiss was folgt, gefolgt von einer Leerzeile:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // Hier werden die GPIO Pins ein- oder ausgeschaltet
            if (header.indexOf("GET /5/on") >= 0) {
              Serial.println("GPIO 5 on");
              output5State = "on";
              digitalWrite(output5, HIGH);
            } else if (header.indexOf("GET /5/off") >= 0) {
              Serial.println("GPIO 5 off");
              output5State = "off";
              digitalWrite(output5, LOW);
            } else if (header.indexOf("GET /4/on") >= 0) {
              Serial.println("GPIO 4 on");
              output4State = "on";
              digitalWrite(output4, HIGH);
            } else if (header.indexOf("GET /4/off") >= 0) {
              Serial.println("GPIO 4 off");
              output4State = "off";
              digitalWrite(output4, LOW);
            }
            
            // Hier wird nun die HTML Seite angezeigt:
            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:,\">");
            // Es folgen der CSS-Code um die Ein/Aus Buttons zu gestalten
            // Hier können Sie die Hintergrundfarge (background-color) und Schriftgröße (font-size) anpassen
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #333344; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #888899;}</style></head>");
            
            // Webseiten-Überschrift
            client.println("<body><h1>ESP8266 Web Server</h1>");
            
            // Zeige den aktuellen Status, und AN/AUS Buttons for GPIO 5  
            client.println("<p>GPIO 5 - State " + output5State + "</p>");
            // wenn output5State = off, zeige den EIN Button       
            if (output5State=="off") {
              client.println("<p><a href=\"/5/on\"><button class=\"button\">EIN</button></a></p>");
            } else {
              client.println("<p><a href=\"/5/off\"><button class=\"button button2\">AUS</button></a></p>");
            } 
               
            // Das gleiche für GPIO 4
            client.println("<p>GPIO 4 - State " + output4State + "</p>");
            // Wenn output4State = off, zeige den EIN Button       
            if (output4State=="off") {
              client.println("<p><a href=\"/4/on\"><button class=\"button\">EIN</button></a></p>");
            } else {
              client.println("<p><a href=\"/4/off\"><button class=\"button button2\">AUS</button></a></p>");
            }
            client.println("</body></html>");
            
            // Die HTTP-Antwort wird mit einer Leerzeile beendet
            client.println();
            // und wir verlassen mit einem break die Schleife
            break;
          } else { // falls eine neue Zeile kommt, lösche die aktuelle Zeile
            currentLine = "";
          }
        } else if (c != '\r') {  // wenn etwas kommt was kein Zeilenumbruch ist,
          currentLine += c;      // füge es am Ende von currentLine an
        }
      }
    }
    // Die Header-Variable für den nächsten Durchlauf löschen
    header = "";
    // Die Verbindung schließen
    client.stop();
    Serial.println("Client getrennt.");
    Serial.println("");
  }
}

 Wir laden den Code auf unseren Amica, und öffnen in der Arduino-IDE den Seriellen Monitor:

 

Als Nächstes geben wir im Browser, z.B. auf dem Handy, die IP Adresse des Servers ein. (Achtung, der PC oder das Smartphone müssen mit dem gleichen Netzwerk wie der ESP verbunden sein).

 

Nun können wir ganz einfach vom Smartphone (oder PC) aus die Relais schalten.

 

 

Und wer sich ein wenig im Internet umschaut kann auch schönere Buttons finden, wie z.B. diese:

 

Den HTML-Code und den CSS Code für diese Buttons gibt es bei http://jsfiddle.net/tovic/ve8mU/light/

 

Ich hoffe dieser Beitrag hat Ihnen einen Einblick in die Möglichkeiten des ESP Webservers gegeben.

Wenn Ihnen dieser Beitrag gefallen hat, würde ich mich über eine kurze Rückmeldung freuen. Schreiben Sie uns doch einfach ob für Sie das Thema SVG zur Anzeige von Balken und kleinen Vektorgrafiken mit dem ESP Webserver interessieren würde.

Ich wünsche Ihnen viel Spaß beim nachbauen, und verabschiede mich bis zum nächsten Artikel.

 

Esp-8266Projekte für fortgeschrittene

10 Kommentare

Andreas Wolter

Andreas Wolter

@Thomas Schultz: ab Zeile 60
if (client.available()) {
beginnt die aktualisierung der Webseite. Mein Vorschlag wäre, die Bedingung durch ein ODER zu erweitern, damit auf die Inputs reagiert werden kann. Folglich müsste man vorher die Inputs auslesen und falls sich diese geändert haben, müsste man dann in die Bedingung diese Änderung einbringen. Als Beispiel:
int inputA_new = 0;
int inputA_old = 0;

inputA_new = digitalRead(EINGANG);
if (client.available() || inputA_new != inputA_old) {
….
//zeige Werte aus Input A
}
inputA_old = inputA_new;

für zwei Eingänge wäre das dann wie folgt:
int inputA_new = 0;
int inputA_old = 0;
int inputB_new = 0;
int inputB_old = 0;

inputA_new = digitalRead(EINGANG_A);
inputB_new = digitalRead(EINGANG_B);
if (client.available() || inputA_new != inputA_old || inputB_new != inputB_old) {
….
//zeige Werte aus Input A
//zeige Werte aus Input B
}
inputA_old = inputA_new;
inputB_old = inputB_new;

@Georg: etwas spät, aber: der AsynchWebserver ist anders gelöst. eventuell hilft Ihnen das weiter: https://techtutorialsx.com/2018/01/01/esp8266-arduino-asynchronous-http-web-server/

Thomas Schultz

Thomas Schultz

Hallo und vielen Dank für dieses schöne Beispiel.
Ich habe es mal direkt für mein aktuelles Project benutzt.
Ich habe nur ein kleine Problem, zusätzlich würde ich gerne noch zwei
Kontaktausgänge eines anderen Moduls auslesen. Das auslesen ist kein
Problem, auch das anzeigen nicht… aber die Webseite wird im vorliegenden
ja nur bei Änderungen eines Relais neu aufgebaut.
Wie kann ich das auch mit zwei INPUTS bewerkstelligen?

Für entsprechende Hilfe wäre ich sehr dankbar
Thomas

Phil Phras

Phil Phras

Ich bin bei der IdeenSuche für eins meiner Projekte auf diesen Blog gestoßen und bin begeistert!
Ich habe auch in anderen Blogs hier gestöbert und möchte ein großes Lob aussprechen.

Hier werde ich StammLeser :-) Und wenn ich mal wieder eins meiner Projekte veröffentliche geb ich auf jeden Fall diese Seite hier an als Ideen- und CodeQuelle an.

Vielen Dank

georg

georg

hallo,
das thema ist inzwischen recht alt :-( , für mich aber noch aktuell…
habe versucht den code mit einem asyncwebserver zu kombinieren (die verwendung dieser art des webservers lässt sich aus anderen gründen nicht mehr ändern) – beim compileren wurde die kombination unter anderem mit – ‘class AsyncWebServer’ has no member named ‘available’ – quitiert…
Was kann ich da machen?
gruss

Thmas Nimpsch

Thmas Nimpsch

Hallo ,
Vielen Dank für dieses Beispiel, genau danach hab ich gesucht.
Gruß
Thomas Nimpsch

N1d45

N1d45

Schalter die sich automatisch aktualisieren währen nicht schlecht.

Sprich wenn ich von mehreren Geräten auf die Webseite zugreife. Zum Beispiel schalte ich mit dem Smartphone Kanal 1 ein, wird auf dem PC automatisch angezeigt das der Schalter 1 auch ein ist.

Oder das wenn ich per Taster Kanal 1 ein schalte, das auch auf der Webseite automatisch angezeigt wird das der Kanal 1 eingeschaltet ist.

Bisher muss man immer die Webseite neuladen, z.B. mit F5 um das aktuelle Ergebniss zu sehen.

Tobî

Tobî

an Herbert.

Versuche doch den Taster mal mit einem Interrupt aus.
Ich hoffe ich darf hier einen Link posten, wenn nicht:
Herbert suche mal auf deiner Suchmaschine deines Vertrauens nach: ESP8266 External Interrupt.

https://techtutorialsx.com/2016/12/11/esp8266-external-interrupts/

Herbert

Herbert

Toller Beitrag, soweit funktioniert auch alles.
Mein Problem ist das ich zusätzlich noch einen Hardware Taster einbauen wollte.
Der aber nicht funktioniert wenn der Client mit dem ESP8266 verbunden ist.
Ich vermute das Problem ist die while (client.connected() funktion. Die verhindert das auf die Tastereingabe parrallel zur Verbindung eines Client funktioniert.

Gibt es dafür eine Lösung? Und warum benötigt man eigentlich die while?

Chris

Chris

Hallo Markus,
wäre es möglich noch einen Slider zu integrieren, mit Bsp. Sketch?
LG

K. Dobler

K. Dobler

Hallo Markus,
dein Beispiel hat mir sehr geholfen.
Mit ihm habe ich des geschafft mein Garagentor vom Handy aus zu steuern.
Jetzt geht es nur noch um kleine Anpassungen und Verschönerungen.

Vielen Dank
Kurt Dobler

Kommentar hinterlassen

Alle Kommentare werden von einem Moderator vor der Veröffentlichung überprüft

Empfohlene Blogbeiträge

  1. ESP32 jetzt über den Boardverwalter installieren - AZ-Delivery
  2. Internet-Radio mit dem ESP32 - UPDATE - AZ-Delivery
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1 - AZ-Delivery
  4. ESP32 - das Multitalent - AZ-Delivery