Problem understanding non blocking delay via millis()

I have got a sketch that reads a button to switch between a dimmer mode and a PIR mode for an LED. The idea is to use a non blocking function for the PIR mode to be able to switch between modes at any time. I have got it kind of working, but somewhere is a mistake, since it doesn't matter whatever value i use for my function, the LED always turns on for the same amount of time. After googling and fiddling around for five hours now, could someone please tell me what's wrong there?

int switchPin = 2;              // switch is connected to pin 2
int pir = 3;                    // pir sensor on pin 3
int potPin = A0;                // brightness control
int statLed = 10;               // mode indicator
int lightOut = 11;              // LED strip will go here

int aVal;                       // variable for reading the pot
int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

long previousMillis = 0;
long interval = 150000;         //wait time for pir mode

int lightMode = 0;              // dimmer mode or pir mode

void setup() {
  pinMode(switchPin, INPUT_PULLUP);    
  pinMode(pir, INPUT);
  pinMode(statLed, OUTPUT);
  pinMode(lightOut, OUTPUT);

  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){

  val = digitalRead(switchPin);           // checking and debouncing
  delay(10);                                        
  val2 = digitalRead(switchPin);     
  if (val == val2) {                             
    if (val != buttonState) {              
      if (val == LOW) {                      
        if (lightMode == 0) {         
          lightMode = 1;                  // go to pir mode
        }
        else {
          lightMode = 0;                  //go to dimmer mode
        }
      }
    }
    buttonState = val;                    // save the new state
  }

  if (lightMode == 0) {                   //dimmer
    aVal = analogRead(potPin);
    analogWrite(lightOut,map(aVal, 0, 1023, 2, 255));
    digitalWrite(statLed,LOW);
  }

  else{                                  //pir
    digitalWrite(statLed, HIGH);

      // here is my problem

    if(digitalRead(pir) == HIGH){
     
      digitalWrite(lightOut, HIGH);
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > interval){
        previousMillis = currentMillis;
      }
    }
    else{
      digitalWrite(lightOut, LOW);
    }
  }
}
    if(digitalRead(pir) == HIGH){
     
      digitalWrite(lightOut, HIGH);
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > interval){
        previousMillis = currentMillis;
      }
    }

What is the point of setting currentMillis and previousMillis? You never use them anywhere else.

I was trying to make use of the blink without delay example, that seemed to make sense. So I guess it doesn't and i started the whole thing out wrong?

So I guess it doesn’t and i started the whole thing out wrong?

No. You just didn’t go far enough.

Look back at the blink without delay example. There is a time that something was last done. There is a current time. There is a comparison of now minus then to interval. If the comparison is true, there is an action block.

You have everything correct except the last part.

      if(currentMillis - previousMillis > interval)Something should happen if this is true....

Something more should happen if this is true…

Do you mean:

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

?

Because that's the point. I can't figure out how to use that in my sketch.

No need to complicate things. The LED is on otherwise the timing period would not have started. The period ends. What should happen ?

Well, it's meant to turn off, obviously. Changed the sketch to this:

    if(digitalRead(pir) == HIGH){
    
     
      digitalWrite(lightOut, HIGH);
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > interval){
        previousMillis = currentMillis;
    digitalWrite(lightOut, LOW);        
    
      }
      
    }
    else{
      digitalWrite(lightOut, LOW);
    }

and changing the interval time still does nothing.

Please the full version of your latest sketch - snippets are no use.

I suspect you shouldn't have the time test inside the "if(digitalRead(pir) == HIGH){"

...R

At least i found out that the time check doesn't seem to ever start, Serial.println(previousMillis); never happens. I still have got no idea why.

Here's the full version:

int switchPin = 2;              // switch is connected to pin 2
int pir = 3;                    // pir sensor on pin 3
int potPin = A0;                // brightness control
int statLed = 10;               // mode indicator
int lightOut = 11;              // LED strip will go here

int aVal;                       // variable for reading the pot
int val;                        // variable for reading the pin status
int val2;                       // variable for reading the delayed status
int buttonState;                // variable to hold the button state

long previousMillis = 0;
long interval = 90000;         //wait time for pir mode

int ledState;
int lightMode = 0;              // dimmer mode or pir mode

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  pinMode(pir, INPUT);
  pinMode(statLed, OUTPUT);
  pinMode(lightOut, OUTPUT);
  Serial.begin(9600);
  buttonState = digitalRead(switchPin);   // read the initial state
}

void loop(){

  val = digitalRead(switchPin);           // checking and debouncing
  delay(10);
  val2 = digitalRead(switchPin);
  if (val == val2) {
    if (val != buttonState) {
      if (val == LOW) {
        if (lightMode == 0) {
          lightMode = 1;                  // go to pir mode
        }
        else {
          lightMode = 0;                  //go to dimmer mode
        }
      }
    }
    buttonState = val;                    // save the new state
  }

  if (lightMode == 0) {                   //dimmer
    aVal = analogRead(potPin);
    analogWrite(lightOut,map(aVal, 0, 1023, 2, 255));
    analogWrite(statLed,map(aVal,0,1023,200,2));
  }

  else{                                  //pir
    digitalWrite(statLed, HIGH);

    // here is my problem

    if(digitalRead(pir) == HIGH){


      digitalWrite(lightOut, HIGH);
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > interval){
        previousMillis = currentMillis;
        Serial.println(previousMillis);
        digitalWrite(lightOut, LOW);

      }

    }
    else{
      digitalWrite(lightOut, LOW);
    }
  }
}

You need to put all the separate acitivities separately in loop(), not nested.

One activity is detecting when to turn the LED on.

Another is detecting the time-out for turning the LED off.

These “tasks” should both run everytime through loop - then they are
effectively independent and run in pseudo-parallel.

loop() should always look like:

void loop ()
{
  if (<condition1>)
    task1 () ;
  if (<condition2>)
    task2 () ;
  if (<condition3>)
    task3 () ;
  ....
  ....
  if (<conditionN>)
    taskN () ;
}

Then be careful to code up the conditions so they assume nothing - for instance
a test for timing-out the LED would be something like

  if (LED_is_on() && millis() - led_time >= led_timeout)
    cancel_LED() ;

Note the hiding of detail in clearly named functions - this is always
a good idea.

Thank you so much! Thats was the crux, i've got it working the way it is supposed to be! Now i can finally get some rest :)