[SOLVED] PIR Sensor runs for a millisecond

I'm trying to create a sensor that flashes the lights when a motion is detected while the red LED is turned on

int redLight=3;
int gLight=2;
int pirPin = 5;
int pirStat;
unsigned long startMillis;
const unsigned long period = 5000;
const byte ledPin = 13;
void setup() {
  // put your setup code here, to run once:
pinMode(redLight,OUTPUT);
pinMode(pirPin, INPUT);
pinMode(gLight,OUTPUT);
Serial.begin(9600);
startMillis=millis();
pinMode(ledPin,OUTPUT);
}
void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(gLight,1);
delay(period);
startMillis=0;
pirStat=digitalRead(pirPin);

  for(startMillis; startMillis<=period; startMillis+=millis())
  {
  digitalWrite(gLight,0);
  digitalWrite(redLight,1);
  if(pirStat == HIGH){
  for (int i = 0; i<5; i++)
  {
    digitalWrite(redLight,1);
    digitalWrite(gLight,1);
    delay(200);
    digitalWrite(redLight,0);
    digitalWrite(gLight,0);
    delay(200);
  }
}

  }

delay(period);
digitalWrite(redLight,0);
digitalWrite(gLight,1);
}

this is the code that i'm using, the lights flash if a movement is detected as soon as the red LED turns on, but not at any point after that (for a millisecond only) and then it stops responding throughout the rest of the loop

can anyone please tell me what i'm doing wrong? thank you!

As millis() has been counting the milliseconds SINCE your program started, the sum will ALWAYS be greater than "period".
Paul

1 Like

How to use millis() for timing:
Several things at a time.
Beginner's guide to millis().
Blink without delay().

1 Like

What Paul_KD7HB said. Also, since you are stuck in the for loop forever you never read the PIR sensor again. I would suggest getting rid of all delays as groundFungus has suggested.

Is there a reason you delay 5 seconds at the beginning and end of loop()?

1 Like

Is there a reason you delay 5 seconds at the beginning and end of loop()?

I delay at the beginning because i want the green light to stay on for five seconds before the loop starts, and at the end because the green light stays on for the whole duration

As long as you are OK with only polling the PIR sensor every 15 seconds and not being able to perform any other processing while being delayed.

Otherwise, you should look at the tutorials Ground Fungus suggested.

1 Like

As long as you are OK with only polling the PIR sensor every 15 seconds and not being able to perform any other processing while being delayed.

Otherwise, you should look at the tutorials Ground Fungus suggested.

i don't mind that, the only thing i need is for the red light to be on for a duration and during that duration the sensor will sense any movement, the problem is that without the delay the red light (inside the loop) only blinks for a millisecond and that's the millisecond at which the PIR sensor is working, i need to keep it working for the whole duration and i can't seem to get it done even with the millis guide

Solved, with the use of millis and a slight issue with the code.
changed the for loop to a while loop

  while(millis() < currentMillis + period)
  {
  digitalWrite(gLight,0);
  digitalWrite(redLight,1);
  pirStat=digitalRead(pirPin); // This was written outside the while loop so it was not constantly updating, moved it in.
  if(pirStat == HIGH){
  for (int i = 0; i<5; i++)
  {
    digitalWrite(redLight,1);
    digitalWrite(gLight,1);
    delay(200);
    digitalWrite(redLight,0);
    digitalWrite(gLight,0);
    delay(200);
    isExit=1;

the variable currentMillis gets the time right before the loop begins and adds the period to it.

And that is still wrong, as is using a "while" loop in a multi-functional program.

The correct construct is:

if((millis() - startMillis) < period)
  

And that is still wrong, as is using a "while" loop in a multi-functional program.

That was actually the whole point, i needed the code to run for (period) of time then re-runs the main loop

An if statement will only do it once

And that was indeed the point.

As long as your code needs to do nothing else at the same time, then you can execute that code and nothing else. Same as using delay().

The point of using event-driven timing with millis() is that the main loop() continuously cycles, sequentially testing each individual event - such as whether your red needs to swap to green or vice versa. There is never a need to use delay(), only to keep track of each component state and a corresponding event time.

This means that you can flash your LEDs and do many other things independently. :sunglasses: