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.
10 Kommentare
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
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
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
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
Hallo ,
Vielen Dank für dieses Beispiel, genau danach hab ich gesucht.
Gruß
Thomas Nimpsch
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î
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
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
Hallo Markus,
wäre es möglich noch einen Slider zu integrieren, mit Bsp. Sketch?
LG
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