Constantin Fürst
2 years ago
commit
2d1879229c
1 changed files with 274 additions and 0 deletions
-
274zisterne.ino
@ -0,0 +1,274 @@ |
|||||
|
/*
|
||||
|
Pneumatische Zisternen-Füllstandsmessung. |
||||
|
Start der Messung und Übertragung der Ergebnise über WLAN. |
||||
|
|
||||
|
Arduino-Bord: "NodeMCU 1.0(ESP-12E Module)" |
||||
|
Autor Wolfgang Neußer |
||||
|
Stand: 24.10.2021 |
||||
|
|
||||
|
Hardware: |
||||
|
DOIT ESP12E Motor Shield mit L293D Motortreiber |
||||
|
Amica NODE MCU ESP8266 12E |
||||
|
SparkFun Qwiic MicroPressure Sensor |
||||
|
Druckpumpe und Entlüftungsventil aus Oberarm-Blutdruckmesser |
||||
|
|
||||
|
Messablauf: |
||||
|
1. Abluftventil schließen, Druckpumpe einschalten |
||||
|
2. Druck kontinuierlich messen |
||||
|
Wenn Druckanstieg beendet -> Pumpe ausschalten |
||||
|
3. Beruhigungszeit |
||||
|
4. Aktueller Druck - atmosphärischen Druck = Messdruck |
||||
|
Beispiel: 29810 Pa = 3040 mmH2O = 100% Füllstand |
||||
|
5. Abluftventil öffnen |
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
// Bibliothek für WLAN
|
||||
|
#include <ESP8266WiFi.h>
|
||||
|
|
||||
|
// Bibliothek für die I2C-Schnittstelle
|
||||
|
#include <Wire.h>
|
||||
|
|
||||
|
// Bibliothek für den Sensor (Im Bibliotheksverwalter unter "MicroPressure" suchen
|
||||
|
// oder aus dem GitHub-Repository https://github.com/sparkfun/SparkFun_MicroPressure_Arduino_Library )
|
||||
|
#include <SparkFun_MicroPressure.h>
|
||||
|
|
||||
|
// Server an Port 80 initialisieren
|
||||
|
WiFiServer server(80); |
||||
|
|
||||
|
// Konstruktor initialisieren
|
||||
|
// Ohne Parameter werden Default Werte verwendet
|
||||
|
SparkFun_MicroPressure mpr; |
||||
|
|
||||
|
// Bibliothek für das Flashen über WLAN
|
||||
|
#include <ArduinoOTA.h>
|
||||
|
|
||||
|
// Zuordnung der Ein- Ausgänge
|
||||
|
#define VENTIL 5 // GPIO5 (PWM MotorA)
|
||||
|
#define DA 0 // GPIO0 (Richtung MotorA)
|
||||
|
#define PUMPE 4 // GPIO4 (PWM MotorB)
|
||||
|
#define DB 2 // GPIO2 (Richtung MotorB)
|
||||
|
#define SDA 12 // GPIO12 I2C
|
||||
|
#define SCL 13 // GPIO13 I2C
|
||||
|
#define AUF LOW // Ventil öffnen
|
||||
|
#define AUS LOW // Pumpe ausschalten
|
||||
|
#define ZU HIGH // Ventil schliessen
|
||||
|
#define EIN HIGH // Pumpe einschalten
|
||||
|
|
||||
|
// Heimnetz Parameter (an eigenes Netz anpassen)
|
||||
|
const char* ssid = "Heimnetz-Name"; |
||||
|
const char* pass = "Heimnetz-Passwort"; |
||||
|
|
||||
|
// An eigene Zisterne anpassen (zur Berechnung der Füllmenge)
|
||||
|
const int A = 3140; // Grundfläche der Zisterne in cm^2 (d * d * 3,14 / 4)
|
||||
|
const int maxFuellhoehe = 3040; // Füllhöhe der Zisterne in mm
|
||||
|
|
||||
|
int atmDruck, messDruck, vergleichswert; |
||||
|
int messSchritt, wassersaeule; |
||||
|
String hoehe = " - - "; |
||||
|
String volumen = "- - "; |
||||
|
String fuellstand = " - - "; |
||||
|
unsigned long messung, messTakt; |
||||
|
|
||||
|
// **************************************************************************************
|
||||
|
// State-Machine Füllstandsmessung
|
||||
|
//
|
||||
|
void messablauf() { |
||||
|
switch (messSchritt) { |
||||
|
case 0: // Regelmäßig aktuellen atmosphärischen Druck erfassen
|
||||
|
if (!digitalRead(VENTIL) && !digitalRead(PUMPE)) { |
||||
|
atmDruck = messDruck; |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case 1: // Messung gestartet
|
||||
|
vergleichswert = messDruck; |
||||
|
digitalWrite(VENTIL, ZU); |
||||
|
digitalWrite(PUMPE, EIN); |
||||
|
messung = millis() + 2000; |
||||
|
messSchritt = 2; |
||||
|
break; |
||||
|
|
||||
|
case 2: // warten solange Druck steigt
|
||||
|
if (messDruck > vergleichswert + 10) { |
||||
|
vergleichswert = messDruck; |
||||
|
messung = millis() + 1000; |
||||
|
} |
||||
|
if (wassersaeule > (maxFuellhoehe + 200)) { |
||||
|
Serial.println("Fehler: Messleitung verstopft!"); |
||||
|
messSchritt = 4; |
||||
|
} |
||||
|
else if (messung < millis()) { |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
messung = millis() + 100; |
||||
|
messSchritt = 3; |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case 3: // Beruhigungszeit abgelaufen, Messwert ermitteln
|
||||
|
if (messung < millis()) { |
||||
|
hoehe = String(wassersaeule / 10) + "cm"; |
||||
|
volumen = String((wassersaeule / 10) * A / 100) + "L"; |
||||
|
// Umrechnung Wassersäule in 0 - 100%
|
||||
|
fuellstand = String(map(wassersaeule, 0, maxFuellhoehe, 0, 100)) + "%"; |
||||
|
Serial.println("Füllhöhe: "+ hoehe); |
||||
|
Serial.println("Volumen: " + volumen); |
||||
|
Serial.println("Füllstand: " + fuellstand); |
||||
|
Serial.println(); |
||||
|
messSchritt = 4; |
||||
|
} |
||||
|
break; |
||||
|
|
||||
|
case 4: // Ablauf beenden
|
||||
|
digitalWrite(VENTIL, AUF); |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
messSchritt = 0; |
||||
|
break; |
||||
|
|
||||
|
default: |
||||
|
messSchritt = 0; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void setup() { |
||||
|
// Motortreiber-Signale
|
||||
|
|
||||
|
// Richtung Motor A
|
||||
|
pinMode(DA, OUTPUT); |
||||
|
digitalWrite(DA, HIGH); |
||||
|
// PWM Motor A
|
||||
|
pinMode(VENTIL, OUTPUT); |
||||
|
digitalWrite(VENTIL, AUF); |
||||
|
|
||||
|
// Richtung Motor B
|
||||
|
pinMode(DB, OUTPUT); |
||||
|
digitalWrite(DB, HIGH); |
||||
|
// PWM Motor B
|
||||
|
pinMode(PUMPE, OUTPUT); |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
|
||||
|
Serial.begin(115200); |
||||
|
delay(10); |
||||
|
Serial.println(); |
||||
|
|
||||
|
// I2C initialisieren mit 400 kHz
|
||||
|
Wire.begin(SDA, SCL, 400000); |
||||
|
|
||||
|
// Drucksensor initialisieren
|
||||
|
// Die Default-Adresse des Sensors ist 0x18
|
||||
|
// Für andere Adresse oder I2C-Bus: mpr.begin(ADRESS, Wire1)
|
||||
|
if(!mpr.begin()) { |
||||
|
Serial.println("Keine Verbindung zum Drucksensor."); |
||||
|
while(1); |
||||
|
} |
||||
|
|
||||
|
// WiFi initialisieren
|
||||
|
WiFi.mode(WIFI_STA); |
||||
|
Serial.println("Verbindung zu " + String(ssid) + " wird hergestellt"); |
||||
|
WiFi.begin(ssid, pass); |
||||
|
while (WiFi.status() != WL_CONNECTED) { |
||||
|
delay(500); |
||||
|
Serial.print("."); |
||||
|
} |
||||
|
Serial.println(); |
||||
|
server.begin(); |
||||
|
Serial.println("Server ist gestartet"); |
||||
|
Serial.print("IP-Adresse: "); |
||||
|
Serial.println(WiFi.localIP()); |
||||
|
|
||||
|
ArduinoOTA.onStart([]() { // Pumpe und Ventil ausschalten beim Flashen
|
||||
|
digitalWrite(VENTIL, AUF); |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
messSchritt = 0; |
||||
|
}); |
||||
|
// Passwort zum Flashen
|
||||
|
ArduinoOTA.setPassword((const char *)"esp8266"); |
||||
|
// OTA initialisieren
|
||||
|
ArduinoOTA.begin(); |
||||
|
|
||||
|
messTakt = 0; |
||||
|
messSchritt = 0; |
||||
|
atmDruck = 97400.0; // Augangswert Atmosphärendruck in Pa
|
||||
|
} |
||||
|
|
||||
|
void loop() { |
||||
|
static String inputString; |
||||
|
|
||||
|
// OTA-Service bedienen
|
||||
|
ArduinoOTA.handle(); |
||||
|
yield(); |
||||
|
|
||||
|
// Kommandos über serielle Schnittstelle
|
||||
|
if (Serial.available()) { |
||||
|
char inChar = (char)Serial.read(); |
||||
|
if ((inChar == '\r') || (inChar == '\n')) { |
||||
|
if (inputString == "?") { |
||||
|
Serial.println("Kommandos: "); |
||||
|
Serial.println("p1 = Pumpe EIN"); |
||||
|
Serial.println("p0 = Pumpe AUS"); |
||||
|
Serial.println("v1 = Ventil ZU"); |
||||
|
Serial.println("v0 = Ventil AUF"); |
||||
|
Serial.println("start = Messung starten"); |
||||
|
Serial.println(); |
||||
|
} |
||||
|
else if (inputString == "p1") { |
||||
|
Serial.println("Pumpe EIN"); |
||||
|
digitalWrite(PUMPE, EIN); |
||||
|
} |
||||
|
else if (inputString == "p0") { |
||||
|
Serial.println("Pumpe AUS"); |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
} |
||||
|
else if (inputString == "v1") { |
||||
|
Serial.println("Ventil ZU"); |
||||
|
digitalWrite(VENTIL, ZU); |
||||
|
} |
||||
|
else if (inputString == "v0") { |
||||
|
Serial.println("Ventil AUF"); |
||||
|
digitalWrite(VENTIL, AUF); |
||||
|
} |
||||
|
else if (inputString == "start") { |
||||
|
if (messSchritt == 0) { |
||||
|
Serial.println("Messung gestartet"); |
||||
|
messSchritt = 1; |
||||
|
} |
||||
|
} |
||||
|
inputString = ""; |
||||
|
} else inputString += inChar; |
||||
|
} |
||||
|
|
||||
|
// Alle 10 ms Sensorwert auslesen
|
||||
|
if (messTakt < millis()) { |
||||
|
// Messwert in Pascal auslesen und filtern
|
||||
|
messDruck = ((messDruck * 50) + int(mpr.readPressure(PA))) / 51; |
||||
|
// Umrechnung Pa in mmH2O
|
||||
|
wassersaeule = (messDruck - atmDruck) * 10197 / 100000; |
||||
|
if (wassersaeule < 0) wassersaeule = 0; |
||||
|
messTakt = millis() + 10; |
||||
|
} |
||||
|
|
||||
|
// Sicherheitsabschaltung der Pumpe bei Überdruck
|
||||
|
if ((messSchritt == 0) && (wassersaeule > (maxFuellhoehe + 300))) { |
||||
|
digitalWrite(PUMPE, AUS); |
||||
|
Serial.println("Überdruck. Messleitung verstopft!"); |
||||
|
} |
||||
|
|
||||
|
// State-Machine
|
||||
|
messablauf(); |
||||
|
|
||||
|
// Start der Messung und Übergabe des letzten Ergebnisses bei jeder Client-Anfrage
|
||||
|
WiFiClient client = server.available(); |
||||
|
if (client) { |
||||
|
client.print("<head><title>Fuellstandsmesser</title>"); |
||||
|
client.print("<meta charset=\"utf-8\" http-equiv='refresh' content='10'>"); |
||||
|
client.print("<meta name='viewport' content='width=device-width, initial-scale=1.0' /></head>"); |
||||
|
client.print("<h1>Füllstand Zisterne</h1><br>"); |
||||
|
client.print("<table>"); |
||||
|
client.print("<tr><td><b>Füllhöhe:</b> </td><td>"); client.print(hoehe); client.print("<br></td></tr>"); |
||||
|
client.print("<tr><td><b>Volumen:</b> </td><td>"); client.print(volumen); client.print("<br></td></tr>"); |
||||
|
client.print("<tr><td><b>Füllstand:</b> </td><td>"); client.print(fuellstand); client.print("<br></td></tr>"); |
||||
|
client.print("</table>"); |
||||
|
if (messSchritt == 0) messSchritt = 1; |
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue