State Machine as a function

First of all, thanks to LarryD for the help with this piece of code.

Now.. I tried implementing the state machine as a separate function to be called x number of times in the loop(). First I tried to just call it in the loop, expecting the function to run over and over again. But it doesn't work. I get the same result if I try to run it without a limitation on the number of times, as I do if I set an amount of times to run.

What happes is that it calls the function, but somehow it gets stuck after turning on the "nop" variable assigned to pin10 and never gets to the point of turning on rly1, 2 and finally 3. Anyone have any idea why?

It would be ideal for me to be able to run the program like this, as I need an Autorun mode, and a secondary manual mode, where buttons control the action.

//State Machine

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
const byte button = 2;
int buttonState;

unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 3000;

byte currentState;

void setup()
{
  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  pinMode(button, INPUT);

  //RLYmillis = millis();      //Initialize the time
  //digitalWrite(nop,HIGH);  //start out with this LED on
  //currentState = 1;          //we start out in this machine state 

} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  automode(2);
  
}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<< 


void automode (int times){
  for (int i =0; i<times; i++){
  
  RLYmillis = millis();      //Initialize the time
  digitalWrite(nop,HIGH);  //start out with this LED on
  currentState = 1;          //we start out in this machine state 
  

  
  switch (currentState)
  {
    //***************************
  case 1:
    if (millis() - RLYmillis >= RLYdelay)
    {
      digitalWrite(nop,LOW);
      digitalWrite(rly1,HIGH);
      //Change to the next state
      RLYmillis = millis();
      currentState = 2;
    }
    break;

    //***************************
  case 2:
    if (millis() - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      RLYmillis = millis();
      currentState = 3;
    }
    break;

    //***************************
  case 3:
    if (millis() - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      RLYmillis = millis();
      currentState = 4;
    }
    break;

    //***************************
  case 4:
    if (millis() - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly3,LOW);
      digitalWrite(nop,HIGH);
      //Change to the next state
      RLYmillis = millis();
      currentState = 1;              //Back to state 1
    }
    break;


    //***************************

  default:
    {
    }



  } // END of switch/case
} //Auto
}

 

//======================================================================
//                       E N D   O F   C O D E
//======================================================================

    currentState = 1;          //we start out in this machine stateEach time through the for loop currentState is set to 1. Is that what you really want ? Why put the switch/case in a for loop anyway ?

Something like this:

//State Machine

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
const byte button = 2;
int buttonState;

unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 3000;

byte currentState;

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

  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  pinMode(button, INPUT);

  currentState = 1;          //we start out in this machine state
  digitalWrite(nop,HIGH);  //start out with this LED on

} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  automode();

}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<<


void automode (void){
  currentMillis = millis();      //Initialize the time

  Serial.print("current state: ");
  Serial.println(currentState);

  switch (currentState)
  {
    //***************************
  case 1:
    if (currentMillis - RLYmillis >= RLYdelay)
    {
      digitalWrite(nop,LOW);
      digitalWrite(rly1,HIGH);
      //Change to the next state
      RLYmillis = currentMillis;
      currentState++;
    }
    break;

    //***************************
  case 2:
    if (currentMillis - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      RLYmillis = currentMillis;
      currentState = 3;
    }
    break;

    //***************************
  case 3:
    if (currentMillis - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      RLYmillis = currentMillis;
      currentState = 4;
    }
    break;

    //***************************
  case 4:
    if (currentMillis - RLYmillis >= RLYdelay)
    {
      digitalWrite(rly3,LOW);
      digitalWrite(nop,HIGH);
      //Change to the next state
      RLYmillis = currentMillis;
      currentState = 1;              //Back to state 1
    }
    break;


    //***************************

  default:
    {
    }



  } // END of switch/case
}



//======================================================================
//                       E N D   O F   C O D E
//======================================================================

it will work like you want (at least for what I understand).

The last code was based in your original code. In my opinion, you can do something like this:

//State Machine

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
const byte button = 2;
int buttonState;

unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 3000;

byte currentState;

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

  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  pinMode(button, INPUT);

  currentState = 1;        //we start out in this machine state
  digitalWrite(nop,HIGH);  //start out with this LED on

} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  automode();

}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<<


