LED mit einem Bewegungssensor für ein bestimmtes Zeitintervall einschalten

Hi, ich versuche eine LED mit einem Bewegungssensor und einem Schalter anzusteuern.
Wenn von dem Bewegungssensor ein Impuls kommt und der Schalter in der An-Position ist soll sich eine LED für ca. 20sek. einschalten und danach wieder ausgehen.
(Beide Inputs habe ich mit internem Pullup angeschlossen)

Leider habe ich das Problem, dass beim Anschließen des Arduinos an Strom (also bei jedem Hochfahren oder Reseten), sogar wenn der Schalter in der Aus-Position ist, die LED für 20s. leuchtet. Ich weiß nicht wie ich das beheben kann, ich habe schon versucht die Klammern anders zu positionieren und die Position des Timers zu verändern, hat aber nichts gebracht.

Hoffentlich kann mir jemand helfen.
Grüße Joschi

  {

     if ((digitalRead(Bewegungsmelder) == LOW) && (digitalRead(Schalter_An) == LOW))
      
        Timer_LED_1 = millis();
      
      { if ( millis() < interval_LED_20s + Timer_LED_1 )
        
          digitalWrite(LED_1, HIGH);
        
        else
        
          digitalWrite(LED_1, LOW);
        
      }

Das Frasgment nützt uns überhaupt nichts. Zeige bitte den kompletten Sketch.

Gruß Tommy

int Bewegungsmelder = 22;
int Schalter_An = 24;
int LED_1 = 26;
long interval_LED_20s = 20000;
long Timer_LED_1 = 0;

void setup() {

  pinMode(Bewegungsmelder, INPUT_PULLUP);
  pinMode(Schalter_An, INPUT_PULLUP);
  pinMode(LED_1, OUTPUT);
  digitalWrite(LED_1, LOW);
}

void loop() {
    if ((digitalRead(Bewegungsmelder) == LOW) && (digitalRead(Schalter_An) == LOW))
      Timer_LED_1 = millis();
    { if (millis() < interval_LED_20s + Timer_LED_1 )
        digitalWrite(LED_1, HIGH);
      else
        digitalWrite(LED_1, LOW);
    }
}

(deleted)

da du die LED nicht im 20 Sekundentakt "blinken" lassen möchtest sondern LED ein wenn IR-Sensor impuls gibt
dann 20 Sekunden leuchten danach so lange aus bis IR-Sensor neu schaltet (kann ja auch erst nach Stunden / Tagen sein)

benötigt man eine weitere boolesche Variable. Ich nenne sie jetzt mal EinschaltZeitLaueft

Diese Variable wird auf true gesetzt wenn der IR-Sensor neu geschaltet hat. Wenn die 20 Sekunden abgelaufen sind
wird die Variable auf false gesetzt.

Die LED wird nur eingeschaltet wenn die Variable EinschaltZeitLaueft true ist.

Wenn IR-Sensor impuls gibt und variable EinschaltZeitLaueft == false
dann
EinschaltZeitLaueft = true

Timer starten

if (EinschaltZeitLaueft)
LED einschalten
else
LED ausschalten

if (20 Sekunden vorbei)
EinschaltZeitLaueft = false

jetzt mach einen ersten Versuch diese Logig in dein Programm einzubauen und dann poste den ganzen Sketch
mit entsprechenden Fragen

viele Grüße Stefan

Hallo Peter,

das versetzen der Klammer noch oben wird wohl das anfängliche leuchten der LED wegnehmen.
Es bleiben aber diverse Probleme.

Variablen denen Werte der function mills() zugewiesen werden sollten grundsätzlich unsigned long sein.
Die Rollover-Problematik von millis() bekommt man meines Wissens nach nur in den Griff wenn man

die Zeitabfrage so programmiert

if (currentMillis - previousMillis >= interval_LED_20s ) {
  previousMillis = currentMillis 
}

Das weitere Zeitabfragen erfolgt nur dann wenn der IR-Sensor die ganze Zeit auf LOW bleibt.
Wenn das so ist könnte man den IR-Sensor auch gleich zum Schalten der LED nehmen.
Der Schalter wäre dann einfach die Stromversorgung von IR-Sensor und LED ein/ausschalten.
Dann hätte man die gleiche Funktionalität.

Wenn der Arduino noch mehr im Zusammenspiel mit dem IR-Sensor machen soll dann braucht man den Arduino natürlich. Wenn der IR-Sensor nur einen Impuls gibt dann braucht man die boolsche Variable wie ich es oben beschrieben habe
viele Grüße Stefan

Jetzt habe ich es mal mit der booleschen Variable umgesetzt. Jetzt schaltet sich zwar die LED nicht mehr am Anfang an, geht aber nach den 20s nicht mehr aus.

int Bewegungsmelder = 22;
int Schalter_An = 24;
int LED_1 = 26;
unsigned long interval_LED_20s = 20000;
long Timer_LED_1 = 0;
bool EinschaltZeitLaueft = false;

void setup() {

  pinMode(Bewegungsmelder, INPUT_PULLUP);
  pinMode(Schalter_An, INPUT_PULLUP);
  pinMode(LED_1, OUTPUT);
  digitalWrite(LED_1, LOW);
}

void loop()

{ if  ((digitalRead(Bewegungsmelder) == LOW) && (EinschaltZeitLaueft == false) && (digitalRead(Schalter_An) == LOW))
    EinschaltZeitLaueft = true;
  Timer_LED_1 = millis();


  if (EinschaltZeitLaueft == true)
  {
    digitalWrite(LED_1, HIGH);
  }
  else
  {
    digitalWrite(LED_1, LOW);
  }

  if (millis () > interval_LED_20s + Timer_LED_1 )
  {
    EinschaltZeitLaueft = false;
  }
}

Wo ist da eine Konstante?

Gruß Tommy

Ich mache das zum ersten Mal, deshalb bin ich mir nicht sicher, ob es so überhaupt passt- Mit der Konstante meinte ich die Variable (EinschaltZeitLaeuft)

die if-bedingungen

  if (EinschaltZeitLaueft == true)
  {
    digitalWrite(LED_1, HIGH);
  }
  else
  {
    digitalWrite(LED_1, LOW);
  }

  if (millis () > interval_LED_20s + Timer_LED_1 )
  {
    EinschaltZeitLaueft = false;
  }

müssen ausserhalb der obersten if-bedingung stehen

{ if  ((digitalRead(Bewegungsmelder) == LOW) && (EinschaltZeitLaueft == false) && (digitalRead(Schalter_An) == LOW))
    EinschaltZeitLaueft = true;
  Timer_LED_1 = millis();
} // hier schon Klammer zu

Da in der oberen Bedingung jetzt auf (EinschaltZeitLaueft == false) abgefragt wird
und wenn die drei Bedingungen erfüllt sind
EinschaltZeitLaueft = true
gesetzt wird ist die Bedingung nicht mehr erfüllt.
Das bedeutet so lange die anderen If bedingungen innerhalb der Klammer sind werden sie gar nicht mehr abgefragt.

Deshalb müssen Sie außerhalb stehen. Das Schalten der der LED wird ja jetzt von der Variable EinschaltZeitLaueft gesteuert und nicht mehr von der obersten If-bedingung

Wenn man das Verhalten eines Programms "komisch" findet oder es nicht versteht, baut man serielle Ausgabe ein.
Das hilft in 95% der Fälle auf die Sprünge.
Dann hättest du dich zuerst gewundert warum denn die anderen If-bedingungen gar nicht mehr true werden und die entsprechende serielle Ausgabe ausbleibt,

int Bewegungsmelder = 22;
int Schalter_An = 24;
int LED_1 = 26;
unsigned long interval_LED_20s = 20000;
long Timer_LED_1 = 0;
bool EinschaltZeitLaueft = false;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  pinMode(Bewegungsmelder, INPUT_PULLUP);
  pinMode(Schalter_An, INPUT_PULLUP);
  pinMode(LED_1, OUTPUT);
  digitalWrite(LED_1, LOW);
  Serial.println("Setup-Ende");
}

