If Abfrage Wert und Zeit bedingung

Hallo Zusammen,
könnte mir jemand erklären oder ein Beispiel geben wie ich bei einer If abfrage zwei Bedingungen hinzufüge. Ich habe einen Sensor und der If Befehl soll erst ausgeführt werden wenn der eine bestimmte Zeit lang über 7 liegt. Aber ich habe keine Ahnung wie ich das mit den zwei
Bedingungen mache und im Internet findet man nichts vergleichbares.
Mfg

Ich rate zu einem C++ Buch und dann zum Kapitel "logische Operatoren"

Ansonsten:
Ich persönlich kann if nicht leiden!

Leitmotiv:

Jedes vermeidbare if ist ein böses if
Jedes vermiedene if ist ein gutes if

Und komplizierte Bedingungen machen die Welt auch nicht schöner.

if (bedingung == true && anderebedingung == true)
{machwas}
if (bedingung == true)
{
  if (anderebedingung == true)
   {machwas}
}

man sollte den Zustand "über 7" abfragen, während die Zeit läuft, dann entweder vorzeitigen Abbruch bearbeiten oder erfolgreichen Abschluss der Zeit.

Hallo quenny

Hier kommt was zum Lesen beim Frühstück:

https://www.learncpp.com/cpp-tutorial/logical-operators/

Ich wünsche Ihnen einen geschmeidigen Tag und viel Spaß beim Programmieren in C++.

Mache eine verschachtelte if Abfrage. Als erstes prüfst du, ob dein Wert 7 ist, wenn dies der Fall ist geht es weiter mit der nächsten if Abfrage, wo du auf Zeit prüfst. Das blink without delay Beispiel in der Arduino IDE hilft da weiter. Sollte sich jetzt vor ablauf der Zeit der Wert 7 ändern, setzt du die Zeit einfach zurück und alles beginnt von vorne. Wenn der Wert aber 7 bleibt und die Zeit abgelaufen ist, machst du das was gemacht werden soll und setzt am Ende die Zeit wieder zurück.

unsigned long startTime = 0;
int buttonPin = 2; 
int buttonState = 0; 

void setup() {
  pinMode(buttonPin, INPUT);
}

void loop() {
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
   
    if (millis() - startTime > 10000) {
     
//... mache etwas

      startTime = millis();
    }
  } else {
    startTime = millis();
  }

}

Also ungefähr so, wobei ich in meinem Beispiel der einfachheithalber, einen button lediglich auf high prüfe. Aber das kannste entsprechend auf deine Bedürfnisse ummünzen.

Ist zwar prinzipiell richtig, aber völlig unnötig.
Da der Zeitzähler der Einfachheit halber ständig rückgesetzt wird wenn der Grenzwert nicht erreicht ist, muss nur dieser Zeitzähler abgefragt werden.

if (wert < GRENZE) startTime = millis();
if (millis() - startTime > WARTEZEIT)
     digitalWrite(ledPin, HIGH); // GRENZE überschritten UND WARTEZEIT abgelaufen
else
    digitalWrite (ledPin, LOW);

du kannst deine zwei Bedingungen
a) auswerten
b) mit einem Und verknüpfen.

Im Internet findest du derartiges meist in Verbindung mit "Blink Without Delay".

Wenn der Sensor das Kriterium erfüllt, merkst du dir die Zeit (millis())
In einem Zweiten if kontrollierst ob beide Kriteririen (Sensor && Zeit) erfüllt sind.

so als Idee mit einer Statusvariable damit man den ÜBERGANG von einem Status in den anderen schön erkennt:

// https://forum.arduino.cc/t/if-abfrage-wert-und-zeit-bedingung/1121303
// 2023-04-30 by noiasca
// code in thread

const uint8_t inputPin = A0;          // GPIO to measure something
const uint8_t outputPin = 13;         // GPIO with a LED
uint32_t previousMillis;              // for time management
const uint16_t criterionValue = 7;    // criterion for the measurement
const uint16_t criterionTime = 3000;  // criterion for "must be on for x milliseconds"
uint8_t previousState = 0;            // 0 nicht erfüllt, 1 erfüllt - zeit noch nicht erreicht, 2 erfüllt und Zeit erreicht

void measure() {
  if (analogRead(inputPin) > criterionValue && previousState == 0) {
    previousMillis = millis();        // remember current time
    previousState = 1;
    Serial.println("Kriterium Eingang ist erfüllt");
  }

  if (analogRead(inputPin) <= criterionValue && previousState >= 1 ) {
    previousState = 0;
    Serial.println("Kriterium Eingang ist nicht mehr erfüllt");
    digitalWrite(outputPin, LOW);
  }

  if (previousState == 1 && millis() - previousMillis > criterionTime) {
    previousState = 2;
    Serial.println("Kriterium Eingang und Zeit sind erfüllt");
    digitalWrite(outputPin, HIGH);
  }
}

void setup() {
  Serial.begin(115200);
  pinMode( outputPin, OUTPUT);
}

void loop() {
  measure();
}

if (wert < GRENZE) startTime = millis();
digitalWrite(ledPin, millis() - startTime > WARTEZEIT);

Und schon ist ein if weniger.
Sorry, aber ich habe wirklich eine derbe Abneigung gegen überflüssige if.
Im Prinzip ist deine Variante, dieses zweistufig,zu lösen genau auf meiner Linie.

Quasi täglich haben wir hier Besucher, die sich in ihrem if, Verschachtelungs- und Bedingungsgestrüpp verirren.
Auch ich neige dazu, daher meine Abneigung gegen die "Wenn, dann, Denke".
So manche if Konstruktionen erinnern mich eher an einen Irrgarten, als an ein gradliniges, übersichtliches und klares Programm.
Schwierig zu sagen, wo das anfängt, bzw. wo die Grenzen sind.

Für Anfänger etwas verwirrend.

Ein Vergleich gibt 0 wenn er falsch ist und 1 wenn er richtig ist.
Der Vergleich "millis() - startTime > WARTEZEIT" gibt entweder 0 oder 1 zurück, genau das was Du fürs einschalten bzw Ausschalten der LED als 2. Argument in der Funktion digitalWrite() brauchst.

PS: ich mache das auch meistens nicht. Außer ich will jemand schocken, wie man aus 20 Zeilen Code 1Zeile machen kann.

Grüße Uwe

"Schocken" interessiert mich nicht.
Ob jemand die Sprache lernen will, die er/sie/es verwendet, sehr wohl.
Und während des lernen, sollten sich Verwirrungen und Schockzustände langsam auflösen.

Ich gebe dir recht, @combie.
Dass true/false und HIGH/LOW äquivalent sind, sollte auch Anfängern früh klar werden und diese nicht schocken.

Mein Ziel war zu zeigen, dass weder die Vernüpfung zweier Ausdrücke per && noch die Verschachtelung von zwei if Abfragen ineinander nötig ist.

High kann TRUE als auch FALSE sein.

Das ist dir gelungen und diese Tendenz unterstütze ich!
Ich rate ganz klar (und vielleicht auch schon etwas nervig) zu möglichst flachen Verschachtelungen und einfachen Bedingungen.

Wenn dann das eigentliche Problem wirklich sehr kompliziert ist, dann greifen Auslagern/Modularisieren.
In Funktionen/Klassen usw. um die Einzelkomponenten wieder flach und testbar zu bekommen.
millis() - startTime > WARTEZEIT sowas sieht man in meinen Programmen "eigentlich" nicht mehr.
Die Wurst ist zwar korrekt, aber nicht schön!

Aua.
Wie soll ich das verstehen?

Willst Du das nochmal überdenken?

Gruß Tommy

Habe die Zeit gefunden, das Eingangsproblem in "meine Sprache" zu übersetzen.

Dabei mal untersucht, wie viele if im im Programmfluss stecken...
Es ist nur ein einziges ganz flaches if in dem "timer"

if(!trigger) timer.start();

Das Programm tut nicht viel...
Es prüft, ob die 42 an einem analogen Pin dauerhaft überschritten werden und macht dann nach 12,33 Sekunden die LED an. Sobald der Wert unter die Schwelle sinkt, läuft der Timer neu los und die Led geht aus, wenn sie an war.

Die Libs finden sich zu Hauf hier im Forum, z.B. hier

#include <CombieTimer.h>
#include <CombiePin.h>

#include <CombieTypeMangling.h>
using namespace Combie::Millis;

Combie::Pin::OutputPin<3>       led; // Leuchtmelder
Combie::Timer::RisingEdgeTimer  timer      {12.33_Sekunden};  // steigende Flanke wird verzoegert

void setup() 
{
  led.init();
}

void loop() 
{
   led = timer = 42 < analogRead(A1);
}

Es gibt so Situationen wo Richtig falsch ist.

Aber C++ hat keine solchen Situationen.
Grüße Uwe

Der eigentliche Trick ist, dass der timer immer in die Startstellung gezogen bleibt, wenn die Bedingung nicht erfüllt ist. Wenn sie dann erfüllt ist, muss "gar nichts" gemacht werden.

Dass der Zuweisungsoperator ( = ) je nach Objekt etwas sinnvolles nicht-triviales macht, führt zur eleganten Combie-Arduino Welt.

Zwei includes nur um 12.33_sek statt 12330 schreiben zu können, lohnt sich erst, wenn diese schon voreingestellt in jedem neuen Sketch drin sind, finde ich. Kann man sich jedenfalls später und unabhängig zu Gemüte führen

In meiner Brust 2 Herzen schlagen!

  1. Faulheit! Kein Tastendruck zuviel.
  2. Ausdrucksstärke! Je klarer der Ausdruck, desto weniger Irrungen.

Habe ich die Wahl, dann bevorzuge ich den Sieg über die Faulheit.

Beispiel:

unsigned long schulStunde = 2700000ul;

Da muss man schon mal extra denken, was da wohl gemeint sein könnte.
Gut, Gewohnheit und Übung bringt da fix die Erleuchtung.

Millis schulStunde = 45_Minuten;

Das ist doch um Größenordnungen klarer im Ausdruck.
Auch ohne das "Wie macht der das?" zu beantworten, ist es doch sehr sehr klar, was da gemeint ist. Eben eine Variable, welche den Type/Einheit Millis hat, also Millisekunden beinhaltet und mit einer 3/4 Stunde vor besetzt wird
Das bringt den Ausdruck etwas näher an die natürliche Sprache, sollte meines Erachtens nach die Lesbarkeit und das intuitive Erfassen verbessern.
Weniger Lesestopper.

Millis schulStunde = 0.75_Stunden;
Millis schulStunde =  1_Stunde * 3 / 4;

Das ist alles etwas der FORTH Philosophie nachempfunden:

In Forth verändert man die Sprache so lange, bis sie der Problemstellung optimal entspricht.

Auch der Aufbau ist in etwa einer anderen Sprache nachempfunden, und zwar COBOL.
Hier die vier DIVISIONs. Die Aufteilung ist wohl der praktikabelste Aspekt des COBOL.

Klar geht eine solche Ideenübertragung nicht zu 100%, versucht man das, wird man sich wohl verzetteln.

Häufig konzentrieren sich Anfänger auf den Kontrollfluss.
Quasi ausschließlich. Auch alte Hasen sind da nicht gefeit.
Leider entspricht dieses "wenn dann" nicht wirklich der natürlichen Art Entscheidungen zu treffen.

usw.