Hello and welcome to our today.
After yesterday's topic was HTML and square brackets, today we want to take a look at what can be done with a little HTML and a small script.
For this we need the following components:
A microcontroller with ESP8266 chip such as Amica V2
A relay module like our 2-relay module
A DC-DC Step-Up module, since the Amica only delivers 3.3V, but our relay needs 5V
A breakboard with jumper cable, such as our popular set
Of course you can also supply the relay module directly with a 5V, and save the step-up module. This makes more sense for a finished project in a case, because the same power supply can also be used to power the Amica.
How to use and set the step-up module we already have in our blog post "MT3608 Step-up DC-DC voltage controller"described.
We connect the components as follows:
Amica V2 |
MT3608 |
Relay |
3V3 |
IN+ |
|
GND |
IN- |
|
|
OUT+ |
VCC |
|
OUT- |
GND |
D1 |
|
IN1 |
D2 |
|
IN 2 |
In the last post we already talked about how we connect the ESP to an existing WLAN and how we answer a request from the browser, including the output of a small HTML file.
I mentioned with some HTML tags that they should not be used since HTML5. Modern web pages are often designed using Cascading Stylesheets (CSS).
Before everyone now runs away with the fear that now a CSS course comes, it should be mentioned that it is possible by means of CSS to design beautiful buttons, texts, sliders and forms.
If you search for "css buttons" on Google Image Search, you will find some examples.
Now it's about the implementation - which code do we upload to our ESP?
We take the code from the tutorial of https://randomnerdtutorials.com/esp8266-web-server/ as a basis and adapt the code:
/********* 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(""); } }
We invite the code to our Amica and open the serial monitor in the Arduino IDE:
Next we enter the IP address of the server in the browser, e.g. on the cell phone. (Attention, the PC or smartphone must be connected to the same network as the ESP).
Now we can easily switch the relays from the smartphone (or PC).
And if you look around a little on the Internet, you can also find more beautiful buttons, such as this:
The HTML code and the CSS code for these buttons can be found at http://jsfiddle.net/tovic/ve8mU/light/
I hope this post gave you an insight into the possibilities of the ESP web server.
If you liked this article, I would be glad about a short feedback. Just write us if you are interested in the topic SVG for displaying bars and small vector graphics with the ESP web server.
I wish you a lot of fun, and say goodbye until the next article.
10 comments
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