void automode (void){
  currentMillis = millis();      //Initialize the time

  if (currentMillis - RLYmillis >= RLYdelay)
  {
    Serial.print("current state: ");
    Serial.println(currentState);
    RLYmillis = currentMillis;

    switch (currentState)
    {
      //***************************
    case 1:
      digitalWrite(nop,LOW);
      digitalWrite(rly1,HIGH);
      //Change to the next state
      currentState = 2;
      break;

      //***************************
    case 2:
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      currentState = 3;
      break;

      //***************************
    case 3:
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      currentState = 4;
      break;

      //***************************
    case 4:
      digitalWrite(rly3,LOW);
      digitalWrite(nop,HIGH);
      //Change to the next state
      currentState = 1;              //Back to state 1
      break;


      //***************************

    default:
      currentState = 1;              //Back to state 1

    } // END of switch/case
  }
}


//======================================================================
//                       E N D   O F   C O D E
//======================================================================

The code do the same but you only have one if to check the change of the state. Then you can apply the switch/case and do what you want to do according the state you are (in the moment of the transition). As you have defined a "default" case, you can add something to it. In this case I add a "go back to home", in the case of something go wrong and you end with a currentState=5, for example, you will always go to a known state.

cajodk:
I tried implementing the state machine as a separate function to be called x number of times

This conjures up a concept of "state machine" that I don't recognize. To my mind the entire program is the state machine.

How can the "state machine" be a function?
How can a "state machine" be called x times ?

A successful program depends on a clearly understood and unambiguous expression of the problem to be solved.

...R

Well, let me try to explain what I mean, and bear in mind I am new to Arduino programming, so constructive feedback is appreciated.

Btw.. thanks for helping with the code to those who did. It works wonders.

Well, I need the State machine to switch between 4 states. One state where nothing happens, 1 state where X1 is up, one state where X2 is up, and a final state where X3 is up.

However, I also need to implement a keypad. But for starters I am trying with just a button to activate the state machine. So that in my loop() nothing happens UNTIL I press a button. Upon that button press, the state machine kicks into effect and starts shifting between the above 4 mentioned states.

That, Robin, is why I wanted to implement the State machine as a function. And if that is a poor choice of words, I apologize for that. At least some people got what I wanted to do. :slight_smile:

Now, hoever, I've been fiddling with the button thing, also tried the Switch example in my main loop().. but I just cant seem to get it to work.

In short.. what I need is the program to do ABSOLUTELY nothing until I press a button (not holding it down).

Then it should run the 4 states and keep doing so until I press the button again, at which point it should stop completely and turn off all 4 states.

At 3rd button press, it should start running the 4 states again. 4th press, stop everything and turn off and so on..

How would I go about doing that? So far Ive had no success with what I tried.

In luisilva's example, there is a call to automode().
If you only want the 4 states to happen when you push a switch you need to scan the switch and remove bounce.
When the switch changes state, you can set a Boolean variable.
When the switch is pushed a second time you reset the variable.

You can then use this variable in an "if" condition to call luisilva's automode()

if(myVariable == true)
{
automode();
}

I have 2 questions about what you want:
1st- When you say "(...) at which point it should stop completely and turn off all 4 states." what does you mean with this?
2nd- When you say "At 3rd button press, it should start running the 4 states again." it starts from the 1st state or it starts from where it stops the first time?

Thanks again LarryD - you're a very helpful man. :slight_smile:

luisilva.. well, your 1st question. I want it to start going through the 4 stages when I first press the button. When I press again, it should stop and turn off the LEDs (rly1-rly3 in this code).

Then, when pressed again, it should start running the 4 states again. Whether it starts all over from the beginning or resumes from where it left off before doesn't really matter to me at this time.

I tried Larry's example of making a boolean variable, but all it does (most likely due to my noobiness) is change state upon each button press. Well, here's my code so far.

//State Machine

const int rly2_2 = 11;

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
const byte buttonPin = 2;
boolean switchState = false;
unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 1000;

byte currentState;

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

  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, LOW);
  currentState = 4;        //we start out in this machine state
} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<
 


void loop()
{
  if (digitalRead(buttonPin) == HIGH)
  {  
    delay(5);                        // delay to debounce switch
    switchState = !switchState;                // toggle switchState variable
    automode();
    }
}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<<
void manualmode (void){}


void automode (void){
  currentMillis = millis();      //Initialize the time

  if (currentMillis - RLYmillis >= RLYdelay)
  {
    RLYmillis = currentMillis;
    switch (currentState)
    {
      //***************************
    case 1:
      Serial.println("Relay 1");
      digitalWrite(rly1,HIGH);
      currentState = 2;
      break;
    //***************************
    case 2:
      Serial.println("Relay 2");
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      currentState = 3;
      break;
      //***************************
    case 3:
      Serial.println("Relay 3");
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      currentState = 4;
      break;
      //***************************
    case 4:
      Serial.println("No operation");
      digitalWrite(rly3,LOW);
      //Change to the next state
      currentState = 1;
      break;
      //***************************

    default:
      currentState = 1;              //Back to state 1

    } // END of switch/case
  } //END of 'if' statement
} //END of 'automode'


//======================================================================
//                       E N D   O F   C O D E
//======================================================================

If you want an on/off situation you need to monitor for a change in switch state, not while the switch it is pressed.
I believe there is a change in state sketch that comes with the IDE, if not, Google Arduino change in state.

.

I actually tried that also, but never got it to work... simply can't figure out how to go about it, if it's not about turning on a LED. I found the following example:

const int buttonPin  = 2;     // the pin that the pushbutton is attached to
const int ledPin     = 13;    // the pin that the LED is attached to
 
int buttonState      = 0;     // current state of the button
int lastButtonState  = 0;     // previous state of the button
int ledState         = 0;     // remember current led state
 
void setup() {
  pinMode(buttonPin, INPUT);  // initialize the button pin as a input
  pinMode(ledPin, OUTPUT);    // initialize the button pin as a output
}
 
void loop() {
  // read the pushbutton input pin
  buttonState = digitalRead(buttonPin);
 
  // check if the button is pressed or released
  // by comparing the buttonState to its previous state 
  if (buttonState != lastButtonState) {
    
    // change the state of the led when someone pressed the button
    if (buttonState == 1) { 
      if(ledState==1) ledState=0;
      else            ledState=1;         
    }
    
    // remember the current state of the button
    lastButtonState = buttonState;
  }
  
  // turns LED on if the ledState=1 or off if the ledState=0
  digitalWrite(ledPin, ledState);
  
  // adding a small delay prevents reading the buttonState to fast
  // ( debouncing )
  delay(20);
}

You see, this line:

  // turns LED on if the ledState=1 or off if the ledState=0
  digitalWrite(ledPin, ledState);

is what gets me. 'Cause if I type in automode(); instead of all that it doesn't work. I think it's because I don't give it a 'toggle' alternative as a LED would have both an ON and OFF state.

I am a bit lost with what you need but try this:

const unsigned long debounceValue = 50UL; //debounce time in milliseconds
const int startSwitch = 2; //note: pressing this switch makes i/p go LOW 
unsigned long debounceTime;
boolean lastSwitchState1;  //the last read value of switch 
boolean changed;

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 1000;

byte currentState;

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

  pinMode(startSwitch,INPUT_PULLUP); 
  debounceTime = millis(); //initailize to the current time 

  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  currentState = 4;        //we start out in this machine state
} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<



void loop()
{
  //================== is it time to check the switches?
  if (millis() - debounceTime >= debounceValue)
  {
    debounceTime = millis(); //re-initialize to the current time 
    debounceSwitches();      //check the switches 
  } 
  //==================

  if (changed == true)
  {  
    automode();
  }
}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<<

//======================================================================
void manualmode (void)
{
}

//======================================================================
void automode (void)
{
  currentMillis = millis();      

  if (currentMillis - RLYmillis >= RLYdelay)
  {
    RLYmillis = currentMillis;
    switch (currentState)
    {
      //***************************
    case 1:
      Serial.println("Relay 1");
      digitalWrite(rly1,HIGH);
      currentState = 2;
      break;
      //***************************
    case 2:
      Serial.println("Relay 2");
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      currentState = 3;
      break;
      //***************************
    case 3:
      Serial.println("Relay 3");
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      currentState = 4;
      break;
      //***************************
    case 4:
      Serial.println("No operation");
      digitalWrite(rly3,LOW);
      //Change to the next state
      currentState = 1;
      break;
      //***************************

    default:
      currentState = 1;              //Back to state 1

    } // END of switch/case
  } //END of 'if' statement
} //END of 'automode'

