Run multiple if else simultaneously with millis

Hello,
I have a switch which uses a, ESP8266 and relay module connected to it.
It operates in two modes based on the selection made on a web page.
In mode 1 (Auto Mode), it turnes on and off based on the value from a sensor which my sensor module uploads to the website.
In mode 2 (Timer Mode), it operates based on timer value and duration entered in the website.
All the values entered in the website is stored in SQL database and are fetched from the database and compared.

So the issue I am facing is as follows.
Everything works fine in both the modes. But when I am in Timer Mode and I switch to Auto Mode, it waits till the timer duration is complete, before switching to Auto Mode. Is there any way to modify the program in such a way that it monitors the switch state all the time and changes mode accordingly even if the timer is running?

Relevant part of the code is as below

int ontime = 5000;

void loop() {
  time_now = millis();

 if (timermode == 0 && setvalue > sensorvalue) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Set Value is more than Actual Value. Switch Activated");
    while(millis() < time_now + ontime){
      yield();
     }
    digitalWrite(device1_pin, LOW);
    Serial.println("Switch is OFF after Set duration in Auto Mode");
   } else if (timermode == 0 && setvalue < sensorvalue) {
    digitalWrite(device1_pin, LOW);
    Serial.println("Set Value is less than Actual Value. Switch is OFF");
  }

  if (timermode == 1) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Switch is ON in Timer Mode");
    while(millis() < time_now + (duration*1000)){
      yield();
     }
    digitalWrite(device1_pin, LOW);
    Serial.println("Switch is OFF after Set duration in Timer Mode");
    while(millis() < time_now + (timer*1000)){
      yield();
     }
  }
}

Could you put your sketch between lines with three backslash-single-quotes ?

```
Your sketch
```

Or use the </> button.

If we see only a part of the sketch, then we don't know if the variables are the right type.

Can you write your sketch without waiting ?
This is waiting:

while(millis() < time_now + (duration1000))
{
  yield();
}

You could replace that while-loop with a delay().

The Blink Without Delay shows how to use millis().

Your "millis() < time_now + (duration1000)" is not okay.

Thanks a lot for the quick response.. sorry for not posting the code properly. I have rectified that..
I am trying to understand the "Blink Without Delay" example. I am a newbie and may have to trouble you again if I don't get anywhere.
Sorry about that :slight_smile:

No need to say sorry. Really. You can ask as many questions as you like. If the readers can see that you have done at least a single step forward through own effort they will anser again and again.

The while loops counteract on what is called non-blocking timing

Me personal I think it is very important to give an easy to understand basic analogon how millis() is used.
This is what most millis() tutorials are missing. So here it is:
as an allday example with easy to follow numbers
delay() is blocking. As long as the delay is "delaying" nothing else of the code can be executed.
Now there is a technique of non-blocking timing.
The basic principle of non-blocking timing is fundamental different from using delay()
You have to understand the difference first and then look into the code.
otherwise you might try to "see" a "delay-analog-thing" in the millis()-code which it really isn't
Trying to see a "delay-analog-thing" in millis() makes it hard to understand millis()
Having understood the basic principle of non-blocking timing based on millis() makes it easy to understand.

imagine baking a frosted pizza
the cover says for preparation heat up oven to 200°C
then put pizza in.
Baking time 10 minutes

You are estimating heating up needs 3 minutes
You take a look onto your watch it is 13:02 (snapshot of time)
You start reading the newspaper and from time to time looking onto your watch
watch 13:02 not yet time
watch 13:03 not yet time
watch 13:04 not yet time 13:04 - 13:02 = 2 minutes is less than 3 minutes
watch 13:05 when did I start 13:02? OK 13:05 - 13:02 = 3 minutes time to put pizza into the oven

