Gute Beispiele für Webserver (Nano) ESP32 gesucht

Für ein Projekt möchte ich einige Einstell-Parameter, die mit der preferences.h fest gespeichert sind, im lfd. Betrieb mit Hilfe eines kleines Webservers in einem Browser ändern und damit dann das Programm aktualisieren.

Einige 0/1-Parameter sind dabei (z.B. via Ein-/Aus-Schalter-Symbole), einige Uhrzeiten und weitere numerische Einstellfelder, für die sich Slider oder Felder mit Rauf-/Runter-Pfeilen gut eignen würden.
Ggf. noch Textfelder für SSID und Router-Passwort etc.

Wo finde ich gute Beispiele, wie man so etwas angeht, damit es halbwegs professionell aussieht?

Das hier habe ich z.B. schon angetestet:

https://github.com/s00500/ESPUI
https://werner.rothschopf.net/microcontroller/202108_esp_generic_webserver_en.htm
https://fipsok.de/

Bekomme aber leider nicht alle Sketche zum Laufen.

Wie arbeitet man sich am besten in html und CSS bzw. JSON ein (ist für mich weitestgehend Neuland)?

der zweite Link ist von mir - bekommst den zu laufen? Wenn nicht - was geht nicht?

Deine Webserver Mini Version läuft, die generic Variante hat gestern auch schon funktioniert. Heute jedoch nicht mehr. Habe dazwischen auf die IDE 2.2.0 upgedated.

Wenn ich wieder am Rechner bin, kann ich mal die Fehler posten.

Kannst du denn "Gute Beispiele" genauer definieren ?
Die beiden (2 + 3) Links von dir sind doch schon sehr gut.
Evtl. liegt das Problem ja auch an der neuen IDE-Version.