//======================================================================
void debounceSwitches()  //switches are checked every debounceValue milli seconds 
//no minimum switch press time is validated with this code
{
  boolean thisState;   

  //================== check if this switch has changed state
  thisState = digitalRead(startSwitch);
  if (thisState != lastSwitchState1)
  {  
    lastSwitchState1 = thisState;  //update the switch state
 
    //if(thisState == HIGH)   // OR        
    if(thisState == LOW)         
    {
      changed = !changed;
    }
  }
}
//======================================================================
//                       E N D   O F   C O D E
//======================================================================

@cajodk

  1. What does this do?
    if(thisState == LOW)
    {
    changed = !changed;
    }

  2. How would you change the sketch to force the outputs LOW and change to State 1 when the switch goes LOW?

cajodk:
However, I also need to implement a keypad. But for starters I am trying with just a button to activate the state machine. So that in my loop() nothing happens UNTIL I press a button. Upon that button press, the state machine kicks into effect and starts shifting between the above 4 mentioned states.

In anything I've ever written that uses states and switch input, waiting for a button press is one of the states. I don't understand why you would consider it separate.

But of course it is common for the loop task to repeatedly poll the switch. The results of that can trigger state changes. So in that sense, the act of polling itself is not a state.

As far as functions, I have encapsulated state machines in functions. It is a good idea.

Hi Larry,

You came pretty close to what I wanted. Except that on every second button press, when I stop the state machine, all LEDs should also go LOW, but they don't. The state machine just stops where it is and waits for a button press agan, after which it continues it's cycle.

This is the problem I've had when I tried to make a state change also.

When the state machine is stopped nothing is supposed to be running until I press the button again.

An even better alternative would be if the button press would toggle between automode and manualmode - don't know if that is possible?

So when in manual mode, everything in automode should be turned off (no LEDS on at all).

Hope it makes sense??

Your 1st question:
It reads the variable thisState. If the variable is HIGH, it does nothing. If it is LOW it toggles the 'changed' variable TRUE or NOT TRUE.

Your 2nd question I am not sure I understand correctly, but:

if(thisState == LOW)
{
digitalWrite (rly1, LOW);
}

aarg:
In anything I've ever written that uses states and switch input, waiting for a button press is one of the states. I don't understand why you would consider it separate.

But of course it is common for the loop task to repeatedly poll the switch. The results of that can trigger state changes. So in that sense, the act of polling itself is not a state.

As far as functions, I have encapsulated state machines in functions. It is a good idea.

Thats also what I did with this state machine... so that my main loop can call upon that function to run the states I specify there. If not called upon, they dont run.

The reason why I want a button in my main loop, is to toggle between my automode and my manualmode. So when the program starts, you are prompted to press ex. '1' for automode or '2' for manualmode.

Automode is my state machine and manualmode will be another function, where each of the 3 LEDs can be turned on individually in whichever order you want. Automode can not be part of manualmode, and therefore, when manualmode is selected, all LEDs must be initially be OFF!

Hope that makes sense...?

You came pretty close to what I wanted. Except that on every second button press, when I stop the state machine, all LEDs should also go LOW, but they don't. The state machine just stops where it is and waits for a button press agan, after which it continues it's cycle.

The second question would reset the outputs to a power up condition which I believe is what you want in the above quote.

So what changes would you make to the sketch?

Well, could do it like this... that works to toggle between auto and manual mode. Only problem is that the LED on pin11 keeps being HIGH for a while, when I toggle back to auto mode. Seemingly until automode has passed it again...

Like:

"AUTOMODE"
Pin11 is HIGH when Pin12 goes HIGH
Pin12 goes LOW, but Pin11 is still HIGH
Pin13 goes HIGH, Pin11 is still HIGH
Pin13 goes LOW, Pin11 is still HIGH
Pin11 goes HIGH
Pin11 goes LOW, Pin12 goes HIGH...

Uhmm.. almost confusing myself now. :slight_smile:

