Keep running LEDs after PIR sensor goes back to low?

Hello. I am new to Arduino, and working on building a Star Wars-themed door panel for my kid's bedroom. The plan is to have the panel light up for a few minutes based on input from a PIR sensor (e.g. when he enters/exits the room). Right now I'm working with an Uno R3 board and an Adafruit PIR sensor. At this point, I'm just using the built-in LED for testing the sensor and timing.

I'm having trouble getting both the PIR and the time limiting factor to work together. I tried using an AND (&&) statement for if the PIR was HIGH and then the millis(), but that didn't work. Then I separated them into two IF statements, and that didn't work. Then I tried what's below, which is inverting the first IF to if the PIR is LOW, do nothing, else run the timed portion of the loop. However, this only seems to work while the input from the PIR is still HIGH. Watching the serial output, the loop only seems to work as long as there is motion at the sensor, and the input stays at HIGH. I have experimented with the two pots or dials (sensitivity and timing) on the sensor, but haven't gotten any kind of consistent result.

I've read through many posts today on the forum, but haven't been able to figure this out on my own. Appreciate any input or help.

int motionSensor = 3;
int pirState = LOW;
int val = 0;
unsigned long minutes = 60000;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(motionSensor, INPUT);
  Serial.begin(9600);
}

void loop() {
   
    val = digitalRead(motionSensor);
    if (val == LOW) {}
    
    else {
      
    if (millis() < minutes * 1)

    Serial.println("Motion detected!");
    digitalWrite(LED_BUILTIN, HIGH); 
    delay(1000);                      
    digitalWrite(LED_BUILTIN, LOW);  
    delay(1000);                      
                      
  
    }}

You need to detect when the input becomes HIGH rather than when it is HIGH
See the StateChangeDetection example in the IDE

Also, how is the input wired ? Is it in a known state at all times by means of a pulldown resistor ?

Why if/else when you could test for HIGH ?

Which lines of code should run if the input is HIGH and which should always run regardless of the state of the input ?

I just want to know it effect the battery of the devise or not.

@agri9 please don't hijack other people's topics. If you have a question about batteries, then you can open a dedicated topic. This topic is not an appropriate place for that.

That PIR sensor has a "time" pot that can be adjusted from a few seconds to almost seven minutes.
And a jumper that can be set to once or re-trigger.
An Arduino might not be needed, unless you plan to drive addressable LEDs.
Leo..

1 Like

I'm using power from USB, so battery isn't an issue for me.

Blockquote
You need to detect when the input becomes HIGH rather than when it is HIGH
See the StateChangeDetection example in the IDE

I think I see what you're saying, and Wawa below mentioned the jumper position between retrigger and normal settings. I think moving the jumper over to the "retrigger" position, where the output remains HIGH, and then using a State Change Detection to increment every time the PIR is triggered might do the trick.

Blockquote
Also, how is the input wired ? Is it in a known state at all times by means of a pulldown resistor ?

I edited my original post to add a photo, but it's wired to 5V, GND, and input 3. I don't have a pulldown resister in the circuit.

Blockquote
Why if/else when you could test for HIGH ?

Do you mean test for HIGH with the State Change Detection? I was using If/Else because I didn't yet know a better alternative.

Blockquote
Which lines of code should run if the input is HIGH and which should always run regardless of the state of the input ?

The timer and the LEDs should run when the PIR is HIGH, and the PIR should always run to monitor for triggers.

I meant that instead of

   if (val == LOW) {} // do nothing if LOW
    else {        //it must be HIGH
      
    if (millis() < minutes * 1)
etc

why not

   if (val == HIGH)  //do something if it is HIGH
    {  
    if (millis() < minutes * 1)
etc

There is no need for the if/else

    if (millis() < minutes * 1)  //why mustily by 1 ?
    Serial.println("Motion detected!");  //this will be run if the test is true
    digitalWrite(LED_BUILTIN, HIGH);   //lines below this will be run whether or not it is true
    delay(1000);                      
    digitalWrite(LED_BUILTIN, LOW);  
    delay(1000);  
    Serial.println("Motion detected!");
    digitalWrite(LED_BUILTIN, HIGH); 
    delay(1000);                      
    digitalWrite(LED_BUILTIN, LOW);  
    delay(1000);  

See my comments. IS that what you want to happen ?

Not relevant. That PIR sensor has a push-pull output.
And it has a ~1k5 resistor in series with the output, which means that a 5volt-logic pin might not register a HIGH anymore if you use a pull-down resistor (which makes a voltage divider).
Leo..

I tried using the

if (val == HIGH)  //do something if it is HIGH
    {  
    if (millis() < minutes * 1)

and it triggers on movement, but the time limiter does not work. For some reason the loop continues to run after one minute.

if (millis() < minutes * 1)  //why mustily by 1 ?

I picked one minute just because it's a short enough time for testing purposes to see if it works.