Zisterne 3.0 Web Server + SPIFFS

68 Kommentare
Zisterne 3.0 Web Server + SPIFFS

In meinem ersten Beitrag für die Zisterne (Wasserstandsmessung), verwende ich Batterie Bilder für den Füllstand der Zisterne. Hier werde ich immer wieder gefragt wie die Bilder angezeigt werden können.

Da nicht jeder eine Webseite besitzt oder sich extra dafür eine anschaffen will (Kostet ja auch Geld), hab ich hier eine andere Lösung für euch.


Inhaltsverzeichnis

  1. Installation ESP8266 in der Arduino IDE
  2. Filesystem Uploader Plugin (SPIFFS)
  3. Installation der Librarys
  4. Welche Bauteile werden benötigt.
  5. Schema
  6. Der Programmcode
  7. Der HTML Code
  8. Der CSS Code
  9. Upload Code und Datein


Der ESP8266 egal welche Version, haben einen Speicherplatz auf dem Chip wo man Daten ablegen und abrufen kann. Könne Ihr hier nachlesen. https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html

Das werden wir hier benutzen um die Bilder und die HTML Seite dort abzulegen.

|--------------|-------|---------------|--|--|--|--|--|
^              ^       ^               ^     ^
Sketch    OTA update   File system   EEPROM  WiFi config (SDK)

Board Flash chip size, bytes File system size, bytes
Generic module 512k 64k, 128k
Generic module 1M 64k, 128k, 256k, 512k
Generic module 2M 1M
Generic module 4M 1M, 2M, 3M
Adafruit HUZZAH 4M 1M, 2M, 3M
ESPresso Lite 1.0 4M 1M, 2M, 3M
ESPresso Lite 2.0 4M 1M, 2M, 3M
NodeMCU 0.9 4M 1M, 2M, 3M
NodeMCU 1.0 4M 1M, 2M, 3M
Olimex MOD-WIFI-ESP8266(-DEV) 2M 1M
SparkFun Thing 512k 64k
SweetPea ESP-210 4M 1M, 2M, 3M
WeMos D1 R1, R2 & mini 4M 1M, 2M, 3M
ESPDuino 4M 1M, 2M, 3M
WiFiduino 4M 1M, 2M, 3M


Was wird für das Projekt benötigt.

1. Installation ESP8266 in der Arduino IDE

Um den EPS8266 in der Arduino IDE verwenden zu können, muss dieser erst installiert werden. Wie das geht habe ich in diesem Blogbeitrag schon einmal erklärt.



2. Filesystem Uploader Plugin (SPIFFS)

Mit diesem Plugin können Daten bequem per Knopfdrück auf den EPS8266 (SPIFFS) geladen werden.Zunächst müsst Ihr euch das Plugin von Github herunterladen. https://github.com/esp8266/arduino-esp8266fs-plugin/releases/tag/0.5.0

Den Inhalt der ZIP Datei kopiert ihr in den Tools Ordner.
C:\Program Files (x86)\Arduino\tools
oder in diesen, das ist egal.
C:\Users\???\Documents\Arduino\tools

Wenn das erledigt ist müsst Ihr die Arduino IDE neu starten. Dann sollte das Plugin hier angezeigt werden.




3. Installation der Librarys

Ihr braucht hier die Librarys ESPAsyncWebServer und ESPAsyncTCP.

ESPAsyncWebServer


ESPAsyncTCP


Die Zip Datei entpackt Ihr in den Library Ordner C:\Users\???\Documents\Arduino\libraries jenachdem wo er bei euch liegt.

ODER / ALTERNATIV

Die Import Funktion der Arduino IDE nutzen.




Welche Bauteile werden benötigt.

Beim ESP spielt es keine Rolle welches Modell genommen wird.

1x D1 mini ESP8266 ESP-12 - https://ap-url.de/d1mini
1x Ultraschallentfernungsmesser AJ-SR04M / JSN-SR04T Wasserdicht - https://ap-url.de/jsnsr04t



Schema