Bei Verwendung des generic sketches unter IDE 1.8.19 kommt (#define USE_BOARD 1):

In file included from C:\Users\Martin\Documents\Arduino\esp_webserver_generic\config.h:10,
                 from C:\Users\Martin\Documents\Arduino\esp_webserver_generic\esp_webserver_generic.ino:81:
config1.h:15:28: error: invalid initialization of reference of type 'HardwareSerial&' from expression of type 'USBCDC'
 HardwareSerial &Terminal = Serial;            // if you would need debug messages on another Serial, you could define it
                            ^~~~~~

exit status 1
invalid initialization of reference of type 'HardwareSerial&' from expression of type 'USBCDC'

Sketch, angemeckerte Stelle ist im Tab "config1.h", relativ weit oben:

/* *******************************************************************
   Example board setting
   use this as base for your own setting
   Controller:   should be compatible with ESP32 and ESP8266
   Description:  Describe the board you have

   Amazon:       paste a link where you have bought it or a link to a datasheet
   Aliexpress:

  ********************************************************************/

#pragma once
#if USE_BOARD == 1                            // this is an ID for the configuration
#define TXT_BOARDNAME "Generic ESP Webserver" // the name of the board on webgui and Serial
HardwareSerial &Terminal = Serial;            // if you would need debug messages on another Serial, you could define it

// assign pins to arrays:
// Pins, which should be readed
//Pin inputPin[] {
//  // the pin    a name for the website
//  {0,    "IO00"},   // the NodeMCU has a flash button
//  {13,   "IO13"}, 
//  {14,   "IO14"},    
//  {15,   "IO39"}
//};
// if don't need to read input pins, delete the above structure and activate this line
#define NO_INPUTPIN

// Pins, which can be switched on or off
OutputPin outputPin[] {
  // pin  a name  LOW active or HIGH active
  {14,    "D14", LOW},    // on some ESP8266 there is a blue LED on the ESP
  {15,    "D15", LOW},
  {16,    "D16", LOW} 
};
// if you don't need output pins to switch on/off delte the above structure and actviate the following line
// #define NO_OUTPUTPIN

// Pins, which can be switched on or off
// the ESP32 can use a maximum of 16 pins for PWM
//PWMPin pwmPin[] {
//  //pin   a name  a PWM value
//  {16,   "IO16", 1023},    // on a NodeMCU there is a LED (invers)  
//  {13,   "IO13", 511},
//  {12,   "IO12", 0}  
//};

// if you don't need pins with pwm outputs, delete the above structure and activate the following line
 #define NO_PWMPIN

// if you don't need shift registers use this define
#define NO_SHIFTPIN

const byte wifiActivityPin = 2;   // if you want to indicate Wifi activity - set to 255 if activity LED is not needed
#endif

Unter IDE 2.2.0 das gleiche Bild.

Was muss ich tun, damit ich Meldungen im seriellen Monitor bekomme und der Sketch kompiliert?

Mit "gut" meine ich einfache, nachvollziehbare Beispiele, gerade auch bezgl. html, CSS usw. Also warum sieht der Befehl so und so aus und wie beeinflusst das den Aufbau der Website.

So bleibt nur trial & error und Ausprobieren.

Wie muss ich z.B. diese Seite mit Input füttern: https://validator.w3.org
Wahrscheinlich mit dem nackten html, also ohne die "message = ..."-Befehle, oder?

Falls noch nicht getan, aktiviere mal die
show verbose output during compiliation
und ausführliche Compiler Warnings.
Und dann die GESAMTE Fehlermeldung hier posten.
Welchen ESP Core Version hast du genau installiert?
Mit welcher Boardeinstellung kompilierst du den ESP32?

ja klar - nur den HTML quelltext den du im Browser bekommst.

1 Like

Und das sind die gezeigten nicht ?
Das wundert mich jetzt aber. Darin geht es doch erstmal um die "einfache" Programmierung der ESP-Controller. Für HTML, CSS usw. gibt wieder andere Foren die dir da helfen können.
Oder du stellst hier gezielt Fragen zu den Problemen, die bei dir (den Projekten) auftauchen.

Sagen wir so,
Das Themengebiet ist eben SEHR umfangreich.
Einerseits will der ESP Server in C++ programmiert werden,
dann soll man noch HTML5 valide hinbekommen,
CSS damit es was gleich schaut
JavaScript damit es noch besser bedienbar wird (obwohl ich ja der Fraktion angehöre, dass es auch ohne JS gehen muss),
FetchAPI zum automatisieren.

Jedes Thema für sich füllt Bücher ... da reicht ein 30 min Tutorial für alle Themen halt nicht wirklich. Egal von welcher Seite man kommt.

Auf der anderen Seite ist dann dieses ESPUI. Das kann man sich ansehen.
Hab ich für mich auch gemacht.
Muss dann jeder für sich entscheiden was langfristig für ihn mehr bringt.

3 Likes

Ich empfehle dir als Selber-Einsteiger diese „Standardwerke“ :slight_smile:

https://werner.rothschopf.net/201809_arduino_esp8266_server_client_0.htm

Viel lesen musst Du. Und ausprobieren.

Es lohnt sich :wink:

EDIT Und natürlich w3schools, fiddle, iopen und selfhtml

2 Likes

Verwendet wird ein Original Nano ESP32 Board, Core Version 2.0.11, kompiliert mit Boardeinstellung "Arduino Nano ESP32 auf COM7":

Arduino: 1.8.19 (Windows 10), Board: "Arduino Nano ESP32"
In file included from C:\Users\Martin\Documents\Arduino\esp_webserver_generic\config.h:10,

                 from C:\Users\Martin\Documents\Arduino\esp_webserver_generic\esp_webserver_generic.ino:81:

config1.h:15:28: error: invalid initialization of reference of type 'HardwareSerial&' from expression of type 'USBCDC'

 HardwareSerial &Terminal = Serial;            // if you would need debug messages on another Serial, you could define it

                            ^~~~~~

Mehrere Bibliotheken wurden für "WiFi.h" gefunden

 Benutzt: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\WiFi

 Nicht benutzt: C:\Program Files (x86)\Arduino\libraries\WiFi

Bibliothek WiFi in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\WiFi  wird verwendet

Bibliothek WebServer in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\WebServer  wird verwendet

Bibliothek ESPmDNS in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\ESPmDNS  wird verwendet

Bibliothek ArduinoOTA in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\ArduinoOTA  wird verwendet

Bibliothek Update in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\Update  wird verwendet

Bibliothek FS in Version 2.0.0 im Ordner: C:\Users\Martin\AppData\Local\Arduino15\packages\arduino\hardware\esp32\2.0.11\libraries\FS  wird verwendet

exit status 1

invalid initialization of reference of type 'HardwareSerial&' from expression of type 'USBCDC'

wenn es schon mal funktioniert hat, könntest du folgendes probieren

  • z.B. für das Wemos Lolin32 Board kompilieren - geht/geht nicht?
  • downgraden auf ESP Core 2.0.6 - geht/geht nicht
  • HardwareSerial auf USBCDC ändern - geht/geht nicht
1 Like
  • z.B. für das Wemos Lolin32 Board kompilieren - geht
  • downgraden auf ESP Core 2.0.6 - geht nicht (alte Versionen werden nicht mehr vom Boardverwalter angeboten)
  • HardwareSerial auf USBCDC ändern --> was müsste ich hierfür tun?

schön, was Board individuelles, wtf.

stochern im Nebel:

 USBCDC &Terminal = Serial;            // if you would need debug messages on another Serial, you could define it

edit: Stream geht leider nicht

und so als vorletzte Variante

 #define Terminal Serial           // if you would need debug messages on another Serial, you could define it

Übrigens der Grund warum ich hier eine Referenz verwende ist, dass das H801 Board nur einen Ausgang von Serial1 anbietet und ich daher über die config Dateien die konkrete Serielle Schnittstelle festlegen will. Mit dem Webserver selber hat es eigentlich nichts zu tun.

H801 PWM RGBW Wifi Dimmer - Programming the internal ESP8266 module (rothschopf.net)

Die USBCDC- und die #define-Variante funktionieren jetzt, vielen Dank!

Wobei ich vorhin noch mehrere DFU USB Errors hatte, gestern ebenfalls, da hatte ich die #define-Variante schon mal getestet; nach einmal IDE neustarten und den Nano ein-/ausstöpseln und vorher einen anderen Sketch hochladen ging es wieder.

Danke auch für Links, da habe ich jetzt genug Lektüre ...

Frage, welchen Anschluss hast du da eigentlich ausgewählt?
eine COM oder DFU?

Hallo,
die Beispiele zu der PDF gibts hier

In der IDE 1 habe ich ich noch keinen DFU gesehen.

In der 2er wird es angezeigt, ich habe aber immer den COM-Port gewählt.

Bin nun etwas weitergekommen und aktuell baut der Nano_ESP32 folgende Webseite auf, Basis war der sketch von Werner:

Nach Drücken des Speichern-Buttons kommt eine weitere Seite:

Ganz schön viel Aufwand, aber das Ergebnis kann sich sehen lassen!

2 Fragen hätte ich noch dazu:

Erstens, ich habe vor, diese Einstellungen in mein Wordclock-Projekt zu integrieren, um sie über einen Browser machen zu können. Auf Knopfdruck soll der WLAN-Zugriff ermöglicht werden (ich hole die NTP-Zeit nur alle paar Stunden, dazwischen schaltet ich das ESP-WLAN aus). Dann kann man die Einstellungen vornehmen und an die Uhr übertragen. Anschließend soll das WLAN wieder deaktiviert werden.

Macht man das eher im Access Point Modus oder im Stationsmodus? Wie teile ich dem User die IP-Adresse mit? Oder macht eine feste IP Sinn?

Wie erkenne ich im sketch, dass der User den Browser einfach geschlossen hat und keine Einstellungen ändern will? Zeitbegrenzung?

Momentan wird in der loop() lfd. server.handleClient () aufgerufen, um die Webseite auszuwerten. Wenn ein User die Einstellungen gespeichert hat, müsste ich einfach ein Flag setzen, damit die Webseite dann ggf. nicht mehr ausgewertet wird, da die Einstellungen erledigt sind, oder?

Zweitens, auf der Webseite verwende ich slider, um Werte einzustellen. Der jeweils aktuelle Wert wird rechts daneben durch ein paar Befehle dargestellt. Diese habe ich hier eingebaut:

//--------------------------------------------------------------------------------------------------------------------
void
handleJs ()
//--------------------------------------------------------------------------------------------------------------------
{
    // Output: a fetch API / JavaScript
    // a function in the JavaScript uses fetch API to request a JSON file from the webserver and updates the values on the page if the object names and ID are the same
    String message;
    // message += F ( "const url ='json';\n");
    // clang-format off
    message += R"rawliteral(var slider_T = document.getElementById("Range_T");
var output_T = document.getElementById("Vol_t");
output_T.innerHTML = slider_T.value;

slider_T.oninput = function() {output_T.innerHTML = this.value}

var slider_C = document.getElementById("Range_C");
var output_C = document.getElementById("Vol_c");
output_C.innerHTML = slider_C.value;

slider_C.oninput = function() {output_C.innerHTML = this.value}
  
var slider_B = document.getElementById("Range_B");
var output_B = document.getElementById("bri");
output_B.innerHTML = slider_B.value;

slider_B.oninput = function() {output_B.innerHTML = this.value})rawliteral";
    // clang-format on

    server.send ( 200, "text/javascript", message );
}

Die Routine wird über

   server.on ( "/j.js", handleJs );                      // javscript based on fetch API to update the page

aufgerufen, Was aber nicht funktioniert.
Erst wenn ich die Befehle direkt in die html-Seite mit einbaue, geht es. Was mache ich hier falsch?

das liegt daran was man haben will.
Gehst du davon aus, dass der User zu diesem Zeitpunkt in einem Netzwerk angemeldet ist (zu hause `? eher ja?) dann würde ich die Uhr auch ins Netzwerk anmelden.

Wenn die Uhr irgendwo im freien hängt, und man annehmen kann dass der User nicht im Wifi ist dann macht der AP sinn.

ja könntest du nutzen. mach auf der Homepage einen Fetch API intervall von ein paar Sekunden, dann weist du am server wenn nach 10 sek nichts mehr kommt, der User ist weg.

1 Like