New basetime 13:05 (the snapshot of time)
watch 13:06 not yet time
watch 13:07 not yet time
watch 13:08 not yet time (13:08 - 13:05 = 3 minutes is less than 10 minutes
watch 13:09 not yet time
watch 13:10 not yet time
watch 13:11 not yet time
watch 13:12 not yet time
watch 13:13 not yet time
watch 13:14 not yet time (13:14 - 13:05 = 9 minutes is less than 10 minutes
watch 13:15 when did I start 13:05 OK 13:15 - 13:05 = 10 minutes time to eat pizza (yum yum)

You did a repeated comparing how much time has passed by
This is what non-blocking timing does

In the code looking at "How much time has passed by" is done

currentTime - startTime >= bakingTime

bakingTime is 10 minutes

13:06 - 13:05 = 1 minute >= bakingTime is false
13:07 - 13:05 = 2 minutes >= bakingTime is false
...
13:14 - 13:05 = 9 minutes >= bakingTime is false
13:15 - 13:05 = 10 minutes >= bakingTime is TRUE time for timed action!!

if (currentTime - previousTime >= period) {

it has to be coded exactly this way because in this way it manages the rollover from Max back to zero
of the function millis() automatically

baldengineer.com has a very good tutorial about timing with function millis() too .

There is one paragraph that nails down the difference between function delay() and millis() down to the point:

The millis() function is one of the most powerful functions of the Arduino library. This function returns the number of milliseconds the current sketch has been running since the last reset. At first, you might be thinking, well that’s not every useful! But consider how you tell time during the day. Effectively, you look at how many minutes have elapsed since midnight. That’s the idea behind millis()!

Instead of “waiting a certain amount of time” like you do with delay(), you can use millis() to ask “how much time has passed”?

I relation to your code

    digitalWrite(device1_pin, HIGH);
    Serial.println("Switch is ON in Timer Mode");

if (enough time has passed by)  
    digitalWrite(device1_pin, LOW);
    Serial.println("Switch is ON in Timer Mode");

best regards Stefan

1 Like

That was a very detailed explanation and I'm glad that there are people out there to help..
The baldengineer.com website really helped an I am getting a hang of what non-blocking code is all about..
Thanks alot for the detailed explanation..

I edited the code and the AUTO mode is kind of working as expected. I changed it as below

if (timermode == 0 && setvalue > sensorvalue) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Set Value is more than Actual Value. Switch Activated");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Auto Mode");
   }
   
   } else if (timermode == 0 && setvalue < sensorvalue) {
    digitalWrite(device1_pin, LOW);
    Serial.println("Set Value is less than Actual Value. Switch is OFF");
  }

When I switch to TIMER mode, the switch turns on, stays ON for the set duration and turns OFF, which is good.
But it is expected to remain OFF for the "timer" duration, and then turn back on, remain ON for the set "duration" and then turn OFF. This cycle is not happening. The code I wrote is as below

if (timermode == 1) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Switch is ON in Timer Mode");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
      if ((unsigned long)(currentMillis - previousMillisTimer) >= timer) {
      
      previousMillisTimer = currentMillis;
      digitalWrite(device1_pin, HIGH);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
  }

What could I be doing wrong?

You should always post the complete sketch. From the snippet I can't see how you defined the variables

Also a typecast to unsigned long looks odd to me. Maybe it is working never tried it that way
Just define all variables that are related to millis() as unsigned long and then your if-conditions look like this

if ((currentMillis - previousMillisDuration) >= duration)

The variablename previousMillisDuration is confusing it is not a duration it is the previous timestamp

for programming different durations you could assign different values to a duration-variable and then check always with the same if-condition.

best regards Stefan

Sorry about that..
Please see below

unsigned long previousMillisDuration=0;
unsigned long previousMillisTimer=0;

boolean Switchstate = false;

void setup () {

  Serial.begin(115200);
  pinMode(device1_pin, OUTPUT);
  }

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

if (timermode == 0 && setvalue > sensorvalue) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Set Value is more than Actual Value. Switch Activated");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Auto Mode");
   }
   
   } else if (timermode == 0 && setvalue < sensorvalue) {
    digitalWrite(device1_pin, LOW);
    Serial.println("Set Value is less than Actual Value. Switch is OFF");
  }

if (timermode == 1) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Switch is ON in Timer Mode");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
      if ((unsigned long)(currentMillis - previousMillisTimer) >= timer) {
      
      previousMillisTimer = currentMillis;
      digitalWrite(device1_pin, HIGH);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
  }

I prefer not to use the cast. The cast is confusing and gives the impression that something needs to be fixed. If something needs to be fixed, then the millis-timer does not work.

if ((unsigned long)(currentMillis - previousMillisDuration) >= duration)   // with cast for no reason
if (currentMillis - previousMillisDuration >= duration)    // okay, this is what I use
if ((currentMillis - previousMillisDuration) >= duration)   // okay

Can you take some time to go through the next lines ? It is like going back to school :wink:

Could you read my post in an other topic: Continuous serial communication between arduino and pc - #4 by Koepel and click on that video what Andreas Spiess thinks about it.
Andreas Spiess is referring to non-blocking code with millis() and he mentioned someone who uses also a Finite State Machine with that. He calls it: wearing a shirt inside out.

Your sketch is controlled by the variable 'timermode'. So the sketch can be in a few different states depending on that variable. You could call that variable 'state'.

Could you have a look at a Finite State Machine ? If you see what is going on, then it is simple: The Finite State Machine | Majenko Technologies

You could try my example millis_and_finite_state_machine.ino

If you understand the Finite State Machine with millis(), then you are an advanced Arduino programmer, even if you have to wear your shirt inside out.

I re-read your description but I'm unsure if understand it right.
It would be very good if you post an example with easy to calculate numbers.

at the moment I understand your description this way

no timing at all just switching on/off depends only on the sensor-value not on any times.
But your code has timing for

if (timermode == 0 && setvalue > sensorvalue) {

So please give examples for each case
automode is activated
20:00:00 sensor-value goes below threshold what should happen
time goes on
20:00:01
20:00:02
...
what shall happen?

next case
sensorvlaue goes below threshold what shall hapen?

timer-mode gets activated
21:00:00
21:00:01
21:00:02
21:00:03 which condition becomes true? What shall happen?
21:00:04
21:00:05
....
which condition becomes true? What shall happen ?

best regards Stefan

"timermode" is actually the state of the selector switch in the webpage which selects between "AUTO" and "TIMER" modes. When it is "0" it is in "AUTO" mode and when it is "1" it is in "TIMER" mode.. I am posting the full code below. Hope that will give full understanding of what I am trying to achieve..

Please note that some parts of the code may be irrelevant as I am still testing.. also removed the website address as I am not allowed to share that..

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>

static const uint8_t D0   = 16;
static const uint8_t D1   = 5;
static const uint8_t D2   = 4;
static const uint8_t D3   = 0;
static const uint8_t D4   = 2;
static const uint8_t D5   = 14;
static const uint8_t D6   = 12;
static const uint8_t D7   = 13;
static const uint8_t D8   = 15;
static const uint8_t D9   = 3;
static const uint8_t D10  = 1;

int device1_pin = D5;
int device2_pin = D6;
int device3_pin = D7;
int device4_pin = D8;

int sensorvalue = 0;
int setvalue = 0;
int timer = 0;
int duration = 0;
int timermode = 0;
int ontime = 5000;
unsigned long previousMillisDuration=0;
unsigned long previousMillisTimer=0;

boolean Switchstate = false;

void setup () {

  Serial.begin(115200);
  WiFiManager wifiManager;
  wifiManager.autoConnect("Device");
  Serial.println("Connected to WiFi");
  pinMode(device1_pin, OUTPUT);
  pinMode(device2_pin, OUTPUT);
  pinMode(device3_pin, OUTPUT);
  pinMode(device4_pin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
 
  
  if (timermode == 0 && setvalue > sensorvalue) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Set Value is more than Actual Value. Switch Activated");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Auto Mode");
   }
   
   } else if (timermode == 0 && setvalue < sensorvalue) {
    digitalWrite(device1_pin, LOW);
    Serial.println("Set Value is less than Actual Value. Switch is OFF");
  }

  if (timermode == 1) {
    digitalWrite(device1_pin, HIGH);
    Serial.println("Switch is ON in Timer Mode");
    if ((unsigned long)(currentMillis - previousMillisDuration) >= duration) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisDuration = currentMillis;
      digitalWrite(device1_pin, LOW);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
      if ((unsigned long)(currentMillis - previousMillisTimer) >= timer) {
      Switchstate = !Switchstate;
      digitalWrite(device1_pin, Switchstate);
      previousMillisTimer = currentMillis;
      digitalWrite(device1_pin, HIGH);
      Serial.println("Switch is OFF after Set duration in Timer Mode");
   }
  }

  //delay(2000);    //Send a request every 30 seconds
}