Alternativ zu der 5 Volt Spannungsversorgung kann auch die 3,3 Volt genommen werden. Der D1 mini verträgt nur 3,3 Volt an den Eingängen. Der Ultraschallsensor gibt aber keine 5 Volt am Echo Ausgang raus.

Der Programmcode

#include <esp8266wifi.h>
#include <espasynctcp.h>
#include <espasyncwebserver.h>
#include <fs.h>

const char* ssid = "DEIN WLAN";
const char* password = "DEIN PASSWORT";

AsyncWebServer server(80);

char* Bild = "";

int trigger = 12;
int echo = 13;
long dauer = 0;

long entfernung = 0;
long Liter = 0;

//Berechnung der Liter für die Webseite
String getLiter() {
  digitalWrite(trigger, LOW);
  delay(5);
  digitalWrite(trigger, HIGH);
  delay(10);
  digitalWrite(trigger, LOW);
  dauer = pulseIn(echo, HIGH);
  // Prüfen ob Messwert zwischen 200cm und 0cm liegt
  entfernung = (dauer / 2) / 29.1;
    if (entfernung >= 200 || entfernung <= 0)
  {
    entfernung = 0;
  }
  else
  {
    Liter = 199 - entfernung;
    Liter = Liter * 84.7457;
  }
  Serial.println(Liter);
  return String(Liter);
}

//Auswertung wann welches Bild angezeigt werden soll
String getBild() {
  if (Liter >= 0 && Liter <= 1833)
  {
    Bild = "/bat_emty.jpg";
  }
  else if (Liter >= 1833 && Liter <= 3666)
  {
    Bild = "/bat_1.jpg";
  }
  else if (Liter >= 3666 && Liter <= 5500)
  {
    Bild = "/bat_2.jpg";
  }
  else if (Liter >= 5500 && Liter <= 7332)
  {
    Bild = "/bat_3.jpg";
  }
  else if (Liter >= 7332 && Liter <= 9165)
  {
    Bild = "/bat_4.jpg";
  }
  else if (Liter >= 9165 && Liter <= 16000)
  {
    Bild = "/bat_full.jpg";
  }
  Serial.println(Bild);
  return String(Bild);
}


// Platzhalter im HTML Code
String colldata(const String& var) {
  Serial.println(var);
  if (var == "LITER") {
    return getLiter();
  }
}

void setup() {
  Serial.begin(115200);

  // Starte SPIFFS
  if (!SPIFFS.begin()) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print Local IP Address
  Serial.println(WiFi.localIP());

  // Webseite Laden
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/index.html", String(), false, colldata);
  });

  // CSS Datei Laden
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, "/style.css", "text/css");
  });

  // Liter an Webseite übergeben
  server.on("/Liter", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send_P(200, "text/plain", getLiter().c_str());
  });
  // Bild an Webseite übergeben
  server.on("/bat", HTTP_GET, [](AsyncWebServerRequest * request) {
    request->send(SPIFFS, getBild().c_str(), "image/jpg");
  });

  // Start server
  server.begin();
}

void loop() {

}

Funktionsweise

Als erstes werden die Librarys inkludiert.

#include &>t;ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <FS.h>

Für das WLAN werden die Zugangsdaten benötigt und der Web Server wird mit dem Port 80 erstellt.

const char* ssid = "DEIN WLAN";
const char* password = "DEIN PASSWORT";

AsyncWebServer server(80);

Definieren der Variablen (char, int und long). char* Bild  speichert die Bildinformation, int trigger und echo sind für den Ultraschallsensor Zuständig. Der long entfernung gibt den die gemessene Entfernung des Ultraschallsensors wieder und der long Liter ist für die Berechnung der Literzahl da.

char* Bild = "";

int trigger = 12;
int echo = 13;
long dauer = 0;

long entfernung = 0;
long Liter = 0;

Die Berechnung des Volumen:

Hier werden 2 Funktionen erstellt (getLiter und getBild) die einmal den Sensorwert als LONG zurück gibt und einmal den Bildname als CHAR zurück gibt.

//Berechnung der Liter für die Webseite
String getLiter() {
  digitalWrite(trigger, LOW);
  delay(5);
  digitalWrite(trigger, HIGH);
  delay(10);
  digitalWrite(trigger, LOW);
  dauer = pulseIn(echo, HIGH);
  // Prüfen ob Messwert zwischen 200cm und 0cm liegt
  entfernung = (dauer / 2) / 29.1;
    if (entfernung >= 200 || entfernung <= 0)
  {
    entfernung = 0;
  }
  else
  {
    Liter = 199 - entfernung;
    Liter = Liter * 84.7457;
  }
  Serial.println(Liter);
  return String(Liter);
}

Meine Zisterne fast 10000 Liter. Die 199 cm ist die Enfternung vom Sensor bis zum Boden der Zisterne. Jetzt brauchen wir den Multiplikator, die 100% Füllstand sind bei mir bei 118 cm erreicht, also 10000/118=84,7457.
Das ist nun der Multiplikator aus der Sketch.
    Liter = 199 - entfernung;
    Liter = Liter * 84.7457;



Die Funktion colldata() weist dem Platzhalter in der HTML Datei (%LITER%) den Wert zu.

// Platzhalter im HTML Code
String colldata(const String& var) {
  Serial.println(var);
  if (var == "LITER") {
    return getLiter();
  }
}

Mit den server.on Befehle werden die Daten wie index.html, style.css und die Werte in die Weitseite gepackt und auf dem SPIFFS gelesen.
Man könnte jetzt die Daten auch einzeln abrufen wie zu Beispiel http://ipadresse/Liter dann bekommt man hier die Literzahl angezeigt.

// Webseite Laden
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send(SPIFFS, "/index.html", String(), false, colldata);
});

// CSS Datei Laden
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send(SPIFFS, "/style.css", "text/css");
});

// Liter an Webseite übergeben
server.on("/Liter", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send_P(200, "text/plain", getLiter().c_str());
});
// Bild an Webseite übergeben
server.on("/bat", HTTP_GET, [](AsyncWebServerRequest * request) {
  request->send(SPIFFS, getBild().c_str(), "image/jpg");
});



Der HTML Code

<!DOCTYPE html>
<!--
Projekt Details im Blog https://arduino-projekte.info
-->
<html>
<head>
<title>Zisterne 3.0</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="refresh" content="5">
<link rel="icon" href="data:,">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>Zisterne 3.0</h1>
<p>
<span id="Liter">%LITER%</span>
<span>Liter</span>
</p>
<p><img src="/bat"></p>
</body>
</html>

Die Webseite wird über die IP Adresse des EPS8266 aufgerufen. Diese könnt Ihr über den Seriellen Monitor abrufen, oder über euren WLAN Router.



Hier könnt Ihr einstellen in welchen Intervall die Webseite aktualisiert werden soll. In diesem Fall sind es 5 sekunden.

<meta http-equiv="refresh" content="5">

Der %LITER% dient hier als Platzhalter und wird vom ESP8266 über den Sketch beschrieben. Hier wird die Liter Anzahl übergeben. Der "/bat" ist ebenfalls der Char String der dann von ESP beschrieben und das Bild (Batterie) übergeben wird.

<p><span id="Liter">%LITER%</span>
    <span class="label">Liter</span>
</p>
<p><img decoding="async" src="data:image/svg+xml,%3Csvg%20xmlns='http://
www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E" data-lazy-src="/bat"><noscript><img decoding="async" src="/bat"></noscript></p>



Der CSS Code

CSS wird verwenden um Webseite von der Darstellung zu verändern. Alles was Schriftarten, Schriftgörßen, Farben und so weiter angeht.

/***
  Projekt Details im Blog https://arduino-projekte.info
***/
html {
  font-family: Arial;
  display: inline-block;
  margin: 0px auto;
  text-align: center;
}
h1 {
  font-size: 40px;
  color: #4054b2;
}
p {
  font-size: 30px;
}
.label {
  font-size: 30px;
  vertical-align:middle;
  padding-bottom: 5px;
}



Upload Code und Datein

  • Sketch -> Sketch Ordner anzeigen, und erstellte einen Ordner Names data. In diese Ordner packt Ihr eure Daten wie Bilder, HTML und CSS Datein.
  • Werkzeuge -> Board, wählt euer ESP8266 Board aus was Ihr benutzt.
  • Dann geht Ihr auf Werkzeuge -> Flash size and select 4M (FS:1MB) es kann hier auch stehen 4M (1M SPIFFS).

