Relay switch come on for 15 seconds using millis

I'm having a hard time with using millis in my sketch. I have read UKHeliBob's "Using millis() for timing. A beginners guide" Using millis() for timing. A beginners guide - Introductory Tutorials - Arduino Forum but it's not registering in my head for how I want to use it, I need some extra guidance. I want to have LED strips come on in my hallway at night for 15 seconds then go off until next detection. I am using an Arduino Nano with a PIR sensor to activate a relay. Later I will add the LED strips and two more PIRs to my project. Can someone help with the use of millis in my code? Thank you in advance.

(Side note: I originally wanted to use IR sensors for smart cars in my project instead of the PIR sensors but the range was too short. If anyone has any suggestions on something other than the PIR sensors, that would be greatly appreciated also.)

int relayPin = 12;                // choose the pin for the LED
int pir_Pin = 11;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status

boolean relayState = true;           // relayState used to set relay
unsigned long lastLedTime = 0;       // will store last time relay was updated (the last time LED turned on or off)
unsigned long ledOn = 15000;         // milliseconds of on-time for relay (LED on 15 seconds)

void setup() {
  pinMode(relayPin, OUTPUT);      // declare LED as output
  pinMode(pir_Pin, INPUT);     // declare sensor as input

  Serial.begin(9600);
}

void loop() {
  unsigned long currentTime = millis();

  val = digitalRead(pir_Pin);  // read input value
  if (val == HIGH) {            // check if the input is HIGH

    if (pirState == LOW) {
      //      // we have just turned on
      Serial.println("Motion detected!");
      //      // We only want to print on the output change, not state
      pirState = HIGH;
    }
    relayState = true;
    digitalWrite(relayPin, LOW);// turn LED ON
    lastLedTime = currentTime;// Save the time

  } else {
    digitalWrite(relayPin, HIGH); // turn LED OFF
    if (pirState == HIGH) {
      // we have just turned off
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}

You did not post what’s actually wrong with your code. I would suspect the relay does not stay on for 15 s because you immediately shut it off again if no motion is detected. I also can’t see any implementation of millis() where you would count 15s.

Also it’s enough to initialize current time as unsigned long once before setup, not in every loop.

I would think you'd want some logic like:

if((pirState==HIGH)&((millis()-lastLedTime)>ledOn)) {
digitalWrite(relayPin, HIGH); // turn LED OFF
pirState = LOW;
}

chuckyx:
You did not post what's actually wrong with your code.

Oops! Yes it doesn't stay on for 15 seconds. It's on for 2 seconds then doesn't detect again until 5 seconds later.

DaleScott:
I would think you'd want some logic like:

if((pirState==HIGH)&((millis()-lastLedTime)>ledOn)) {
digitalWrite(relayPin, HIGH); // turn LED OFF
pirState = LOW;
}

Thank you. I will try that.

DaleScott:
I would think you'd want some logic like:

if((pirState==HIGH)&((millis()-lastLedTime)>ledOn)) {
digitalWrite(relayPin, HIGH); // turn LED OFF
pirState = LOW;
}

Thank you. This is what I came up with.

int relayPin = 12;// choose the pin for the LED
int pir_Pin = 11;               // choose the input pin (for PIR sensor)
int val = 0;                     // variable for reading the pin status
unsigned long startMillis;  //some global variables available anywhere in the program
int pirState = LOW;             // we start, assuming no motion detected


void setup() {

  Serial.begin(9600);
  pinMode(relayPin, OUTPUT);      // declare Relay as output
  digitalWrite(relayPin, HIGH); //Make sure the Relay is in un-powered position at startup
  pinMode(pir_Pin, INPUT);     // declare sensor as input
}

void loop() {

  val = digitalRead(pir_Pin); // read input value

  //  if (val == HIGH) {    // check if the input is HIGH
  //    if (pirState == LOW) {
  if ((val == HIGH) & (pirState == LOW)) {
    digitalWrite(relayPin, LOW); // turn LED ON
    Serial.println("Motion detected!"); // We only want to print on the output change, not state
    startMillis = millis();  // Save the time
    pirState = HIGH;
  }
  //}

  if ((pirState == HIGH) & ((millis() - startMillis) >= 15000)) {
    digitalWrite(relayPin, HIGH); // turn LED OFF
    Serial.println("Motion ended!"); // We only want to print on the output change, not state
    pirState = LOW;
  }


}