Die verzögerte Pumpenabschaltung soll im Display(MicroView) jede Sekunde runtergezählt angezeigt werden.
Wird merkwürdigerweise nur letze case angezeigt, also 3s.
switch (millis() - altMillis)
{
case 1000 … 1999:
Zeile1 = “Pume aus in 1s”;
DisplayChange = HIGH;
break;
case 2000 … 2999:
Zeile1 = “Pume aus in 2s”;
DisplayChange = HIGH;
break;
case 3000 … 3999:
Zeile1 = “Pume aus in 3s”;
DisplayChange = HIGH;
break;
}
Was mache ich falsch?
#include <MicroView.h> // include MicroView library
int Pin0 = 0;
int Pin1 = 1;
int Pin2 = 2;
int Pin3 = 3;
int Pumpe = 5;
int State0 = HIGH;
int LastState0 = HIGH;
int State1 = HIGH;
int LastState1 = HIGH;
int State2 = HIGH;
int LastState2 = HIGH;
int State3 = HIGH;
int LastState3 = HIGH;
int Pumpenverzoegerung = 5000;
String Zeile1;
String Zeile2;
String Zeile3;
String Zeile4;
String Zeile5;
String Zeile6;
String Ereignis;
bool AutoPumpeAus = LOW;
bool AutoPumpeAusErkannt = LOW;
bool DisplayChange = HIGH;
unsigned long aktMillis, altMillis, printMillis, pumpenMillis; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
void setup()
{
Serial.begin(9600);
/* Setup the pin direction. */
pinMode(Pin0, INPUT);
pinMode(Pin1, INPUT);
pinMode(Pin2, INPUT);
pinMode(Pin3, INPUT);
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
uView.begin(); // start MicroView
uView.clear(PAGE); // clear page
uView.print("Initialisation complete.");
uView.display();
delay(2000);
}
void loop()
{
State0 = digitalRead (Pin0);
State1 = digitalRead (Pin1);
State2 = digitalRead (Pin2);
State3 = digitalRead (Pin3);
//Aktion für Pin0
if(LastState0 == LOW && State0 == HIGH)
{
Zeile2 = "Spr O aus";
DisplayChange = HIGH;
LastState0 = State0;
AutoPumpeAus = HIGH;
}
if(LastState0 == HIGH && State0 == LOW)
{
Zeile2 = "Spr O an";
Zeile1 = "Pumpe an";
DisplayChange = HIGH;
LastState0 = State0;
digitalWrite(Pumpe, HIGH);
AutoPumpeAus = LOW;
}
//Aktion für Pin1
if(LastState1 == LOW && State1 == HIGH)
{
Zeile3 = "Spr S aus";
DisplayChange = HIGH;
LastState1 = State1;
AutoPumpeAus = HIGH;
}
if(LastState1 == HIGH && State1 == LOW)
{
Zeile3 = "Spr S an";
Zeile1 = "Pumpe an";
DisplayChange = HIGH;
LastState1 = State1;
digitalWrite(Pumpe, HIGH);
AutoPumpeAus = LOW;
}
//Aktion für Pin2
if(LastState2 == LOW && State2 == HIGH)
{
Zeile4 = "Spr W aus";
DisplayChange = HIGH;
LastState2 = State2;
AutoPumpeAus = HIGH;
}
if(LastState2 == HIGH && State2 == LOW)
{
Zeile4 = "Spr W an";
Zeile1 = "Pumpe an";
DisplayChange = HIGH;
LastState2 = State2;
digitalWrite(Pumpe, HIGH);
AutoPumpeAus = LOW;
}
//Aktion für Pin3
if(LastState3 == LOW && State3 == HIGH)
{
Zeile5 = "Spr N aus";
//Zeile1 = "Pumpe aus";
DisplayChange = HIGH;
LastState3 = State3;
digitalWrite(Pumpe, LOW);
AutoPumpeAus = HIGH;
}
if(LastState3 == HIGH && State3 == LOW)
{
Zeile5 = "Spr N an";
Zeile1 = "Pumpe an";
DisplayChange = HIGH;
LastState3 = State3;
digitalWrite(Pumpe, HIGH);
AutoPumpeAus = LOW;
}
//Automatische Pumpenabschaltung nach Zeit
if(AutoPumpeAus == HIGH)
{
if(AutoPumpeAusErkannt == LOW)
{
aktMillis = millis();
altMillis = aktMillis;
AutoPumpeAusErkannt = HIGH;
}
Ereignis = "Automatische Pumpenabschaltung an";
switch (millis() - altMillis)
{
case 1000 ... 1999:
Zeile1 = "Pume aus in 1s";
DisplayChange = HIGH;
break;
case 2000 ... 2999:
Zeile1 = "Pume aus in 2s";
DisplayChange = HIGH;
break;
case 3000 ... 3999:
Zeile1 = "Pume aus in 3s";
DisplayChange = HIGH;
break;
}
if (millis() - altMillis > Pumpenverzoegerung) //Pumpe aus
{
Ereignis = "5s Automatische Pumpenabschaltung vorbei";
Zeile1 = "Pumpe aus";
DisplayChange = HIGH;
AutoPumpeAusErkannt = LOW;
AutoPumpeAus = LOW;
}
}
//Anzeige
if(DisplayChange == HIGH)
{
uView.begin(); // start MicroView
uView.clear(PAGE); // clear page
uView.setCursor(0,0); // set cursor at 0,0
uView.print(Zeile1);
uView.setCursor(0,9);
uView.print(Zeile2);
uView.setCursor(0,18);
uView.print(Zeile3);
uView.setCursor(0,27);
uView.print(Zeile4);
uView.setCursor(0,36);
uView.print(Zeile5);
uView.display();
DisplayChange = LOW;
}
}
Bevor sich jemand wundert: ... bei switch/case ist eine Erweiterung die von manchen Compilern wie gcc unterstützt wird:
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Case-Ranges.html#Case-Ranges
Da kann man aber auch gleich if/else nehmen
Geht aber auch mit if/else nicht...
Hallo,
zählt deine Differenzbildung nicht eher hoch statt runter?
Okay, wirst du besser wissen. Ich würde ja nur den reinen Sekundenwert aktualisieren.
unsigned int Differenz = (millis()-altMillis)/1000;
lcd.cursor(1,7); lcd.print(Differenz);
Doc_Arduino:
Hallo,
zählt deine Differenzbildung nicht eher hoch statt runter?
Okay, wirst du besser wissen. Ich würde ja nur den reinen Sekundenwert aktualisieren.
unsigned int Differenz = (millis()-altMillis)/1000;
lcd.cursor(1,7); lcd.print(Differenz);
Hab alles so aufgebaut damit Display nicht flackert. Wert soll nur bei Änderung angezeigt werden.
Hallo,
mit deinem Pseudo Code würde auch permanent auf das Display geschrieben. Außerdem kann nichts flackern wenn immer das gleiche Zeichen an die gleiche Stelle geschrieben wird. Den Text davor mußte ja nicht ständig schreiben sondern nur die Sekunden. Würde aber auch nicht flackern, weil er gleich bleibt.
Doc_Arduino:
Hallo,
mit deinem Pseudo Code würde auch permanent auf das Display geschrieben. Außerdem kann nichts flackern wenn immer das gleiche Zeichen an die gleiche Stelle geschrieben wird. Den Text davor mußte ja nicht ständig schreiben sondern nur die Sekunden. Würde aber auch nicht flackern, weil er gleich bleibt.
Nö, nö Doc.
Display wird nur beschrieben wenn DisplayChange auf H gesetzt wird.
Aber warum wird bei case 1s nicht angezeigt?
Hallo,
das ist doch permanent "high" zwischen 1000 und 3999. Also wird auch permanent geschrieben.
case 1s, weil das Ergebnis scheinbar nie kommt, da würde Debugging helfen. Sich die ms Differenz und altMillis permanent anzeigen lassen. Und zwar direkt nach
switch (millis() - altMillis)
{
Das mit den millis-Anzeigen
hab ich schon gemacht.
Das Ereignis tritt ein. Ich dachte schon ein loop-Durchlauf wäre zu lange - ist aber bei ca. 40ms.
Hmm, bin etwas ratlos...
stoni99
August 26, 2016, 4:52pm
#10
Scheint dem Dislay zu schnell zu gehen:
Mit bösem delay(300)
switch (millis() - altMillis)
{
case 1000 ... 1999:
Zeile1 = "Pume aus in 1s";
DisplayChange = HIGH;
delay(300);
break;
case 2000 ... 2999:
Zeile1 = "Pume aus in 2s";
DisplayChange = HIGH;
delay(300);
break;
case 3000 ... 3999:
Zeile1 = "Pume aus in 3s";
DisplayChange = HIGH;
delay(300);
break;
}
wird auch 1s & 2s angezeigt. Flackernd - aber geht. Muß also Anzeige nach 1. Anzeige verriegeln und erst bei Änderung wieder neu anzeigen...
Hallo,
wenn das Ereignis nachweislich eintritt, dann wird es auch ausgeführt. Kommt ja direkt danach dran. Ich wette es wird durch etwas anderes sofort überschrieben. Setz mal nach der 1s Anzeige ein hartes delay rein. Dann mußt du die 1s im Display sehen. Wenn ja, ab da weiter im Code nach überschreiben suchen.
Edit:
hattest schon die gleiche Idee. Dann suche danach warum es überschrieben wird.
Ich meine das Freigabe "High" ist ja immer noch ständig "High". Vielleicht liegst daran.
Das ordentlich zwischen H und L zu schalten wäre bestimmt wichtig.
Oder mit if und eine eigene bool Sperrvariable einbauen.
stoni99
August 26, 2016, 7:23pm
#12
Aufwändig aber funktioniert: Nur einmal anzeigen.
switch (millis() - altMillis)
{
case 1000 ... 1999:
Zeile1 = "Pumpe 4s";
if (SchonAngezeigt1 == LOW)
{
DisplayChange = HIGH;
SchonAngezeigt1 = HIGH;
}
break;
case 2000 ... 2999:
Zeile1 = "Pumpe 3s";
if (SchonAngezeigt2 == LOW)
{
DisplayChange = HIGH;
SchonAngezeigt2 = HIGH;
}
break;
case 3000 ... 3999:
Zeile1 = "Pumpe 2s";
if (SchonAngezeigt3 == LOW)
{
DisplayChange = HIGH;
SchonAngezeigt3 = HIGH;
}
break;
case 4000 ... 4999:
Zeile1 = "Pumpe 1s";
if (SchonAngezeigt4 == LOW)
{
DisplayChange = HIGH;
SchonAngezeigt4 = HIGH;
}
break;
}
Übrigends:
Das MicroView-Display lässt sich nur komplett anzeigen - nur ein einzelnes Zeichen ändern & anzeigen geht nicht. Daher der Aufwand.
stoni99:
Übrigends:
Das MicroView-Display lässt sich nur komplett anzeigen - nur ein einzelnes Zeichen ändern & anzeigen geht nicht. Daher der Aufwand.
aha, na dann muß man leider paar Umstände einbauen. Schön das es jetzt funktioniert.
Finde nur ich den Code etwas unübersichtlich? Das mit dem switch und "..." mag zwar gehen, wenn Serenfly angemerkt hat (wusste ich nicht), aber sollte man nicht verwenden, ausser man WILL Verwirrung stiften
uint32_t actMillis = millis();
static uint32_t lastMillis = 0;
uint8_t actCt = (uint32_t)(actMillis - lastMillis)/1000;
static uint8_t lastCt = 0;
if(actCt != lastCt) {
lastCt = actCt;
printf("CTVAL in Sekunden\n");
}
aber sollte man nicht verwenden, ausser man WILL Verwirrung stiften
Solange man es selbst versteht ist es ja ok. Und es ist auch etwas besser lesbar als
if (var > y && var < z)
Da es nicht Standard ist sollte man es halt erwähnen wenn man Code postet, da es nicht jeder kennt
Bei seinen Switch Abfragen kann man sich x > y && x < z sparen. Hier reicht eine einfache 1000er Division
stoni99
August 27, 2016, 2:48pm
#17
Ja, das stimmt. Gibt noch einiges zu verbessern - ist auch noch nicht fertig.
Hallo,
ähm, will ja nichts sagen, aber das "durch 1000" hatte ich weiter oben schon erwähnt, war scheinbar der Zeit zu weit voraus ... muß immer erst ein anderer kommen um das nochmal bestätigen.
ruhiges WE