Change state one in a state machine state

I have written this bit of code for my LED lights for my aquarium using Blynk as the UI. it works as expected except for 1 issue.
I have created a state machine whereby a button is checked along with the temperature of the heatsink. the issue I have is that once I am within the AUTO state which is the state whereby the LEDS are doing their thin I need to keep an eye on the heatsink temperature and if it gets too hot I need to jump out of the state and go to the LEDSAFE state wich is a procedure of automatically dimming all the leds to a level to allow for passive cooling of the heatsink. When temp of the heatsink is drops to is acceptable value I need to return to the Auto state.
I have tied various options but cant seem to get out of the AUTO state to go to LEDSAFE state.
I am using an ESP8266 D1 mini so all my bits are 1023 as opposed to 255.
Any suggestions please?

void LEDFunction()
{
  switch (state)
  {
    case BUTTCHECK:
    {
      if (BTNval == 1 && TempAlarm == false) // button is 1 and the heatsink temp is OK
      {
        state = AUTO;
      }
      else if (BTNval == 0 && TempAlarm == false) //button is 0 and the heatsink temp is OK
      {
        state = MANUAL;
      }
      else if (BTNval == 1 && TempAlarm == true) //button is 1 but heatsink temp is NOT OK
      {
        state = LEDSAFE;
      }
      else
      {
        state = LEDSAFE; //button is 0 but heatsink temp is NOT OK
      }
      break;
    }
   
    case MANUAL:  //manual mode to set the LEDS brightness
    {
      analogWrite(CH1, maxPWM1);
      analogWrite(CH2, maxPWM2);
      analogWrite(CH3, maxPWM3);
      analogWrite(CH4, maxPWM4);
      analogWrite(CH5, maxPWM5);
      analogWrite(CH6, maxPWM6);
      state = BUTTCHECK;
      break;
    }

    case AUTO: //AUTO mode the function of the leds
    {
      if (TempAlarm == false)
      {
        sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
        Serial.println(currentTime);
        TotalMillis = (((hour()*3600) + (minute()*60) + second()) * 1000);
        CH1Period = CH1End - CH1Start;
        CH2Period = CH2End - CH2Start;
        CH3Period = CH3End - CH3Start;
        CH4Period = CH4End - CH4Start;
        CH5Period = CH5End - CH5Start;
        CH6Period = CH6End - CH6Start;
        SetLed(CH1, TotalMillis, CH1Start, FadeINmillis1, CH1Period, FadeOUTmillis1, maxPWM1, V38);  //UV 
        SetLed(CH2, TotalMillis, CH2Start, FadeINmillis2, CH2Period, FadeOUTmillis2, maxPWM2, V39);  //RBLUE/BLUE
        SetLed(CH3, TotalMillis, CH3Start, FadeINmillis3, CH3Period, FadeOUTmillis3, maxPWM3, V40);  //BLUE
        SetLed(CH4, TotalMillis, CH4Start, FadeINmillis4, CH4Period, FadeOUTmillis4, maxPWM4, V41);  //OCW
        SetLed(CH5, TotalMillis, CH5Start, FadeINmillis5, CH5Period, FadeOUTmillis5, maxPWM5, V42);  //AMBER
        SetLed(CH6, TotalMillis, CH6Start, FadeINmillis6, CH6Period, FadeOUTmillis6, maxPWM6, V55);  //LIME
        state = BUTTCHECK;      //THIS IS WHERE I HAVE THE ISSUE. WHAT I WANT IS IF THE 
HEATSINK TEMP IS OK CONTINUE THROUGH AS NORMAL BUT IF BY CHANCE THE HEATSINK FAN IS BROKEN AND TEMP RISES THEN IT MUST EMMEDIATLY GO TO THE LEDSAFE OPTION.
        if (TempAlarm == true)
        {
          state = LEDSAFE;
        }
      }
      break;
    }
    
    case LEDSAFE: //ledsafe option dim all channels down to 300
    {
      analogWrite(CH1, 300);
      analogWrite(CH2, 300);
      analogWrite(CH3, 300);
      analogWrite(CH4, 300);
      analogWrite(CH5, 300);
      analogWrite(CH6, 300);
      state = BUTTCHECK;
      break;
    }
  }
}

You didn't post ALL of your code, so I have to assume you've enumerated "state" correctly and TempAlarm gets set somewhere else....accurately... Probably best to post all of your code because the problem may not be where you are looking. Can you add some print statements to your code to check the values of your conditions. Perhaps you are not taking the branch you expect to take because your values are not what you expect them to be.

I have tied various options but cant seem to get out of the AUTO state to go to LEDSAFE state.

Your code appears OK in that if TempAlarm is true then the state changes to LEDSAFE. What evidence do you have that it is not working ?

Is the problem in the code that you have not posted, I wonder (hint)
Where is BTNval set, for instance ?

Printing the relevant variables before testing them would be useful in tracking down the problem

You are checking whether TempAlarm is true to decide whether to set state to LEDSAFE. Problem is, that check is inside another if that already established that TempAlarm is false. Unless TempAlarm is being set in an interrupt, that's not going to work. Add an else clause to the first if and set state to LEDSAFE there.

Here is the entire code. All the functions named BLYNK_WRITE () is data coming from another Master ESP 8266 via a widget called bridge. All this works fine. While in the AUTO state the LEDS function as they should ie. they dim up and dim down according to the set times. But when I put a heat gun on the temp sensor (trying to emulate a hot heat sink) the function carries on as normal. It seems that it has to complete the state before it can move onto the next state. What I am trying to do is while the temp is OK do the LED function as soon as it is not OK stop the LED function and move to the LEDSAFE state. I know that probably a "while" function might work, I cannot use this function as it is blocking code which does not work with Blynk.

//LED1_DEVICE TAB//
//LIBRARIES//             
                  
#include <ESP8266WiFi.h>                
#include <BlynkSimpleEsp8266.h>        

#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>  //For OTA w/ ESP8266
// #include <ESPmDNS.h>  //For OTA w/ ESP32
#include <WiFiUdp.h>

#include <TimeLib.h>
#include <WidgetRTC.h>
#include <OneWire.h>
#include <DallasTemperature.h>
WidgetRTC rtc;
BlynkTimer timer;

//PIN ASSIGNMENTS//
#define CH1 D5           //UV pin

#define HSinkFan D1      //Heat sink fan pin
#define ONE_WIRE_BUS D4  //Temp sensor pin

//WIFI Variables
char auth[] = ""; 
char ssid[] = "";
char pass[] = "";
char modulename[] = "AquArt Blynk Computer Slave1";      //Insert app name

//BRIDGE WIDGET//
WidgetBridge master_slave1(V62);

//RTC & TIME IMPUT ATTRIBUTES & VARIABLES
char currentTime[9];    //RTC time
unsigned long TotalMillis;

//LED FADE GLOBALS & VARIABLES//
int BTNval;

enum LEDFunction {BUTTCHECK, MANUAL, AUTO, LEDSAFE};
LEDFunction state = BUTTCHECK;

//CHANNEL 1//
unsigned long CH1S;
unsigned long CH1E;
unsigned long CH1Start;
unsigned long CH1End;
unsigned long FadeINmin1;
unsigned long FadeINmillis1;
unsigned long FadeOUTmin1;
unsigned long FadeOUTmillis1;
int maxPWM1;
unsigned long CH1Period;
int ProgressBar1;

//TEMPERATURE ATTRIBUTES & VARIABLES//
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float tempHSink1 = 0;
byte tempHSinkSetPoint = 35;
boolean TempAlarm = false;

//CONNECT TO BLYNK SERVER//
BLYNK_CONNECTED()
{
  Blynk.syncAll();
  rtc.begin();
  master_slave1.setAuthToken("");   //MASTER
}

void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  ArduinoOTA.setHostname(modulename);
  ArduinoOTA.begin(); 

  pinMode(ONE_WIRE_BUS, INPUT);
  pinMode(CH1, OUTPUT);
  pinMode(HSinkFan, OUTPUT);
  analogWrite(CH1, 0);
 
  sensors.begin();
  
  setSyncInterval(30);
  timer.setInterval(1050L, HeatSink);
  timer.setInterval(100L, LEDFunction);  
}

void loop()
{
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();
}
//LIGHTING TAB//
void LEDFunction()
{
  switch (state)
  {
    case BUTTCHECK:
    {
      if (BTNval == 1 && TempAlarm == false)
      {
        state = AUTO;
      }
      else if (BTNval == 0 && TempAlarm == false)
      {
        state = MANUAL;
      }
      else if (BTNval == 1 && TempAlarm == true)
      {
        state = LEDSAFE;
      }
      else
      {
        state = LEDSAFE;
      }
      break;
    }
   
    case MANUAL:
    {
      analogWrite(CH1, maxPWM1);
      analogWrite(CH2, maxPWM2);
      analogWrite(CH3, maxPWM3);
      analogWrite(CH4, maxPWM4);
      analogWrite(CH5, maxPWM5);
      analogWrite(CH6, maxPWM6);
      state = BUTTCHECK;
      break;
    }

    case AUTO:
    {
      if (TempAlarm == false)
      {
        sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
        Serial.println(currentTime);
        TotalMillis = (((hour()*3600) + (minute()*60) + second()) * 1000);
        CH1Period = CH1End - CH1Start;
        CH2Period = CH2End - CH2Start;
        CH3Period = CH3End - CH3Start;
        CH4Period = CH4End - CH4Start;
        CH5Period = CH5End - CH5Start;
        CH6Period = CH6End - CH6Start;
        SetLed(CH1, TotalMillis, CH1Start, FadeINmillis1, CH1Period, FadeOUTmillis1, maxPWM1, V38);  //UV 
        SetLed(CH2, TotalMillis, CH2Start, FadeINmillis2, CH2Period, FadeOUTmillis2, maxPWM2, V39);  //RBLUE/BLUE
        SetLed(CH3, TotalMillis, CH3Start, FadeINmillis3, CH3Period, FadeOUTmillis3, maxPWM3, V40);  //BLUE
        SetLed(CH4, TotalMillis, CH4Start, FadeINmillis4, CH4Period, FadeOUTmillis4, maxPWM4, V41);  //OCW
        SetLed(CH5, TotalMillis, CH5Start, FadeINmillis5, CH5Period, FadeOUTmillis5, maxPWM5, V42);  //AMBER
        SetLed(CH6, TotalMillis, CH6Start, FadeINmillis6, CH6Period, FadeOUTmillis6, maxPWM6, V55);  //LIME
        state = BUTTCHECK;
        if (TempAlarm == true)
        {
          state = LEDSAFE;
        }
      }
      break;
    }
    
    case LEDSAFE:
    {
      analogWrite(CH1, 300);
      analogWrite(CH2, 300);
      analogWrite(CH3, 300);
      analogWrite(CH4, 300);
      analogWrite(CH5, 300);
      analogWrite(CH6, 300);
      state = BUTTCHECK;
      break;
    }
  }
}

void SetLed(int pin,
            unsigned long time,       //Current time in millis
            unsigned long start,      //Start of LED channel
            unsigned long fadeup,     //Fadeup period in millis
            unsigned long period,     //Total photo period
            unsigned long fadedown,   //Fadedown period in millis
            float pwm,                //Max value of brightness
            int Vpin)                 //ProgressBar
{
  //HOLD PERIOD//
  if (time > start + fadeup && time <= start + period - fadedown)
  {
    analogWrite(pin, pwm);
    int progress = round((pwm*100)/1023);
    Blynk.virtualWrite (Vpin, progress);   
  }
  //FADEUP PERIOD//
  if (time > start && time <= start + fadeup)
  {
    float brightness;
    brightness = map(time - start, 0, fadeup, 0, pwm);
    analogWrite(pin, brightness);
    int progress = round((brightness*100)/1023);
    Blynk.virtualWrite (Vpin, progress);   
  }
  //FADEDOWN PERIOD//
  if (time > start + period - fadedown && time <= start + period)
  {
    float brightness;
    brightness = map(time - start - period + fadedown, 0, fadedown, pwm, 0);
    analogWrite(pin, brightness);
    int progress = round((brightness*100)/1023);
    Blynk.virtualWrite (Vpin, progress);   
  }
}

