From 2e578004c7cd3db60074094795a3f4cf4326c825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Constantin=20F=C3=BCrst?= Date: Tue, 27 Sep 2022 22:28:47 +0200 Subject: [PATCH] rework to use functions and not a state machine --- zisterne.ino | 252 +++++++++++++++++++++++++-------------------------- 1 file changed, 125 insertions(+), 127 deletions(-) diff --git a/zisterne.ino b/zisterne.ino index 862e5f0..12cc18e 100644 --- a/zisterne.ino +++ b/zisterne.ino @@ -20,27 +20,20 @@ 4. Aktueller Druck - atmosphärischen Druck = Messdruck Beispiel: 29810 Pa = 3040 mmH2O = 100% Füllstand 5. Abluftventil öffnen - */ -// Bibliothek für die I2C-Schnittstelle #include - -// Bibliothek für den Sensor (Im Bibliotheksverwalter unter "MicroPressure" suchen -// oder aus dem GitHub-Repository https://github.com/sparkfun/SparkFun_MicroPressure_Arduino_Library ) #include -// Konstruktor initialisieren -// Ohne Parameter werden Default Werte verwendet -SparkFun_MicroPressure mpr; +SparkFun_MicroPressure mpr; // 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 SDA 12 // GPIO12 I2C +#define SCL 13 // GPIO13 I2C #define AUF LOW // Ventil öffnen #define AUS LOW // Pumpe ausschalten #define ZU HIGH // Ventil schliessen @@ -50,115 +43,30 @@ SparkFun_MicroPressure mpr; 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; +int atmDruck = 97400; - 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; +/* +* HELPERS FOR INPUT / OUTPUT +*/ - case 4: // Ablauf beenden - digitalWrite(VENTIL, AUF); - digitalWrite(PUMPE, AUS); - messSchritt = 0; - break; - - default: - messSchritt = 0; - break; - } -} +void printMeasurements(const int& pressure) { + const int wassersaeule = convertPressureToHeight(currentPressure); -void setup() { - // Motortreiber-Signale + 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)) + "%"; - // 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); + if (Serial.available()) { + Serial.println("Füllhöhe: "+ hoehe); + Serial.println("Volumen: " + volumen); + Serial.println("Füllstand: " + fuellstand); } - - messTakt = 0; - messSchritt = 0; - atmDruck = 97400.0; // Augangswert Atmosphärendruck in Pa } - -void loop() { + +void handleSerialInput() { static String inputString; - // Kommandos über serielle Schnittstelle if (Serial.available()) { char inChar = (char)Serial.read(); if ((inChar == '\r') || (inChar == '\n')) { @@ -188,31 +96,121 @@ void loop() { digitalWrite(VENTIL, AUF); } else if (inputString == "start") { - if (messSchritt == 0) { - Serial.println("Messung gestartet"); - messSchritt = 1; - } + Measurement(); } inputString = ""; } else inputString += inChar; } +} + +/* +* FUNCTIONS FOR MEASUREMENT +*/ - // Alle 10 ms Sensorwert auslesen +int getPressureSensorValue() { + static int measuredPressure = 0; + static unsigned long messTakt = 0; + // Messwert in Pascal auslesen und filtern - alle 10ms bei aufruf 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; + measuredPressure = ((measuredPressure * 50) + int(mpr.readPressure(PA))) / 51; messTakt = millis() + 10; } + return measuredPressure; +} + +int convertPressureToHeight(const int& pressure) { + // Umrechnung Pa in mmH2O + const int wassersaeule = (pressure - atmDruck) * 10197 / 100000; + if (wassersaeule < 0) return 0; + else return wassersaeule; +} + +int setAtmosphericPressure() { + static unsigned long messTakt = 0; + if (messTakt < millis()) { + if (!digitalRead(VENTIL) && !digitalRead(PUMPE)) { + atmDruck = getPressureSensorValue(); + } + messTakt = millis() + 1000; + } +} - // Sicherheitsabschaltung der Pumpe bei Überdruck - if ((messSchritt == 0) && (wassersaeule > (maxFuellhoehe + 300))) { - digitalWrite(PUMPE, AUS); - Serial.println("Überdruck. Messleitung verstopft!"); +/* +* MAIN MEASUREMENT ORCHESTRATOR +*/ + +void Measurement() { + int oldPressure = getPressureSensorValue(); + digitalWrite(VENTIL, ZU); + digitalWrite(PUMPE, EIN); + delay(500); + + while (true) { + const int currentPressure = getPressureSensorValue(); + + if (convertPressureToHeight(currentPressure) > (maxFuellhoehe + 200)) { + digitalWrite(VENTIL, AUF); + digitalWrite(PUMPE, AUS); + Serial.println("Fehler: Messleitung verstopft!"); + return; + } + + if (currentPressure > oldPressure + 10) { + oldPressure = currentPressure; + delay(100); + } + else { + break; + } } + + const int finalPressure = getPressureSensorValue(); + + digitalWrite(VENTIL, AUF); + digitalWrite(PUMPE, AUS); + + printMeasurements(finalPressure); +} + +/* +* SETUP AND LOOP FOR ARDUINO RUNTIME +*/ + +void setup() { + // 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); + + // enable serial console + Serial.begin(115200); + delay(10); + + // 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); + } +} - // State-Machine - messablauf(); +void loop() { + handleSerialInput(); + setAtmosphericPressure(); + + // ensure valve is open and pump turned off + digitalWrite(VENTIL, AUF); + digitalWrite(PUMPE, AUS); }