Assistance Needed to Understand FSM Code

Hi Everyone

I have successfully ran my code with nested if /else statements but due to the project size i was persuaded to try the State Machine way..

Unfortunately i can't seem to get my head round the programming code side of this

const long DBTIME = 25; // number of ms allowed to eliminate key bounce
int machinestate();

bool debounce(bool state, bool val, long time, long dbTime, bool& lastVal, long& lastTime) {
// We will only register a change of state if the input value has not
// changed for a certain time
  bool newState;

  newState = state;         // by default the new state is the old state

  if (lastVal != val) {     // if the input value has changed
    lastTime = time;        // set the last time it changed to "now"
    lastVal = val;          // and retain the current input value
  } else {                  // otherwise (input value has NOT changed) 
    if ((time - lastTime) >= dbTime) { // has it remained stable long enough
      newState = val;       // change the state
    }
  }
  
  return newState;          // This is the new state
}

bool simpleDebounce(int inPin, bool& state, bool& lastVal, long& lastTime) {
// A debounce routine with a simpler interface.
  long time = millis();             // time in milliseconds
  bool val = digitalRead(inPin);    // current pin value
  long dbTime = DBTIME;               // the debounce interval
  
  state = debounce(state, val, time, dbTime, lastVal, lastTime); // debounce the pin
  
  return state;                     // return state
}

//
// INPUTS
//

// button A1 - London End Fiddle Yard Down "Train Ready Dispatch"
const int buttonA1 = 8;
bool lastButtonA1;
bool currentButtonA1;
long lastButtonA1Time;
bool btnA1Edge;

// Button B1 - London End Main Control Down "Train Accepted"
const int buttonB1 = 7;
bool lastButtonB1;
bool currentButtonB1;
long lastButtonB1Time;
bool btnB1Edge;


// Button B2 - London End Main Control Down "Ready Next Service"
const int buttonB2 = 6;
bool lastButtonB2;
bool currentButtonB2;
long lastButtonB2Time;
bool btnB2Edge;

//
// OUTPUTS
//

// LED A1 - Amber - "Train Ready Dispatch"
const int ledA1 = 5;
bool ledOnA1 = false;

// LED B1 - Green - "Train Accepted"
const int ledB1 = 4;
bool ledOnB1 = false;

// LED B2 - Red - "Ready Next Service"
const int ledB2 = 3;
bool ledOnB2 = false;

void writeLEDStates() {
// writes the current states to the LEDs
  digitalWrite(ledA1, ledOnA1);
  digitalWrite(ledB1, ledOnB1);
  digitalWrite(ledB2, ledOnB2);
}

void setup(){
  
  // initialize pins
  pinMode(buttonA1, INPUT);
  pinMode(buttonB1, INPUT);
  pinMode(buttonB2, INPUT);
  
  pinMode(ledA1, OUTPUT);
  pinMode(ledB1, OUTPUT);
  pinMode(ledB2, OUTPUT);
  
  // set output states
  writeLEDStates();
 
  // get the initial state of buttons
  currentButtonA1 = lastButtonA1 = digitalRead(buttonA1); 
  lastButtonA1Time = millis();
  
  currentButtonB1 = lastButtonB1 = digitalRead(buttonB1); 
  lastButtonB1Time = millis();
  
  currentButtonB2 = lastButtonB2 = digitalRead(buttonB2); 
  lastButtonB2Time = millis();
}
  

void readSwitchStates() {
// read the current button states
  simpleDebounce(buttonA1, currentButtonA1, lastButtonA1, lastButtonA1Time);
  simpleDebounce(buttonB1, currentButtonB1, lastButtonB1, lastButtonB1Time);
  simpleDebounce(buttonB2, currentButtonB2, lastButtonB2, lastButtonB2Time);
}

bool pressEdge(bool& state, bool lastVal) {
// detects the leading edge of a button press.
  if ((!state) && lastVal) { // button pressed, but state not yet set
    state = true;            // set the state without waiting for debouncing
    return true;             // return a valid edge
  } else {
    return false;            // it's not a press edge.
  }
  
  bool btnA1Edge = pressEdge(currentButtonA1, lastButtonA1);
  bool btnB1Edge = pressEdge(currentButtonB1, lastButtonB1);
  bool btnB2Edge = pressEdge(currentButtonB2, lastButtonB2); 
}
    

 void function setStateB(bool &bState, long &lTime, bool bValue,bool bChanged) { // gather data and pass to void function stateChange
    if (bState != bValue) {
      bState = bValue;
      lTime = millis();
      bChanged = true;
    }
 }

  void function setStateI(int &iState, long &lTime, int iValue, bool bChanged) { // gather data
    if (iState != iValue) {
      iState = iValue;
      lTime = millis();
      bChanged = true;
    }
  }
  
  void  function stateChange () { // run test to decide machineState pass to void function machineStates
  setbState(bState,ltime= true)
  bChanged = false;
 

  switch(bState)  {     
    case 0:         
      if (!btnA1Edge || !btnB1Edge || !btnB2Edge) {
         machineState(-1) 
       }
      break;
      
    case 1:         
      if (btnA1Edge) {
          machineState(1)
      }
      break; 
  
     case 2:         
      if (btnB1Edge) {
         machineState(2);
      }
      break;  
     
     case 3:         
      if (btnB2Edge) {
         machineState(3);
      }  
      default:
      machineState = (0);
      break; 
  }
  }
  
  void function machineState(int newState) { // Set output states
  setStateI(iState, lStateTime, true);
  
  switch ( iState ) {

    case 0 :
      
      break;

    case 1 :
      
      break;

    case 2 :
     
      break;

    case 3 :
      
  }
}
 
void loop() {

  while (true) {
    // get input states
    readSwitchStates();
  
    // set output states
    writeLEDStates();
  }
 void function setStateB;
 void function setStateI;   
 void  function stateChange();
 void function machineState();
     
  }  
}

Can't Get Rid of these faults

Steve_FSM1:8: error: expected initializer before 'setStateB'
Steve_FSM1:9: error: expected initializer before 'setStateI'
Steve_FSM1:10: error: expected initializer before 'stateChange'
Steve_FSM1:11: error: expected initializer before 'machineState'
Steve_FSM1:131: error: expected initializer before 'setStateB'

Also how do i get the machineState() function to work ? how and where to i declare this?
machineState(-1); machineState(1)

 switch(bState)  {     
    case 0:         
      if (!btnA1Edge || !btnB1Edge || !btnB2Edge) {
        machineState(-1) 
       }
      break;
      
    case 1:         
      if (btnA1Edge) {
         machineState(1)
      }
      break;
void function setStateB(b...

Looks like you're mixing C and Pascal there.... Pick one or the other, but don't mix both. If you don't know which to pick, then a hint: You can't program an Arduino in Pascal :stuck_out_tongue:

"function" is not a keyword in C.

You must have ';' after each statement - try auto-formatting to see some of the
numerous errors like this.

You must declare global variables before you use them.

What the lines at the end of loop() supposed to do?

void loop() {

  while (true) {
    // get input states
    readSwitchStates();
  
    // set output states
    writeLEDStates();
  }
 void function setStateB;       //// Huh???
 void function setStateI;   
 void  function stateChange();
 void function machineState();
     
  }  
}
void loop() {

  while (true) {

It makes no sense to have nothing but an infinite loop in an infinite loop(). Get rid of one of them.

Sorry the loop() statements were a left over from last code with a reminder to put statements for FSN in :blush:

Still looking for the solution

I understand that " the beauty of Finite State Machines is that one FSM can change the state of another".

But unfortunately the tutorial http://hacking.majenko.co.uk/finite-state-machine fell short of showing how this was achieved :stuck_out_tongue_closed_eyes:

Let's take a simple example to help illustrate how to make an FSM. Let's say you have an automatic gate controlling access to a car park. The gate wants to stay closed until a car drives up to it. When the car arrives you want to open the gate and flash a warning light while it opens. Once the gate is open, you need to wait for the car to go through, then give a little extra time, and close the gate, flashing the light while you do.

#define S_IDLE 1 
#define S_LEDON 2
#define S_WAITON 3 
#define S_LEDOFF 4 
#define S_WAITOFF 5
#define S_TURNOFF 6 

void setup() { 
pinMode(13,OUTPUT);
 } 

void loop() {

 static int state = S_IDLE; // initial state is 1, the "idle" state. static 
unsigned long ts; // To store the "current" time in for delays. 

switch(state)
 {
  case S_IDLE:
       // We don't need to do anything here, waiting for a forced state change.
  break;

  case S_LEDON: 
      digitalWrite(13,HIGH); // Turn on the light 
      ts = millis(); // Remember the current time 
      state = S_WAITON; // Move to the next state 
      break; 

  case S_WAITON: // If one second has passed, then move on to the next state. 
     if(millis() > ts + 1000)
    { 
    state = S_LEDOFF;
    } 
   break; 

  case S_LEDOFF: 
     digitalWrite(13,LOW); // Turn off the light 
    ts = millis(); // Remember the current time
    state = S_WAITOFF;
    break;

  case S_WAITOFF: // If one second has passed, then go back to state 2. 
      if(millis() > ts + 1000)
     {
     state = S_LEDON; 
    }
    break; 

  case S_TURNOFF: // We only get here when forced from outside. 
      digitalWrite(13,LOW); // Turn off the light 
      state = S_IDLE; // Return to the "idle" state. 
     break; 

  default: 
    state = S_IDLE; 
    break;
 } }

Can anyone enlighten me as to how to reference this FSM in another FSM.......
Or maybe a link to another tutorial that shows how to interact between 2 seperate FSM (1 for Outputs, 1 for Inputs)

Something along the lines that a button press = the car arriving at the pressure pad

Thanks

Mark

An FSM control is just a variable. Just change that variable from the other FSM.

State 1 = idle
State 2 = idle

If State 1 == Somestate
  State 2 = Some Other State
End If

...etc