BLYNK_WRITE(V37)   //Button Mode data
{
  BTNval = param.asInt();
  Blynk.virtualWrite(V37, BTNval);
  Serial.println("BUTTON");
  Serial.println(BTNval);
}

//CHANNEL 1/////////////////////////////////////////////////////////////////////
BLYNK_WRITE(V2)   //Start time
{
  CH1S = param.asInt();
  Blynk.virtualWrite(V2, CH1S);
  CH1Start = CH1S*60*1000;
}

BLYNK_WRITE(V3)   //End time
{
  CH1E = param.asInt();
  Blynk.virtualWrite(V3, CH1E);
  CH1End = CH1E*60*1000;
}

BLYNK_WRITE(V4)   //FadeIn time
{
  FadeINmin1 = param.asInt();
  Blynk.virtualWrite(V4, FadeINmin1);
  FadeINmillis1 = map(FadeINmin1, 0, 120, 0, 7200000);
}

BLYNK_WRITE(V5)   //FadeOut time
{
  FadeOUTmin1 = param.asInt();
  Blynk.virtualWrite(V5, FadeOUTmin1);
  FadeOUTmillis1 = map(FadeOUTmin1, 0, 120, 0, 7200000);
}

BLYNK_WRITE(V6)   //Intensity value 
{
  maxPWM1 = param.asInt();
  Blynk.virtualWrite(V6, maxPWM1);
  Serial.println("INTENSITY");
  Serial.println(maxPWM1);
}
//TEMPERATURE TAB//

void HeatSink()
{
  sensors.requestTemperatures();
  tempHSink1 = sensors.getTempCByIndex(0);
  Serial.println(tempHSink1);
  if(tempHSink1 >= tempHSinkSetPoint)
  {
    digitalWrite(HSinkFan, HIGH);
    TempAlarm = false;
  }
  else if (tempHSink1 <= tempHSinkSetPoint - 1)
  {
    digitalWrite(HSinkFan, LOW);
    TempAlarm = false;
  }
  else if (tempHSink1 >= 50)
  {
    digitalWrite(HSinkFan, HIGH);
    TempAlarm = true;
    master_slave1.virtualWrite(V60, 1);
  }
  else
  {
    TempAlarm = false;
    master_slave1.virtualWrite(V60, 0);
  }
}

Proietti:
It seems that it has to complete the state before it can move onto the next state.

Once it's passed the conditional check, it's complete the code based on that check. If that's too long... consider that a heatsink doesn't usually heat up as fast as a heat gun, and shouldn't get beyond a safe level. If it's critical, it shouldn't be software... get a PPTC fuse, a zener, a plain old fuse, whatever you need to do in hardware... Also consider making additional checks on the sensor throughout your branch, and use

return;
//or
break;

with your sensor check to jump out of the state machine.

I where to use w "while" statement instead of an if at the beginning of the AUTO case, what would happen? would it block the other functions happening elsewhere in the code?

@ wildbill noted

You are checking whether TempAlarm is true to decide whether to set state to LEDSAFE. Problem is, that check is inside another if that already established that TempAlarm is false. Unless TempAlarm is being set in an interrupt, that's not going to work. Add an else clause to the first if and set state to LEDSAFE there.

Have you fixed this? The latest posted code still has this logical error

