Ich habe ein Problem mit einer if- Bedingung, das ich einfach nicht verstehe, es wäre so schön wenn mich jmd. erlösen könnte!
Es handelt sich um diese Intervallsteuerung:
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW; // Pumpe is normally on
int Pumpe= 9;
void setup() {
// put your setup code here, to run once:
pinMode(Pumpe,OUTPUT);
digitalWrite(Pumpe, LOW);
}
void loop() {
// put your main code here, to run repeatedly:
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
} else { // wenn die Pumpe an ist
if (millis() - timestore > 6000) { // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, dass die Pumpe ausgeschaltet ist
timestore = millis();
}
}
}
Ich will diese Intervallsteuerung nur laufen lassen wenn ein Taster LOW ist. Also dachte ich mir ich muss den void- loop- Teil der Intervallsteuerung einfach in eine zusätzliche if- Bedingung einbinden. Das war der Versuch:
// Versuch mit zusätzlicher if- Bedingung
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW; // Pumpe is normally on
int Pumpe= 9;
int Niveauschalterminimum = 2;
void setup() {
// put your setup code here, to run once:
pinMode(Pumpe,OUTPUT);
digitalWrite(Pumpe, LOW);
pinMode(Niveauschalterminimum, INPUT_PULLUP);
}
void loop() {
if (Niveauschalterminimum == LOW){ // wenn der Niveauschalterminimum LOW ist...
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
}
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
else { // wenn die Pumpe an ist
if (millis() - timestore > 6000) { // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, dass die Pumpe ausgeschaltet ist
timestore = millis();
}
}
}
}
Kann mir bitte jmd. verraten was ich falsch gemacht habe?
Das Problem bei meinem Versuch ist, dass die Intervallsteuerung nicht läuft wenn der Taster LOW ist und so auch garnicht unterbrochen werden kann von einer nichterfüllten if- Bedingung;)
statte deinen Sketch mit entsprechenden Debug-Ausgaben (Serial.print) aus, damit du siehst wo dein Programm in ein If hineinspringt. Dann siehst du auch, wo du NICHT hinkommst.
Das schaut auf alle Fälle eingenartig aus, das Pumpenstatus == LOW tut vermutlich nicht viel, da fehlt der Anweisungsblock:
if (Niveauschalterminimum == LOW){ // wenn der Niveauschalterminimum LOW ist...
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
}
auch könntest mal STRG-T in der IDE drücken. Das hilft, die ganzen Einrückungen sichtbar zu machen. Vieleicht siehst du es dann auch schon.
@noiasca:
Kannst Du mir erklären oder ein Beispiel geben wie ich meinen Sketch mit serial.print austatte um zu gucke wo mein Programm in ein if einsprint? Was muss ich dafür mit Serial.print auslesen?
Der Tipp mit STRG + T war gut, habe jetzt auch nochmal ein paar {} Klammern dazugetan, jetzt sehen die Verzeigungen zumindest sinnvoller aus:D.
@Doc_Arduino: Oh ja ich hatte ein digitalRead zum Einlesen des Signals vergessen, habe es hinzugefügt.
So sieht der Sketch jetzt aus:
// Versuch mit zusätzlicher if- Bedingung
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW; // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;
void setup() {
// put your setup code here, to run once:
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
pinMode(Niveauschalterminimum, INPUT_PULLUP);
}
void loop() {
if (digitalRead(Niveauschalterminimum) == LOW) { // wenn der Niveauschalterminimum LOW ist...
{ if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
}
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
else // wenn die Pumpe an ist
if (millis() - timestore > 6000) { // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, dass die Pumpe ausgeschaltet ist
timestore = millis();
}
}
}
}
Es funktioniert leider noch nicht, bitte noch mehr Tipps:)
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
} // diese Klammer muss woanders hin
in dem if Block steht ja nichts drin, eigendlich willst Du doch den gesamten Block zum einschalten da drin haben.
if (digitalRead(Niveauschalterminimum) == LOW){ // wenn der Niveauschalterminimum LOW ist...
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
}
}
Heinz
Nachtrag. Allerdings klappt das Ausschalten mit dem Taster dann immer noch nicht.
die Klammersetzung ist komplett daneben. Schreibe für den Anfang erstmal die geschweiften Klammern ausführlich hin. Also keine öffnende Klammer am Ende der Zeile sondern auf nächste Zeile alleine. Dann nochmal Auto Formatierung. Dann sollte dir etwas auffallen.
Kannst Du mir erklären oder ein Beispiel geben wie ich meinen Sketch mit serial.print austatte um zu gucke wo mein Programm in ein if einsprint? Was muss ich dafür mit Serial.print auslesen?
hm, du sollst dir ja nur marker setzen damit du siehst was das Programm macht. So in etwa:
// Debugausgaben für Serial ergänzt
// STRG-T gedrückt
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW; // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;
void setup() {
Serial.begin(115200); // Serial Ausgabe beginnen
// put your setup code here, to run once:
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
pinMode(Niveauschalterminimum, INPUT_PULLUP);
Serial.println(F("D14 Ende Setup"));
}
void loop() {
if (Niveauschalterminimum == LOW) { // wenn der Niveauschalterminimum LOW ist...
Serial.println(F("D20 Niveauschalterminimum LOW"));
if (PumpenStatus == LOW) { // wenn die Pumpe aus ist
}
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
Serial.println(F("D24 Timestore > 3000"));
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
else { // wenn die Pumpe an ist
if (millis() - timestore > 6000) { // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
Serial.println(F("D31 Timestore > 6000"));
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, dass die Pumpe ausgeschaltet ist
timestore = millis();
}
}
}
}
Die Zeilennummer ist nicht so genau, es geht nur darum, dass du dann auf Grund der Ausgabe im Serial-Monitor weist, woher die Meldung gekommen ist.
Das Program ist natürlich gleich "falsch" wie vorher - analysieren musst du selber.
nach Formatierung sieht man, dass die erste millis Abfrage > 3000 immer gewinnt. Die Zweite kommt nie zum Zug.
Und wenn der Niveauschalter High liest, wird die Pumpe nie ausgeschalten, weil ja dann nichts mehr ausgeführt wird. Das heißt komplette Logik für den Ablauf überdenken. Male es vorher am besten auf.
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
bool PumpenStatus = LOW; // Pumpe is normally on
const byte Pumpe = 9;
const byte Niveauschalterminimum = 2;
void setup()
{
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
pinMode(Niveauschalterminimum, INPUT_PULLUP);
}
void loop()
{
if (digitalRead(Niveauschalterminimum) == LOW) // wenn der Niveauschalterminimum LOW ist...
{
if (PumpenStatus == LOW) // wenn die Pumpe aus ist
{
if (millis() - timestore > 3000) // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
{
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
else // wenn die Pumpe an ist
{
if (millis() - timestore > 6000) // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
{
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, dass die Pumpe ausgeschaltet ist
timestore = millis();
}
}
}
}
}
das sind doch noch mehr Zustände - ich kriege gleich Zustände ...
Schreit nach einem Zustandsautomat - switch case und enums sind dein Freund.
Ich habe das mal versucht umzusetzen.
Wenn die Einstiegsbedingungen einmal erfüllt sind, werden die cases konsequent abgearbeitet, bis die Pumpe wieder aus ist. Vorteil, keine if else Verschachtelungen wo man nicht mehr raus kommt bzw. durchblickt.
Die Signallogik kann ich nicht prüfen.
struct Pumpe
{
unsigned long lastMillis; // Variabler Speicher für 15 Minuten und 15Sekunden
bool status = LOW; // Pumpe is normally on
const byte pin = 9;
const byte pinNiveau = 2;
};
Pumpe pump;
enum class state : byte {IDLE, WAITON, WAITOFF};
state mode = state::IDLE;
void setup()
{
Serial.begin(9600);
pinMode(pump.pin, OUTPUT);
digitalWrite(pump.pin, LOW);
pinMode(pump.pinNiveau, INPUT_PULLUP);
}
void loop()
{
switch (mode)
{
case state::IDLE:
if (!digitalRead(pump.pinNiveau) && (!pump.status) ) // wenn Niveauschalter LOW und Pumpe aus ist ...
{
pump.lastMillis = millis(); // aktuelle Zeit merken für den Vergleich im Nächsten case
mode = state::WAITON;
Serial.println("WAIT ON");
}
break;
case state::WAITON:
if (millis() - pump.lastMillis > 3000) // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
{
digitalWrite(pump.pin, LOW); // Pumpe einschalten
pump.status = HIGH; // notieren, dass die Pumpe angeschaltet ist
pump.lastMillis = millis(); // aktuelle Zeit merken für den Vergleich im Nächsten case
mode = state::WAITOFF;
Serial.println("WAIT OFF");
}
break;
case state::WAITOFF:
if (millis() - pump.lastMillis > 6000) // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
{
digitalWrite (pump.pin, HIGH); // Pumpe ausschalten
pump.status = LOW; // notieren, dass die Pumpe ausgeschaltet ist
mode = state::IDLE;
Serial.println("IDLE");
}
break;
}
}
LeonardoFiando:
Ich habe ein Problem mit einer if- Bedingung, das ich einfach nicht verstehe, es wäre so schön wenn mich jmd. erlösen könnte!
Ich würde mich freuen, wenn Du in Deinem Ursprungsthread bleiben würdest.
Dann wäre es nicht so schwer sich damit auseinandersetzen zu müssen. Nicht alle wissen, wo die Reise hingeht.
Es handelt sich um diese Intervallsteuerung:
Kann mir bitte jmd. verraten was ich falsch gemacht habe?
Also ich fange noch einmal an und biete Dir folgende Zeilen, die ich aus Deinem ersten Code rausgekürzt habe.
Bitte überlege, was Du für Kommentare reingeschrieben hast.
// Forumsketch - kompiliert / ungetestet
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int Pumpe = 9;
void setup() {
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
}
void loop() {
if (digitalRead(Pumpe) && (millis() - timestore > 3000)) // - Neu: Wenn PumpenPin gesetzt UND Zeit abgelaufen
{
digitalWrite(Pumpe, LOW);
timestore = millis();
}
if (!digitalRead(Pumpe) && (millis() - timestore > 6000)) // Wenn PumpenPin gesetzt UND Zeit abgelaufen
{
digitalWrite (Pumpe, HIGH);
timestore = millis();
}
}
Du brauchst keine zusäzliche Variable für den Status.
Das soll das Intervall machen.
Wenn Du vermeiden willst, das das Intervall läuft, wenn Du einen Schalter umlegst, das musst Du dann drum(!) mit einer Abfrage des Schalters legen!
// PSEUDOCODE / kompiliert
// die boolche Variable ist zu ersetzen durch den Schalterzustand
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int Pumpe = 9;
bool Schalter_umgelegt=false;
void setup() {
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
}
void loop() {
if (Schalter_umgelegt )
{
if (digitalRead(Pumpe) && (millis() - timestore > 3000)) // - Neu: Wenn PumpenPin gesetzt UND Zeit abgelaufen
{
digitalWrite(Pumpe, LOW);
timestore = millis();
}
if (!digitalRead(Pumpe) && (millis() - timestore > 6000)) // Wenn PumpenPin gesetzt UND Zeit abgelaufen
{
digitalWrite (Pumpe, HIGH);
timestore = millis();
}
}
}
Mach was draus und bring das in Dein Ursprungsprojekt ein.
Ich hätte nochmal eine Verständnisfrage zu diesem Sketch:
unsigned long timestore; // Variabler Speicher für 15 Minuten und 15Sekunden
int PumpenStatus = LOW; // Pumpe is normally on
int Pumpe = 9;
int Niveauschalterminimum = 2;
void setup() {
// put your setup code here, to run once:
pinMode(Pumpe, OUTPUT);
digitalWrite(Pumpe, LOW);
pinMode(Niveauschalterminimum, INPUT_PULLUP);
}
void loop()
{
if (digitalRead(Niveauschalterminimum == LOW)) { // wenn der Niveauschaltermimum geschlossen ist
if (PumpenStatus == LOW) { // wenn der Pumpenstatus aus ist // Doc_Arduino: Die erste millis Abfrage gewinnt immer!!! aber warum läuft das Programm weiter wenn die Bedingung garnicht erfüllt ist?
if (millis() - timestore > 3000) { // auf die Uhr sehen, ob die 15 Minuten schon rum sind, wenn ja
digitalWrite(Pumpe, LOW); // Pumpe einschalten
PumpenStatus = HIGH; // notieren, dass die Pumpe angeschaltet ist
timestore = millis();
}
} else { // wenn die Pumpe an ist
if (millis() - timestore > 6000) { // auf die Uhr sehen ob die 15 Minuten und 15 Sekunden schon rum sind, wenn ja
digitalWrite (Pumpe, HIGH); // Pumpe ausschalten
PumpenStatus = LOW; // notieren, der Pumpenstatus an ist
timestore = millis();
}
}
} else digitalWrite(Pumpe, HIGH); //Pumpe ausschalten
}
Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?
LeonardoFiando:
Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?
Weil es if (digitalRead(Niveauschalterminimum) == LOW) heissen muss.
Den Rest habe ich mir nicht angeschaut, genau wie Du die Beispiele in der IDE
LeonardoFiando:
Ich verstehe einfach nicht warum die Intervallsteuerung weiterläuft wenn die Bedingung if (digitalRead(Niveauschalterminimum == LOW)) nicht erfüllt ist, dann müsste die Pumpe doch einfach ausgeschaltet sein/ werden?
Die Bedingung ist erfüllt.
Du verstehst nicht die Klammersetzung!
Kurzform:
if (!digitalRead(Niveauschalterminimum)) { // Wenn LowPegel auf PIN machwas
}
Langform:
if (digitalRead(Niveauschalterminimum)==LOW) { // Wenn LowPegel auf PIN machwas
}