void loop() {
  if  ((digitalRead(Bewegungsmelder) == LOW) && (EinschaltZeitLaueft == false) && (digitalRead(Schalter_An) == LOW))
    EinschaltZeitLaueft = true;
  Timer_LED_1 = millis();
  Serial.println("if  ((digitalRead(Bewegungsmelder) == LOW) usw. ist true");


  if (EinschaltZeitLaueft == true)
  {
    digitalWrite(LED_1, HIGH);
    Serial.println("LED HIGH");
  }
  else
  {
    digitalWrite(LED_1, LOW);
    Serial.println("LED LOW");
  }

  if (millis () > interval_LED_20s + Timer_LED_1 )
  {
    EinschaltZeitLaueft = false;
    Serial.println("Zeit abgelaufen setze EinschaltZeitLaueft false");
  }
}

viele Grüße Stefan

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

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

Combie::Pin::InvInputPin<22> bewegungsmelder; // invertierender Input
Combie::Pin::InvInputPin<24> schalter; // invertierender Input
Combie::Pin::OutputPin<26>   led ;

Combie::Tools::FlankenErkennung  flankenerkennung;
Combie::Timer::FallingEdgeTimer  toff {20_sec};  // Timer Leuchtdauer

void setup() 
{
  bewegungsmelder.initPullup();
  schalter.initPullup();
  led.init();
}