case AUTO:
    {
      if (TempAlarm == false)
      {
        sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
        Serial.println(currentTime);
        TotalMillis = (((hour()*3600) + (minute()*60) + second()) * 1000);
        CH1Period = CH1End - CH1Start;
        CH2Period = CH2End - CH2Start;
        CH3Period = CH3End - CH3Start;
        CH4Period = CH4End - CH4Start;
        CH5Period = CH5End - CH5Start;
        CH6Period = CH6End - CH6Start;
        SetLed(CH1, TotalMillis, CH1Start, FadeINmillis1, CH1Period, FadeOUTmillis1, maxPWM1, V38);  //UV 
        SetLed(CH2, TotalMillis, CH2Start, FadeINmillis2, CH2Period, FadeOUTmillis2, maxPWM2, V39);  //RBLUE/BLUE
        SetLed(CH3, TotalMillis, CH3Start, FadeINmillis3, CH3Period, FadeOUTmillis3, maxPWM3, V40);  //BLUE
        SetLed(CH4, TotalMillis, CH4Start, FadeINmillis4, CH4Period, FadeOUTmillis4, maxPWM4, V41);  //OCW
        SetLed(CH5, TotalMillis, CH5Start, FadeINmillis5, CH5Period, FadeOUTmillis5, maxPWM5, V42);  //AMBER
        SetLed(CH6, TotalMillis, CH6Start, FadeINmillis6, CH6Period, FadeOUTmillis6, maxPWM6, V55);  //LIME
        state = BUTTCHECK;
        if (TempAlarm == true) //>>This check is inside the TempAlarm==false block
        {
          state = LEDSAFE;
        }
      }
      break;
    }

Proietti:
I where to use w "while" statement instead of an if at the beginning of the AUTO case, what would happen? would it block the other functions happening elsewhere in the code?

Fix the other problem first

Do not use a while loop in a switch/case if there is code in loop() outside of the switch/case, such as reading inputs that needs to be executed frequently. I would go as far as to say that there is never a need to use a while loop in a switch/case

Proietti:
I where to use w "while" statement instead of an if at the beginning of the AUTO case, what would happen? would it block the other functions happening elsewhere in the code?

One should never use a while() unless he or she knows exactly what will happen in all cases. It is more than just blocking code. It can stop the program from going further.

Ok I think I have it working now, just have to sort out the progress bars to show what's happening.

void LEDFunction()
{
  if (TempAlarm == true)
  {
    analogWrite(CH1, 300);
    analogWrite(CH2, 300);
    analogWrite(CH3, 300);
    analogWrite(CH4, 300);
    analogWrite(CH5, 300);
    analogWrite(CH6, 300);
    Blynk.virtualWrite(V38, 30);
    Blynk.virtualWrite(V39, 30);
    Blynk.virtualWrite(V40, 30);
    Blynk.virtualWrite(V41, 30);
    Blynk.virtualWrite(V42, 30);
    Blynk.virtualWrite(V55, 30);
    TempAlarm = false;
    Serial.println("LEDSAFEMODE");
  }
  else if (TempAlarm == false)
  {
    switch (state)
    {
      case BUTTCHECK:
      {
        if (BTNval == 1)
        {
          state = AUTO;
        }
        else if (BTNval == 0)
        {
          state = MANUAL;
        }
        break;
      }
   
      case MANUAL:
      {
        Serial.println("MANUALMODE");
        analogWrite(CH1, maxPWM1);
        analogWrite(CH2, maxPWM2);
        analogWrite(CH3, maxPWM3);
        analogWrite(CH4, maxPWM4);
        analogWrite(CH5, maxPWM5);
        analogWrite(CH6, maxPWM6);
        state = BUTTCHECK;
        break;
      }
  
      case AUTO:
      {
        Serial.println("AUTOMODE");
        sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
        TotalMillis = (((hour()*3600) + (minute()*60) + second()) * 1000);
        CH1Period = CH1End - CH1Start;
        CH2Period = CH2End - CH2Start;
        CH3Period = CH3End - CH3Start;
        CH4Period = CH4End - CH4Start;
        CH5Period = CH5End - CH5Start;
        CH6Period = CH6End - CH6Start;
        SetLed(CH1, TotalMillis, CH1Start, FadeINmillis1, CH1Period, FadeOUTmillis1, maxPWM1, V38);  //UV 
        SetLed(CH2, TotalMillis, CH2Start, FadeINmillis2, CH2Period, FadeOUTmillis2, maxPWM2, V39);  //RBLUE/BLUE
        SetLed(CH3, TotalMillis, CH3Start, FadeINmillis3, CH3Period, FadeOUTmillis3, maxPWM3, V40);  //BLUE
        SetLed(CH4, TotalMillis, CH4Start, FadeINmillis4, CH4Period, FadeOUTmillis4, maxPWM4, V41);  //OCW
        SetLed(CH5, TotalMillis, CH5Start, FadeINmillis5, CH5Period, FadeOUTmillis5, maxPWM5, V42);  //AMBER
        SetLed(CH6, TotalMillis, CH6Start, FadeINmillis6, CH6Period, FadeOUTmillis6, maxPWM6, V55);  //LIME
        state = BUTTCHECK;
        break;
      }
    }
  }
}