It will be much much easier for me to understand what you trying to achieve if you follow the example that I have posted.

You might have some really wrong assumptions of how your code works and by analysing your code I would come to a wrong solution.

This is the reason why I insist on "post examples with numbers" in the pattern like I have posted above
best regards Stefan

OK, let me try to put it as an example with numbers

Condition 1: Mode switch in the website in AUTO (timermode = 0)

There are sensorvalue, setvalue and duration. Lets say duration is set to 5 seconds
If setvalue is greater than sensorvalue, the switch is activated (if (timermode == 0 && setvalue > sensorvalue) {
digitalWrite(device1_pin, HIGH);

20:00:00
20:00:01
20:00:02
20:00:03
20:00:04
20:00:05 Switch turns off

Again goes back to see if the mode is still in AUTO and compare sensorvalue and setvalue. If the condition is same, the cycle repeats till sensorvalue is more than setvalue.
As long as the sensorvalue is more than setvalue, the switch remains off

Condition 2: Mode switch in TIMER mode (timermode = 1)

There is Timer and Duration. Lets say timer is set to 60 seconds and duration to 5 seconds
The switch is activated. (if (timermode == 1) {
digitalWrite(device1_pin, HIGH);

20:00:00 Switch turns on upon selecting TIMER mode
20:00:01
20:00:02
20:00:03
20:00:04
20:00:05 Switch turns off (after duration of 5 seconds)
20:00:06 Switch remains off
20:00:07
20:00:08
20:00:09
20:00:10 ........
.....
20:01:06 Switch turns on (after timer of 60 seconds)
20:01:07
20:01:08
20:01:09
20:01:10
20:01:11 Switch turns off (after duration of 5 seconds)

This cycle repeats as long as the mode switch is in TIMER mode. At any point of time, if the timer value or duration in changed in the website, the timing changes accordingly. At all times, the MODE switch state is monitored and depending on whether it is in AUTO or TIMER, the operation changes to Condition 1 or Condition2 above.
Hope this time I explained as you expected.
Thanks!!

Thanks a lot for the links and for sharing the ino file..
I tried reading, though most of it went over my head, it really took me to several new openings.. I never knew Arduino could do this much..
I need to understand more of basics in order to fully understand the concept I guess, and I am really into that now.. appreciate your support..

a statemachine in combination with non-blocking timing is good

a state.machine has a variable that can be set to multiple values where each value represents one "state"

first value of myState "CheckMode"
inside this code-section
if (mode == Auto)
myState = CheckValue

if (mode == Timer)
myState = OnOFF_Timing // this means "branch" to the step OnOFF_Timing see ********-line below

inside the code that gets executed if variable myState is == CheckValue
if (setvalue > actualmeasuredValue)
myState = switchOn

inside the code that gets executed with variable myState is == switchOn

digitalwrite (yourPin,HIGH)
SwitchOnTimeStamp = currentMillis
myState = WaitForAutoModeOnTimeToEnd

inside the code that gets executed with variable myState is == WaitForAutoModeOnTimeToEnd

if (currentMillis - SwitchOnTimeStamp >= OnPeriod
myState = CheckMode


inside code that gets executed with variable myState == OnOFF_Timer

digitalwrite (yourpin, HIGH)
TimerModeOnTimeStamp = currentMillis
myState = WaitForTimerONTime_End

inside code that gets executed with variable myState == WaitForTimerONTime_End

if (currentMillis - TimerModeOnTimeStamp > TimerModeONPeriod)
myState = Timer_Start_OFF_Period

inside code that gets executed with variable myState == Timer_Start_OFF_Period
OFFPeriodStartsTimestamp = currentMillis
myState = WaitForTimerOFF_PeriodToEnd

inside code that gets executed with variable myState == WaitForTimerOFF_PeriodToEnd
if (currentMillis - OFFPeriodStartsTimestamp > OFF_Period)
myState = CheckMode

So this statemachine enable the two possible loops
looping through automode
or looping through timermode
where inside state CheckMode the decision which loop shall be started is made.

best regards Stefan

Thanks for the detailed explanation..
I kind of understand the concept, but I really can't figure out how exactly to edit my code to change it to statemachine with non-blocking timing.
I am still trying to understand by also reading the links and code sent by Koepel.
Would appreciate if you could make it a bit more simpler for me to understand how update my code.

Ok to make it easier for you to understand

the state-machine needs a variable that gets assigned different values that represent the different "states" what would be a good name for you that is kind of a generalised word for the different states.

With generalised word I mean this:

there are cars, scooters, trucks, buses, bicycles etc. etc., etc.they are all
generalised word "vehicles"

You have states

  • "CheckMode"
  • "SwitchOn"
  • "WaitForSwitchOnTimeBeeingOver"
  • etc. etc.
    what would for you be a name that is "generalised"

The basic structure is a switch case-structure
here is a rough sketchy sketching of it

const byte CheckMode   = 10;
const byte CheckValue  = 15;
const byte AutoModeSwitchOn = 20;
const .......          = 30;
....

byte MyStateVariable;


  switch(MyStateVariable)
  {
    case CheckMode:
      // code
		if (mode == Auto)
		MyStateVariable = CheckValue;

      break;

    case CheckValue:
	  if (setvalue ....
  	    MyStateVariable = AutoModeSwitchOn;
	  break;
  
    case AutoModeSwitchOn:
  
      // code
      break;

No it is up to you to make a first attempt of adapting and expanding this sketchy sketching towardsa a working code and then come back with questions.

best regards Stefan

I kinda got stuck..
below is what I did so far..

const byte CheckMode   = 10;
const byte CheckValue  = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte SwitchOnTimeStamp = 50;


byte MyStateVariable;
unsigned long currentMillis = millis();
switch(MyStateVariable)
  {
    case CheckMode:
      // code
    if (timer == 0)
    MyStateVariable = CheckValue;

    if (timer == 1)
    MyStateVariable = OnOffTiming;

      break;

    case CheckValue:
    if (setvalue > actualvalue){
        MyStateVariable = AutoModeSwitchOn;
    break;
    }
    case AutoModeSwitchOn:
    digitalWrite(device1_pin, HIGH);
    Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
    SwitchOnTimeStamp = currentMillis;
    MyStateVariable = WaitForAutoModeOnTimeToEnd;
    break;

    case WaitForAutoModeOnTimeToEnd:
    if (currentMillis - SwitchOnTimeStamp >= ontime){
    MyStateVariable = CheckMode;

upon verifying, I get the error "assignment of read-only variable 'SwitchOnTimeStamp'"

What am I doing wrong? Or is it dumb altogether :thinking:

the additional word const tells the compiler this symbol is not variable it is a constant.
and you try to assign a constant a new value. That is what the compiler is complaining about.

all variables that deal in some way with millis() must be of type unsigned long.
millis() counts up until 2^32 = 4.294.967.296
such a huge number needs four bytes to be represented in the binary system.
a variable of type byte has 8 bit which menas can hold values from 0 to 255
int has 16 bit and can hold values from -32767..0...+32767
one bit is used as the sign

unsigned int holds values between 0 .. 65535

using symbols for the state makes the code much easier to read and understand

case 7:

says nothing about this state

case SwitchOnPump:

is explaining itself with the symbols name

maybe you should do a step inbetween
and make a handdrawn program schedule
something like this


the list should show what happends after each other and what where the conditions that something new shall happen.

There are two different types
something shall be done and immidiately after this is done
for example switching something on ad starting a timer

and some kind of condition must become true before something new should be done
examples:
wait until 5 seconds has passed by

check if sensorvalue is below setvalue

if you have written down all these conditions you can see how many states your state-machine needs and what are the types of the state transition or condition
and what happends in each state and what state follows

It will be much better if you take time to think about selfexplaining names that nail down to the point what a state is good for.

Sometimes this takes me 15 minutes to "develop" a goodname. But after that time
the name is really good self-explaining the thing.

best regards Stefan

Hello,
I edited the code again and completed the steps. It is compiling without any errors. After uploading, when I run it, nothing is happening. The serial monitor doesn't show any messages in the code
Below is what I made.

int ontime = 5000;
const byte CheckMode   = 10;
const byte CheckValue  = 15;
const byte AutoModeSwitchOn = 20;
const byte TimerModeSwitchOn = 30;
const byte OnOffTiming = 35;
const byte switchOn = 40;
const byte WaitForAutoModeOnTimeToEnd = 45;
const byte WaitForTimerONTime_End = 50;
const byte Timer_Start_OFF_Period = 55;
const byte WaitForTimerOFF_PeriodToEnd = 60;
unsigned long OFFPeriodStartsTimestamp;
unsigned long SwitchOnTimeStamp;
unsigned long TimerModeOnTimeStamp;

byte MyStateVariable;
switch(MyStateVariable)
  {
    case CheckMode:
      // code
    if (timer == 0){
    MyStateVariable = CheckValue;
    }
    if (timer == 1){
    MyStateVariable = OnOffTiming;
    }
      break;

    case CheckValue:
    if (setvalue > actualvalue){
        MyStateVariable = AutoModeSwitchOn;
    break;
    }
    case AutoModeSwitchOn:
    digitalWrite(device1_pin, HIGH);
    Serial.println("Actual Moisture Less Than Set Moisture. Switch Activated");
    SwitchOnTimeStamp = currentMillis;
    MyStateVariable = WaitForAutoModeOnTimeToEnd;
    break;

    case WaitForAutoModeOnTimeToEnd:
    if (currentMillis - SwitchOnTimeStamp >= ontime){
    Serial.println("Switch Turned Off After Set Duration in AUTO mode");
    MyStateVariable = CheckMode;
    break;
    }
  case OnOffTiming:
  digitalWrite(device1_pin, HIGH);
  TimerModeOnTimeStamp = currentMillis;
  Serial.println("Switch ON in TIMER mode");
  MyStateVariable = WaitForTimerONTime_End;
    break;
  
  case WaitForTimerONTime_End:
  if (currentMillis - TimerModeOnTimeStamp > duration){
  Serial.println("Switch Turned OFF in TIMER mode After Set Duration");
  MyStateVariable = Timer_Start_OFF_Period;
  break;
  }
  
  case Timer_Start_OFF_Period:
  OFFPeriodStartsTimestamp = currentMillis;
  MyStateVariable = WaitForTimerOFF_PeriodToEnd;
  break;
  
  case WaitForTimerOFF_PeriodToEnd:
  if (currentMillis - OFFPeriodStartsTimestamp > timer){
  Serial.println("Switch ON in TIMER mode After Set Timer Period");
  MyStateVariable = CheckMode;
  break;
  }
   }
  }

Please see if I am doing something wrong..
Thanks!!

Pretty well done as a first attempt. Still some smaller things to correct.

Yes "of course" there is nothing happeing yet because the most basic structure that all sketches need is missing.

From this I can conclude that you should improve your knowledge about how writing programs with teh Arduino-IDE works.
All any every sketch - without any exception

All any every sketch needs a void setup {} abd a void loop() {} function.

So as you seem to not know yet enough about these basic things I highly recommend to read at least the first 5 sections of this programming tutorial

Take a look into this tutorial:

Arduino Programming Course

It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.

To rise your motivation to really do it I make a condition:

Any further answers from me depend on that you wrote an attempt to add the functions setup and loop to the code above and posted this new codeversion here.

As a general hint
There is an automatic function for doing this in the Arduino-IDE
just three steps

  1. press Ctrl-T for autoformatting your code
  2. do a rightclick with the mouse and choose "copy for forum"
  3. paste clipboard into write-window of a posting

best regards Stefan