millis timer setting not consistent - help needed

I am not so good in programming and I use Arduino UNO and Arduino IDE in this learning. I try to use One Momentory switch button for setting a Timer. The setting is simple as below :-

Mode 1 : Timer OFF
Mode 2 : LED Blue - Light up means setting Timer for 10 sec
Mode 3 : LED Green - Light up mean setting Timer for 20 sec

The Timer is using millis to count and once time counting elapsed, the LED will be off. The momentory switch will toggle inside a switch case, case 1 is OFF timer, case 2 is setting Timer for 10 sec, case 3 is setting timer for 20 sec.

My problem is sometimes when the switch is at mode 2 after mode 1, the elapsed timing is not correct, seem like the elapsed time is not reset if i go through mode 1. I am not very sure where is the problem of the program flow.

There is not debounce issue because when I check with Serial Monitor, every press have the mode display in sequence of 1,2,3,1,2,3... The code is at below :-

/*Using Momentory Button to set timer setting
 * Developed on Arduino UNO
 * Case 1 is OFF, Case 2 is 10 Sec, Case 3 is 20 sec
 * 
 */

int TimerPin = 7;
int mode;
boolean TimerState;
boolean timerLapsedState;

unsigned long previousMillis = 0;  
unsigned long elapsed_time;
unsigned long set_time;//1000 = 1 sec

void setup() {
  // put your setup code here, to run once:
pinMode (TimerPin, INPUT);//Momentory Switch Pin
pinMode (8, OUTPUT); //BLUE 10 sec
pinMode (9, OUTPUT); //GREEN 20 sec
pinMode (11, OUTPUT); //Indicate Timer ON Status led, not turn on yet
Serial.begin(9600);
timerLapsedState = false;
}


void timerCount()
{  //To use millis to count time
    
    if (TimerState==true) {
        unsigned long currentMillis = millis();
        unsigned long elapsedTime = (unsigned long)(currentMillis - previousMillis);
        if (elapsedTime >= set_time){//if Time lapsed    
          Serial.print("Time Lapsed");
          Serial.println(elapsedTime);
          
          previousMillis = currentMillis;
          elapsedTime = 0;    
           timerLapsedState = true;      //set timer_status to lapsed or over.
           digitalWrite(8, LOW);//off all led
           digitalWrite(9, LOW);
           digitalWrite(11, LOW);
           }
   }
 }



void loop(void){ 

 int TimerButtonState = digitalRead(TimerPin);
 if(TimerButtonState == LOW) //low trigger, usually tied to high 
 {
   delay(400);
   timerLapsedState = false;
   mode ++;
   
   //Reset count if over max mode number
   if(mode == 4)
   {
     mode = 1;
   }
   Serial.println(mode);
 
 }
 else
 
   //Come to here only if timer button is pressed again
   if (timerLapsedState==false) {
   switch (mode) {
   case 1://nothing 
     delay(100);
     Serial.println("All LED Off");
     TimerState = false;
     digitalWrite(8, LOW);
     digitalWrite(9, LOW);
     digitalWrite(11, LOW);
     break;
     
   case 2://set timer to 10 sec
     delay(100);
     TimerState = true;
     Serial.println("On LED for 10 SEC");
       digitalWrite(8, HIGH);//on Blue LED for 10 sec
       digitalWrite(9, LOW);
       
     set_time = 10000;//10 sec
     timerCount();  
     break;
   
   case 3://set timer to 20 sec
     delay(100);
     TimerState = true;
     Serial.println("On LED for 20 SEC");
     digitalWrite(8, LOW);
     digitalWrite(9, HIGH);//On Green LED for 20 sec
     
     set_time = 20000;//20 sec
    
     timerCount();
     break;

    }
   }
}

Try to change the state of the LED's only when the button is pressed and let the timeout being handled when the button is not pressed.

I suspect the problem is that when you change state you do not update the value of previousMillis so the new timing is using whatever value existed from the last timing sequence.

Also, in the circumstances I thing a better name for the variable would be timerStartTime rather than previousMillis. Using meaningful names often helps to bring logical errors into focus.

Maybe something like this

if(TimerButtonState == LOW) //low trigger, usually tied to high 
 {
   delay(400);
   timerLapsedState = false;
   mode ++;
   timerStartTime = millis();

and then in the function timerCount() - which also seems to me an inappropriate name as it is not counting anything

void timerCount() {
   if (timerState == true) {
      if (millis() - timerStartTime >= setTime) {
          // time is up so do the stuff

...R

This is how I would re-write it to make it work and make it readable.

/*Using Momentory Button to set timer setting
   Developed on Arduino UNO
   Case 1 is OFF, Case 2 is 10 Sec, Case 3 is 20 sec
*/


const byte TimerButtonPin = 7;
const byte BlueLEDPin = 8;
const byte GreenLEDPin = 9;
const byte StatusLEDPin = 11;


int Mode = 0;


boolean TimerRunning = false;


unsigned long PreviousMillis = 0;
unsigned long CurrentTimeInterval; //1000 = 1 sec


void setup()
{
  Serial.begin(9600);


  // put your setup code here, to run once:
  pinMode (TimerButtonPin, INPUT);//Momentory Switch Pin
  pinMode (BlueLEDPin, OUTPUT); //BLUE 10 sec
  pinMode (GreenLEDPin, OUTPUT); //GREEN 20 sec
  pinMode (StatusLEDPin, OUTPUT); //Indicate Timer ON Status led, not turn on yet


  TimerRunning = false;
}




void TimerCheck()
{
  if (!TimerRunning)
    return;


  //To use millis to count time
  unsigned long currentMillis = millis();
  unsigned long elapsedTime = currentMillis - PreviousMillis;
  if (elapsedTime >= CurrentTimeInterval) //if Time lapsed
  {
    Serial.print("Time Lapsed");
    Serial.println(elapsedTime);
    TimerRunning = false;
    //off all led
    digitalWrite(BlueLEDPin, LOW);
    digitalWrite(GreenLEDPin, LOW);
    digitalWrite(StatusLEDPin, LOW);
  }
}




void loop(void)
{
  TimerCheck();


  boolean timerButtonPressed = digitalRead(TimerButtonPin) == LOW;  //low trigger, usually tied to high
  if (!TimerRunning && timerButtonPressed)
  {
    delay(400);
    Mode ++;


    //Reset count if over max mode number
    if (Mode == 4)
    {
      Mode = 1;
    }
    Serial.println(Mode);


    switch (Mode)
    {
      case 1://nothing
        Serial.println("All LED Off");
        TimerRunning = false;
        digitalWrite(BlueLEDPin, LOW);
        digitalWrite(GreenLEDPin, LOW);
        digitalWrite(StatusLEDPin, LOW);
        break;


      case 2://set timer to 10 sec
        Serial.println("On Blue LED for 10 SEC");
        CurrentTimeInterval = 10000; // 10 sec
        PreviousMillis = millis();
        TimerRunning = true;
        digitalWrite(BlueLEDPin, HIGH); //on Blue LED for 10 sec
        digitalWrite(GreenLEDPin, LOW);
        digitalWrite(StatusLEDPin, HIGH);
        break;


      case 3:  //set timer to 20 sec
        Serial.println("On Green LED for 20 SEC");
        CurrentTimeInterval = 20000; // 20 sec
        PreviousMillis = millis();
        TimerRunning = true;
        digitalWrite(BlueLEDPin, LOW);
        digitalWrite(GreenLEDPin, HIGH);
        digitalWrite(StatusLEDPin, HIGH);
        break;
    }
  }
}

Thank you John, this was beautifully written. This help a lot in my learning.