Wenn der Sketch erfolgreich hochgeladen wurde, müssen nun noch die Daten auf den SPIFFS geladen werden.

Dateisystem für SPIFFS upload.

Um das Upload Tool für das SPIFFS nutzen zu kommen müssen die Daten (Bilder, HTML-Datein usw.) im Sketch Ordern mit abgelegt werden. Dazu im Sketch Ordner eine Ordner Names data erstellen und dort die Daten ablegen.

Sketch Ordner

Data Ordner


Werkzeug -> ESP8266 Sketch Data Uoload


Wichtig Ihr müsst etwas warten bis die Daten hochgeladen sind. Wenn im Ausgabefenster die 100% angezeigt werden ist er noch nicht fertig. Ihr muss auf das "Leaving... Hard resetting via RTS pin..." warten.

noch nicht fertig
fertig



Hier könnt Ihr euch den Sketch runterladen.

Download Sketch + Data (30kb .zip)


Folgende Bauteile wurden verwendet:

1x D1 mini ESP8266 ESP-12 - https://ap-url.de/d1mini
1x Ultraschallentfernungsmesser AJ-SR04M / JSN-SR04T Wasserdicht - https://ap-url.de/jsnsr04t
ESP8266 Projekte ultraschallsensor Zisterne Füllstandsanzeige

68 Kommentare

Hallo,
gucke mal bitte welche ESP8266 Version du in der Arduino IDE installiert hast. Unter Werkzeuge -> Board -> Boradverwalter und dann nach ESP8266 suchen. Hier bitte die Version 3.0 installieren. Es gab bei einer Version Probleme mit dem Code.
Gruß
Tobias

arduino projekte

Habe leider das selbe Problem.

MagicSven

Danke für das tolle Projekt.
Leider bekomme ich beim compilieren deines Codes einen Fehler:

Zeile 80:

conrtrol reaches end of non-void function (-Werror=return-type)
exit status 1

MagicSven

Hallo Engelbert,

zum 1. Thema. Das gleiche Problem habe ich mit meiner Regentonne auch. Das muss daran liegen, das der Raum geschlossen ist. Bei meiner Zisterne (diese hat Löcher im Deckel) gibt es das Problem nicht. Vielleicht liegt es auch an der Form. So richtig konnte ich das noch nicht herausfinden, bzw. testen.

Zum 2. Thema. Leider hat der MRK keinen externen Wifi Anschluss. Entweder du versuchst eine Externe Antenne irgendwie anzubringen oder muss deinen Code so auslegen, das er ein Reconnect durchführt. Es gibt das den Wifi Status den man abfragen kann.

arduino projekte

Servus,
danke – ich bin froh, dass ich die Seite gefunden habe. Zu meiner Aufgabenstellung: ich habe eine Bewässerung gebaut, bei der ich den Füllstand von 2x IBC Tanks messen will. Dazu verwende ich den SR04 in der wasserdichten Variante mit einem MKR 1010 Wifi Board. Der Ultraschallkopf ist am Deckel des IBC-Tanks montier und schallt in das Innere eines Tanks. Aktuell habe ich zwei Probleme:
1. der SR04 funktioniert im freien Raum ganz gut. Sobald ich ihn mit dem Tankdeckel in das Innere des Tanks messen lasse, wird immer nur der minimale Wert von ca. 220 mm gemessen. Was kann ich tun um korrekte Werte zu bekommen.
2. Die WIFI Verbindung reißt immer wieder ab. Anscheinend kommt es zu keinem reconnect. Ich brauche aber eine stabile WiFi Verbindung, da ich am MRK einen Webserver mit Statusanzeigen betreibe.

Würde mich über Feedback freuen. LG, Engelbert

Engelbert Kerschbaummayr

Hinterlassen Sie einen Kommentar

Bitte beachten Sie, dass Kommentare vor der Veröffentlichung genehmigt werden müssen.