EDIT> I know this gets kind of confusing.. why did I set them all HIGH in manualmode? Well, cause that needs to be an option also. I just havent made that function yet with buttons to toggle between HIGH and LOW for each of the LEDs.

However, if I just make sure to turn them all LOW before going back to automode, there seems to be no problem. But would be nice if that wasn't necessary, so when going back to automode, if the LEDs aren't set LOW manually before then, the program will take care of it and just continue automode as it's supposed to run.

const unsigned long debounceValue = 50UL; //debounce time in milliseconds
const int startSwitch = 2; //note: pressing this switch makes i/p go LOW 
unsigned long debounceTime;
boolean lastSwitchState1;  //the last read value of switch 
boolean changed;

const byte nop = 10;
const byte rly1 = 11;
const byte rly2 = 12;
const byte rly3 = 13;
unsigned long currentMillis;
unsigned long RLYmillis;
unsigned long RLYdelay = 1000;

byte currentState;

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

  pinMode(startSwitch,INPUT_PULLUP); 
  debounceTime = millis(); //initailize to the current time 

  pinMode(nop, OUTPUT);
  digitalWrite(nop,LOW);
  pinMode(rly1, OUTPUT);
  digitalWrite(rly1,LOW);
  pinMode(rly2, OUTPUT);
  digitalWrite(rly2,LOW);
  pinMode(rly3, OUTPUT);
  digitalWrite(rly3,LOW);
  currentState = 4;        //we start out in this machine state
} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<



void loop()
{
  //================== is it time to check the switches?
  if (millis() - debounceTime >= debounceValue)
  {
    debounceTime = millis(); //re-initialize to the current time 
    debounceSwitches();      //check the switches 
  } 
  //==================

  if (changed == true)
  {  
    automode();
  }
  else if (changed == false)
  {
    manualmode();
   }
}//  >>>>>>>>>>>>>> E N D   O F   l o o p ( ) <<<<<<<<<<<<<<<<<

//======================================================================
void manualmode (void)
{
      digitalWrite (rly1, HIGH);
      digitalWrite (rly2, HIGH);
      digitalWrite (rly3, HIGH);
}

//======================================================================
void automode (void)
{
  currentMillis = millis();      

  if (currentMillis - RLYmillis >= RLYdelay)
  {
    RLYmillis = currentMillis;
    switch (currentState)
    {
      //***************************
    case 1:
      Serial.println("Relay 1");
      digitalWrite(rly1,HIGH);
      currentState = 2;
      break;
      //***************************
    case 2:
      Serial.println("Relay 2");
      digitalWrite(rly1,LOW);
      digitalWrite(rly2,HIGH);
      //Change to the next state
      currentState = 3;
      break;
      //***************************
    case 3:
      Serial.println("Relay 3");
      digitalWrite(rly2,LOW);
      digitalWrite(rly3,HIGH);
      //Change to the next state
      currentState = 4;
      break;
      //***************************
    case 4:
      Serial.println("No operation");
      digitalWrite(rly3,LOW);
      //Change to the next state
      currentState = 1;
      break;
      //***************************

    default:
      currentState = 1;              //Back to state 1

    } // END of switch/case
  } //END of 'if' statement
} //END of 'automode'

//======================================================================
void debounceSwitches()  //switches are checked every debounceValue milli seconds 
//no minimum switch press time is validated with this code
{
  boolean thisState;   

  //================== check if this switch has changed state
  thisState = digitalRead(startSwitch);
  if (thisState != lastSwitchState1)
  {  
    lastSwitchState1 = thisState;  //update the switch state
 
    if(thisState == HIGH)   // OR        
    //if(thisState == LOW)         
    {
     changed = !changed;
     }
  }
}
//======================================================================
//                       E N D   O F   C O D E
//======================================================================

At a minimum, you need to recode your function so it is non-blocking. It's the only way to keep the key input active. In other words, if the function is just waiting for time to elapse, it should return.

In debounceSwitches() try:

if(thisState == LOW)
{
changed = !changed;
digitalWrite (rly1, LOW);
digitalWrite (rly2, LOW);
digitalWrite (rly3, LOW);
digitalWrite (nop, LOW);
currentState = 4;
}