void loop() 
{
  led = toff = flankenerkennung = schalter && bewegungsmelder;
}

CombieLib.zip

Ich habe es jetzt ausprobiert und es funktioniert so wie ich es wollte.
Danke

int Bewegungsmelder = 22;
int Schalter_An = 24;
int LED_1 = 26;
unsigned long interval_LED_20s = 5000;
long Timer_LED_1 = 0;
bool EinschaltZeitLaueft = false;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  pinMode(Bewegungsmelder, INPUT_PULLUP);
  pinMode(Schalter_An, INPUT_PULLUP);
  pinMode(LED_1, OUTPUT);
  digitalWrite(LED_1, LOW);
  Serial.println("Setup-Ende");
}

void loop() {
  {
    if  ((digitalRead(Bewegungsmelder) == LOW)  && (digitalRead(Schalter_An) == LOW))
    { EinschaltZeitLaueft = true;
      Timer_LED_1 = millis();
      Serial.println("if  ((digitalRead(Bewegungsmelder) == LOW) usw. ist true");
    }
  }
  {
    if (EinschaltZeitLaueft == true)
    {
      digitalWrite(LED_1, HIGH);
      Serial.println("LED HIGH");
    }
    else
    {
      digitalWrite(LED_1, LOW);
      Serial.println("LED LOW");
    }
  }
  {
    if (millis () > interval_LED_20s + Timer_LED_1 )
    {
      EinschaltZeitLaueft = false;
      Serial.println("Zeit abgelaufen setze EinschaltZeitLaueft false");
    }
  }
}

und es funktioniert so wie ich es wollte.

if (millis () > interval_LED_20s + Timer_LED_1 )

Das fällt dir nach 49,x Tagen auf die Füße.

So geht's aber problemlos, auch während eines Nulldurchgangs von millis(),
wenn Timer_LED_1 unsigned long ist

  if (millis () - Timer_LED_1> interval_LED_20s  )

(deleted)

michael_x:
  if (millis () - Timer_LED_1> interval_LED_20s  )

Ich würde >= vorschlagen.

Gruß Tommy

Okay.
Wenn ich meinen Arduino von der Stromquelle löse und wieder dran mache bzw. wenn ich den Resetknopf drücke - werden dann die millis() auch wieder auf Null gesetzt oder bleiben sie gespeichert?

Bei dem Sketch wollte ich es erstmal mit LED´s ausprobieren, bei der finalen Fassung soll aber der Bewegungssensor einen Motor akktivieren. Es soll ein Schulprojekt werden, und deshalb wird es jeweils nur für kurze Zeit im Betrieb sein (max. 1 Tag am Stück) und dann wieder ausgeschaltet. Also wird das Board nie im Dauerbetrieb sein.

Wenn sich die millis selbst nach dem Ausschalten "reseten" würden, hätte ich weniger was ich noch am Sketch ändern müsste. Was aber blöd wäre, wenn es irgendwann ausfällt. (Wenn sich diese knapp 50 Tage gesammelt haben).

Grüße

Die millis zählen vom Start (Reset oder Strom an). Trotzdem solltest Du Dir die richtige Vorgehensweise angewöhnen. Es könnte ja sein, dass Du mal etwas länger laufendes bauen willst und Dich dann wunderst, warum es nach 49,x Tagen aussteigt.

Gruß Tommy

joschi01k:
Wenn sich die millis selbst nach dem Ausschalten "reseten" würden, hätte ich weniger was ich noch am Sketch ändern müsste. Was aber blöd wäre, wenn es irgendwann ausfällt. (Wenn sich diese knapp 50 Tage gesammelt haben).

Und du solltest auch an zukünftige Projekte denken, wo der Controller standig läuft.
Also auch hier gleich die richtige/bessere Schreibweise einsetzen.

Gut,

ich habe es auf if (millis () - Timer_LED_1> interval_LED_20s ) verändert, hat sich doch ziemlich schnell erledigen lassen.