Arduino State Machine issue with switching button states

Hello,I'm working on a project that will ensure that milk or any liquid does not overflow during boiling. First, I tried a simple code and managed to turn off the heater at a certain temperature, but it needs to be adjustable at more than one temperature value. That's why I put buttons that will change the mode according to the liquid when pressed, and I merged it with the concept of state machine. It's been 2 weeks since I started learning state machine.

Materials:

  1. Arduino Uno
  2. Kettle(1kW)
    3)Buzzer
  3. Resistors
    5)DS18B20 temp. sensor
    6)SSR Relay 25 A
    7)Push buttons

What I want, for example, is that when the milk button is pressed, the relay will open up to 95 degrees and turn itself off. The button can also be a slide switch.
The code was compiled successfully in the first place, but the states were changing between 0 and 1. I solved this problem by researching the concept of debouncing and implanting it in my code. This time, when I pressed the button, the button states remained at 1 and did not change. Wiring was done correctly, but I could not do the state machine` transition. I think I'm wrong about the transition. I was solving my previous problems by looking at those who had similar problems. Maybe the answers to this topic will be useful for those who have problems.

#include <DallasTemperature.h>
#include<OneWire.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET -1                      
Adafruit_SSD1306 display(OLED_RESET);
#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);//DS18B20'nin tanımlanması
float Celcius = 0;
float Fahrenheit = 0;

int debug = 1; 


int state_switch_1 = 0;     
int state_prev_switch_1 = 0;  
int switch_1 = 5;             //Wiring
int value_switch_1 = 0;      
unsigned long time_switch_1 = 0;             
unsigned long time_0_switch_1 = 0;          
unsigned long bounce_delay_switch_1 = 10;   
unsigned long hold_delay_switch_1 = 1000;


int state_switch_2 = 0;      
int state_prev_switch_2 = 0;
int switch_2 = 6;             //Wiring
int value_switch_2 = 0;       //Switch HIGH or Low
unsigned long time_switch_2 = 0;             
unsigned long time_0_switch_2 = 0;           
unsigned long bounce_delay_switch_2 = 10;    
unsigned long hold_delay_switch_2 = 1000; 



int state_kettle = 0;         
int state_prev_kettle = 0;
int relay = 8;                //Wiring
int value_relay = 0;          //Kettle relay HIGH or Low
unsigned long time_kettle = 0;            //miliseconds 
unsigned long time_0_kettle = 0;          
unsigned long on_delay_kettle = 500;   //On time delay(miliseconds)
unsigned long off_delay_kettle = 500;  //Off time delay(miliseconds)

int state_buzzer = 0;         
int state_prev_buzzer = 0;
int buzzer = 7;              //Wiring
int value_buzzer = 0;        //Buzzer HIGH or Low
unsigned long time_buzzer = 0;            //miliseconds 
unsigned long time_0_buzzer = 0;          
unsigned long on_delay_buzzer = 500;   //On time delay(miliseconds)
unsigned long off_delay_buzzer = 500;  //Off time delay(miliseconds)


void setup() {


  pinMode(relay, OUTPUT);                      //relay ve buzzer pinMode
  pinMode(buzzer, OUTPUT);
  pinMode(switch_1, INPUT);                    
  pinMode(switch_2, INPUT);
 
  if (debug) {
    Serial.begin(9600);
    Serial.println("Debugging is in process");
  }
  sensors.begin();
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);   
  display.clearDisplay();

}

void loop() {

  sensors.requestTemperatures();
  Celcius = sensors.getTempCByIndex(0);
  Fahrenheit = sensors.toFahrenheit(Celcius);


  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("Temperature: ");
  display.print(sensors.getTempCByIndex(0));
  display.print(" ");
  display.cp437(true);
  display.write(167);
  display.println("C");
  display.display();
  Serial.print(" °C  ");
  Serial.print(Celcius);
  Serial.print(" F  ");
  Serial.println(Fahrenheit);
  delay(100);

  State_Machine_switch_1();
  State_Machine_switch_2();
  State_Machine_kettle();
  State_Machine_buzzer();


  if (Celcius >= 80) {   
    state_buzzer = 1;
  }                                 
  if (Celcius >= 95) {
    state_buzzer = 2;
  }


  if (debug) {
    if ((state_prev_switch_1 = ! state_switch_1 ) | (state_prev_buzzer = ! state_buzzer ) | (state_prev_kettle = ! state_kettle ) | (state_prev_switch_2 = ! state_switch_2)) {
      Serial.print("Switch_1 State: "); Serial.print(state_switch_1);
      Serial.print("Switch_2 State: "); Serial.print(state_switch_2);
      Serial.print(" | Kettle State: "); Serial.print(state_kettle);
      Serial.print(" | Buzzer State: "); Serial.println(state_buzzer);
    }

  }
}


void  State_Machine_switch_1() {

  value_switch_1 = digitalRead(switch_1);
  state_prev_switch_1 = state_switch_1;

  switch (state_switch_1) {

    case 0:

      state_switch_1 = 1; 
      break;



    case 1:
      if (value_switch_1 == LOW)
      {
        state_switch_1 == 2;
      }
      break;


    case 2:
      time_0_switch_1 = millis();
      state_switch_1 = 3;        

      break;
    case 3:
      time_switch_1 = millis();
      if (time_switch_1 - time_0_switch_1 > bounce_delay_switch_1)
      {
        state_switch_1 = 4;
      }

      if (value_switch_1 == HIGH) {
        state_switch_1 = 0;
      }
    case 4:
      time_switch_1 = millis();
      if (value_switch_1 == HIGH) {
        state_switch_1 = 5;
      }
      if (time_switch_1 - time_0_switch_1 > hold_delay_switch_1) {
        state_switch_1 = 6;

      }
    case 5:

      if (debug) {
        Serial.println("Triggered");
        Serial.println("Mode for milk");
      }
      break;

    case 6:

      if (debug) {
        Serial.println("Holding");
        state_kettle = 2; 
        state_switch_1 = 7;
      }
      break;


    case 7:
      if (value_switch_1 == LOW) {
        state_switch_1 = 0;
      }

      break;

  }
}


void  State_Machine_switch_2() {

  value_switch_2 = digitalRead(switch_2);
  state_prev_switch_2 = state_switch_2;

  switch (state_switch_2) {

    case 0:

      state_switch_2 = 1; 
      break;



    case 1:
      if (value_switch_2 == LOW)
      {
        state_switch_2 == 2;
      }
      break;


    case 2:
      time_0_switch_2 = millis(); 

      state_switch_2 = 3;         

      break;
    case 3:
      time_switch_2 = millis();
      if (time_switch_2 - time_0_switch_2 > bounce_delay_switch_2)
      {
        state_switch_2 = 4;
      }

      if (value_switch_2 == HIGH) {
        state_switch_2 = 0;
      }
    case 4:
      time_switch_2 = millis();
      if (value_switch_2 == HIGH) {
        state_switch_2 = 5;
      }
      if (time_switch_2 - time_0_switch_2 > hold_delay_switch_2) {
        state_switch_2 = 6;

      }
    case 5:

      if (debug) {
        Serial.println("Relay on for tea");
        Serial.println("Triggered");
      }

      break;

    case 6:
      if (debug) {
        Serial.println("Holding");
        state_kettle = 3; 
        state_switch_2 = 7;
      }

      break;


    case 7:
      if (value_switch_2 == LOW) {
        state_switch_2 = 0;
      }

      break;

  }
}


void State_Machine_kettle() {

  state_prev_kettle = state_kettle;

  switch (state_kettle) {

    case 0:
      digitalWrite(relay, LOW);
      state_kettle = 1; //RESET

      break;
    case 1:

      //wait

      break;


    case 2:

      digitalWrite(relay, HIGH);
      time_0_kettle = millis();
      if (Celcius >= 80) {
        state_kettle = 4;
      }



      break;


    case 3:

      digitalWrite(relay, HIGH);
      time_0_kettle = millis();
      if (Celcius >= 95) {
        state_kettle = 4;
      }


      break;


    case 4:

      time_kettle = millis();
      if (time_kettle - time_0_kettle > on_delay_kettle) {
        state_kettle = 5;
      }

      break;


    case 5:

      time_0_kettle = millis();
      digitalWrite(relay, LOW);
      state_kettle = 6;

      break;

    case 6:

      time_kettle = millis();
      if (time_kettle - time_0_kettle > off_delay_kettle) {
        state_kettle = 7;
      }

      break;
    case 7:
      digitalWrite(relay, LOW);
      state_kettle = 0;

      break;


  }

}


void State_Machine_buzzer() {

  state_prev_buzzer = state_buzzer;

  switch (state_buzzer) {

    case 0:
      //RESET
      digitalWrite(buzzer, LOW);

      break;

    case 1:
      time_0_buzzer = millis();
      digitalWrite(buzzer, HIGH);
      state_buzzer = 3;

      break;

    case 2:
      digitalWrite(buzzer, HIGH);
      time_0_buzzer = millis();
      state_buzzer = 3;

      break;

    case 3:
      time_buzzer = millis();
      if ((time_buzzer - time_0_buzzer > on_delay_buzzer)) {
        state_buzzer = 4;
      }


      break;

    case 4:
      time_0_buzzer = millis();
      digitalWrite(buzzer, LOW); 
      state_buzzer = 5;
      break;



    case 5:


      time_buzzer = millis();
      if (time_buzzer - time_0_buzzer > off_delay_buzzer) {
        state_buzzer = 0;
      }


      break;




  }
}


Welcome to the forum.

It is too complex.
I think you have just one process going on. That means you need just one Final State Machine.
There are libraries for debouncing.
k ? What is 'k' ?

int debug = 1; k

It is a lot of SRAM usage for a poor little Arduino Uno. I'm not sure that it is possible. Do have other Arduino boards ? Using the 'F()' macro might help a little.
Could you use the word "switch" only for a button or a switch ?

I did not check what your sketch is doing, sorry, in my opinion it has to be rewritten anyway.

why so many state machines, especially for buttons (see below)?

you mention different temperatures for different liquids, why isn't that temperature a variable set by a button press and a conventional routine that simply turns off a relay when the temperature is exceeded? (guessing you have separate states for each liquid type and the buzzer state machine works in parallel with kettle state machine)

consider following for handing multiple buttons with a single routine

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsLed [] = { 10, 11, 12 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    switch (chkButtons ())  {
    case 2:
        digitalWrite (pinsLed [2], ! digitalRead (pinsLed [2]));
        break;

    case 1:
        digitalWrite (pinsLed [1], ! digitalRead (pinsLed [1]));
        break;

    case 0:
        digitalWrite (pinsLed [0], ! digitalRead (pinsLed [0]));
        break;
    }
}

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

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsLed); n++)  {
        digitalWrite (pinsLed [n], Off);
        pinMode      (pinsLed [n], OUTPUT);
    }
}

consider results from code below

  Off  100 C  Water
  Off   95 C  Tea
  Off   80 C  Milk
  Off  100 C  Water
  Off   95 C  Tea
   On   95 C  Tea
 getTempC:  184    89
 getTempC:  183    89
 getTempC:  183    89
 getTempC:  183    89
 getTempC:  183    89
 getTempC:  183    89
 getTempC:  183    89
 getTempC:  190    92
 getTempC:  192    93
 getTempC:  196    95
  Off   95 C  Tea
// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };

byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)
byte butState [N_BUT];

byte pinRelay = LED_BUILTIN;

enum { ButSelect, ButOnOff };

struct Liquid {
    int         tempC;
    const char *label;
};

Liquid liquids [] = {
    { 100,  "Water" },
    { 95,   "Tea" },
    { 80,   "Milk" },
};
#define N_Liquids   (sizeof(liquids)/sizeof(Liquid))

unsigned liqIdx;

char s [90];

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    return -1;
}

// -----------------------------------------------------------------------------
void
dispUpdate ()
{
    sprintf (s, "  %3s  %3d C  %s", 
        On == digitalRead (pinRelay) ? "On" : "Off",
        liquids [liqIdx].tempC, liquids [liqIdx].label);
    Serial.println (s);
}

// -----------------------------------------------------------------------------
int
getTempC ()
{
    int val  = analogRead (A0);
    int temp = map(val, 0, 1023, 0, 500);

#if 1
    sprintf (s, " %s: %4d  %4d", __func__, val, temp);
    Serial.println (s);
    delay (500);
#endif

    return temp;
}

// -----------------------------------------------------------------------------
void
loop ()
{
    // check temperature
    if (On == digitalRead (pinRelay))  {
        if (liquids [liqIdx].tempC <= getTempC ())  {
            digitalWrite (pinRelay, Off);
            dispUpdate ();
        }
    }

    // process buttons
    switch (chkButtons ())  {
    case ButOnOff:
        digitalWrite (pinRelay, ! digitalRead (pinRelay));
        dispUpdate ();
        break;

    case ButSelect:
        liqIdx = N_Liquids <= ++liqIdx ? 0 : liqIdx;
        dispUpdate ();
        break;
    }
}

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

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    digitalWrite (pinRelay, Off);
    pinMode      (pinRelay, OUTPUT);

    dispUpdate ();
}

Thank you.'k' is typing error,i fixed that.I agree with you,it is too much for Arduino Uno,i will consider your suggestion.

I wrote a code based on a single routine in the first place, but I decided to designed a system that shuts down at the limit temperature value for different liquids when the button is pressed.Which is current code.Your option can also be considered,it is solid.Thank you,i will try that.

does it do what you want ??

I'm trying to process it.I think it will work.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.