You seem to be ping-ponging between the BUTTCHECK state and the actual state. I would change that to check the buttons and alarms in individual states:

void LEDFunction()
{
  switch (state)
  {
    case BUTTCHECK:
      if (BTNval == 1) // button is 1
        state = AUTO;
      else
        state = MANUAL;
      break;


    case MANUAL:  //manual mode to set the LEDS brightness
      analogWrite(CH1, maxPWM1);
      analogWrite(CH2, maxPWM2);
      analogWrite(CH3, maxPWM3);
      analogWrite(CH4, maxPWM4);
      analogWrite(CH5, maxPWM5);
      analogWrite(CH6, maxPWM6);
      if (BTNval == 1) // If the button is 1, switch to AUTO...
        state = AUTO;
      if (TempAlarm) // ...unless there is an alarm
        state = LEDSAFE;
      break;




    case AUTO: //AUTO mode the function of the leds
      sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
      Serial.println(currentTime);
      TotalMillis = (((hour() * 3600) + (minute() * 60) + second()) * 1000);
      CH1Period = CH1End - CH1Start;
      CH2Period = CH2End - CH2Start;
      CH3Period = CH3End - CH3Start;
      CH4Period = CH4End - CH4Start;
      CH5Period = CH5End - CH5Start;
      CH6Period = CH6End - CH6Start;
      SetLed(CH1, TotalMillis, CH1Start, FadeINmillis1, CH1Period, FadeOUTmillis1, maxPWM1, V38);  //UV
      SetLed(CH2, TotalMillis, CH2Start, FadeINmillis2, CH2Period, FadeOUTmillis2, maxPWM2, V39);  //RBLUE/BLUE
      SetLed(CH3, TotalMillis, CH3Start, FadeINmillis3, CH3Period, FadeOUTmillis3, maxPWM3, V40);  //BLUE
      SetLed(CH4, TotalMillis, CH4Start, FadeINmillis4, CH4Period, FadeOUTmillis4, maxPWM4, V41);  //OCW
      SetLed(CH5, TotalMillis, CH5Start, FadeINmillis5, CH5Period, FadeOUTmillis5, maxPWM5, V42);  //AMBER
      SetLed(CH6, TotalMillis, CH6Start, FadeINmillis6, CH6Period, FadeOUTmillis6, maxPWM6, V55);  //LIME
      if (BTNval == 0) // If button is 0, switch to Manual...
        state = MANUAL;
      if (TempAlarm)  // ...unless there is an alarm
        state = LEDSAFE;
      break;


    case LEDSAFE: //ledsafe option dim all channels down to 300
      analogWrite(CH1, 300);
      analogWrite(CH2, 300);
      analogWrite(CH3, 300);
      analogWrite(CH4, 300);
      analogWrite(CH5, 300);
      analogWrite(CH6, 300);
      if (!TempAlarm)  // Alarm is over?
      {
        // No alarm, so go back to AUTO or MANUAL
        if (BTNval == 1)
          state = AUTO;
        else
          state = MANUAL;
      }
      break;
  }
}

Working perfectly now. Thanks to all for your time and help