Ich steuere eine Wasserpumpe für mein Hauswasserwerk mit einem Drucksensor, einem Arduino und einem Relais. Funktioniert soweit eigentlich auch. Nur schaltet sich das ganze nur sehr stotternd aus.
Ich würde gerne bei überschreiten des festgelegten Ausschaltdrucks über eine bestimmte Zeit (z.B. 3 Sek.) den Druck messen und wenn der Druck sich nicht mehr verändert erst ausschalten.
Wie stelle ich das am besten an?
So sieht das Ganze bis her aus:
/*
Meine Pumpensteuerung
*/
int druckSensor = A2;
int pumpenRelais = 8;
byte state = 0;
int lastState = 0;
void problem(void) {
digitalWrite(pumpenRelais, LOW);
}
void setup() {
Serial.begin(9600);
pinMode (pumpenRelais, OUTPUT);
}
void loop() {
long sensorSumme=0;
#define SAMPLES 200
for (int i=0; i<SAMPLES; i++) // Signal mehrmals messen, ca. 20 Millisekunden lang
{
sensorSumme+=analogRead(druckSensor);
}
int sensorWert = sensorSumme/SAMPLES; // Mittelwert bilden
Serial.println(sensorWert);
if(sensorWert <= 520) state = 0; // Pumpe AN
if(sensorWert >= 550) state = 1; // Pumpe AUS
if(lastState != state) {
lastState = state;
switch (state)
{
case 0: // Pumpe Aus
digitalWrite(pumpenRelais, LOW);
break;
case 1: // Pumpe An
digitalWrite(pumpenRelais, HIGH);
break;
default:
problem();
}
}
}
Du kannst mit millis() eine Zeit ablaufen lassen und dann nochmal messen. Aber deine Schalthysterese 520/550 ist viel zu eng, das wird immer zu Problemen führen. Ein- und Ausschaltpunkt sollten deutlich auseinander liegen.
Soll eigentlich auch, meine Schalthysterese war ursprünglich 350/550. Das Problem ist, wenn der Druck abfällt, der Einschaltpunkt erreicht wird und die Pumpe anspringt, dann springt der Druck ganz kurz auf den Abschaltpunkt und die Pumpe hat nicht die Zeit den Druck in der Leitung aufzubauen.
Deshalb soll wenn der Auschaltpunkt erreicht wird für 3 Sek. gemessen werden ob der Druck stabil bleibt und dann erst abgeschaltet werden.
Ich hatte auch an millis() gedacht. Aber wie baue ich das ein?
Du solltest die Messwerte des Drucksensors im Loop kontinuierlich einlesen und "glätten", dann passiert bei kurzen Impulsen Nichts. Das ginge z.B. mit einem Array aus 5 Foat-Variablen so:
loop{
press[4]=press[3];
press[3]=press[2];
press[2]=press[1];
press[1]=press[0];
press[0]=aktmess();
medmess=(press[4]+press[3]+press[2]+press[1]+press[0])/5;
if (medmess>auschalt_schwelle){ ausschalt();}
if (medmess<einschalt_schwelle){ einschalt();}
delay(20);
}
Man nennt sowas "kontinuierliche Mittelwertbildung" ... der gezeigte Code ist nur eine Denkanregung, man kann die Mittelwertbildung auch deutlich länger machen, dann natürlich in einer for-Schleife. Der Unterschied zu deiner Lösung ist, dass nicht das Programm quasi angehalten und mehrfach gemessen wird, sondern nach jeder Messung erneut eine Entscheidung getroffen wird ... find ich "flüssiger". Ein maßvoll eingesetztes delay bewirkt eine kalkulierbare Zyklus- und Integrationszeit.
Dein Vorschlag liest sich sehr gut, überfordert mich gerade aber ein klein wenig.
Ich bin ja aber hier um zu lernen und möchte das sehr gerne versuchen.
Ich habe jetzt noch eine Ermittlung des Maximaldruckes in das setup eingebaut und entsprechende Variablen angelegt. Ich hab das ganze noch nicht im Einsatz gehabt.
Funktioniert das so eurer Meinung nach?
/*
Meine Pumpensteuerung
*/
const int druckSensor = A2;
const int pumpenRelais = 8;
bool state = 0;
bool lastState = 0;
unsigned long previousMillis = millis();
const int interval = 3000;
const int kalibrieren = 30000;
int maxDruck = 0;
int newDruck = 0;
void problem(void) {
digitalWrite(pumpenRelais, LOW);
}
void setup() {
Serial.begin(9600);
pinMode (pumpenRelais, OUTPUT);
digitalWrite(pumpenRelais, LOW);
if(millis() - previousMillis >= kalibrieren)
{
newDruck = analogRead(druckSensor);
if(newDruck > maxDruck)
maxDruck = newDruck;
}
digitalWrite(pumpenRelais, HIGH);
}
void loop() {
long sensorSumme=0;
#define SAMPLES 200
for (int i=0; i<SAMPLES; i++) // Signal mehrmals messen, ca. 20 Millisekunden lang
{
sensorSumme+=analogRead(druckSensor);
}
int sensorWert = sensorSumme/SAMPLES; // Mittelwert bilden
Serial.println(sensorWert);
if(sensorWert <= maxDruck - 100) state = 0; // Pumpe AN
if(millis() - previousMillis >= interval && sensorWert >= maxDruck)
{
previousMillis = millis();
state = 1; // Pumpe AUS
}
if(lastState != state) {
lastState = state;
switch (state)
{
case 0: // Pumpe Aus
digitalWrite(pumpenRelais, LOW);
break;
case 1: // Pumpe An
digitalWrite(pumpenRelais, HIGH);
break;
default:
problem();
}
}
}
mioPressControlIntervall.ino: In function 'void setup()':
mioPressControlIntervall:33: error: call of overloaded 'print(long unsigned int (&)())' is ambiguous
Hab die serielle Ausgabe in "setup" jetzt erstmal Auskommentiert.
Setup scheint yu funktionieren.
Die Pumpe geht jetzt aber nicht an bei maxDruck -(minus) 100.