- Notifications
You must be signed in to change notification settings - Fork1
Finite-State Machine (FSM) for Arduino
License
MicroBeaut/Finite-State
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Finite-State provides a bounded state machine that combinesstate transitions, which has the following parts:
typedefstruct {Predicatepredicate;// Predicate Function Pointerid_tnextF;// Next State on FALSEid_tnextT;// Next State on TRUEProcessprocess;// Process Function PointerEventHandlereventHandler;// Event Function Pointertime_tdelayTime;// Delay TimeTimerTypetimerType;// Timer Type}Transition;
A Predicate Function will determine whether the specified object meets the criteria.
typedefbool (*Predicate)(id_t);// Predicate Function Pointer
The following function acceptsid from a caller; type is a parameter of typeid_t. The return type isboolean. It will be used to determine a Next-State for theNextF andnextT:
Syntax:
boolPredicateCallbackFunction(id_tid);// Predicate Callback Function
Example:
boolPredicateCallbackFunction(id_tid) {// TODO: PREDICATE FUNCTIONreturnbutton[id].isPressed(); }
Or,
boolPredicateCallbackFunction(id_tid) {// TODO: PREDICATE FUNCTIONreturnarray[id]==10; }
A Next-State has two destinations:
Next State On FALSE (
nextF)AnextF will be defined by the Id number when the return value from the condition of the Timer and Predicate function is
FALSE.Next State On TRUE (
nextT)ANext State On TURE will be defined by the Id number when the return value from the condition of the Timer and Predicate function is
TRUE.
The Process Function is a function to implement Input/Output control, read/write data, etc.
typedefvoid (*Process)(id_t);// Process Function Pointer
The following function acceptsid from a caller; type is parameters of typeid_t:
Syntax:
voidProcessCallbackFunction(id_tid);// Process Callback Function
Example:
voidMotorProcess(id_tid) {StatusStatestatus;if (motor[id].timerON) {if (motor[id].running) {status=RUNNING; }else {status=FAULT; }digitalWrite(motor[id].faultPin,status==FAULT); }}
NOTE: The Id can also be obtained fromobjectName.id.
id_tid=finiteStateMachine.id;
An Event Handler Function is an option. Finite-State will handle events when the state changes forENTRY andEXIT actions.
typedefvoid (*EventHandler)(EventArgs);// Event Handler Function Pointer
EventArgs:
typedefstruct {id_tid;// State idActionaction;// Action State}EventArgs;
Action:
enumAction {NONE,EXIT,ENTRY};
The following function acceptsid_t, andAction from a caller; type is the parameters of typeEventArgs:
Syntax:
voidEventCallbackFunction(EventArgse);// Event Callback Function
Example:
voidEvnetOnActionChanged(EventArgse) {switch (e.action) {caseENTRY:digitalWrite(motor[e.id].output, true);break;caseEXIT:digitalWrite(motor[e.id].output, false);break; }}
A Timer is an option. Finite-State will predict the condition for the next state with a timer when the timer type selects and the delay time value is greater than zero.
- Not Used Timer (
NOT_USED) - Transition Timer (
TRANS_TIMER) - Predicate Timer (
PREDIC_TIMER) - False-State Timer (
FALSE_TIMER) - True-State Timer (
TRUE_TIMER)
enumTimerType {NOT_USED,// Not Used TimerTRANS_TIMER,// Transition TimerPREDIC_TIMER,// Predicate TimerFALSE_TIMER,// False State TimerTRUE_TIMER,// True State Timer};
When Timer is not used, The predicate function is nonnullptr. The Predicate function's return value determines the condition for the next state.
State transitions can be defined as three options,
- Predicate Function with Process and Event
- Predicate Function with Process
- Predicate Function with Event
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | EventOnActionChanged | - | - |
1 | PredicateFunction | 1 | 0 | ProcessFunction | EventOnActionChanged | - | - |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,EventOnActionChanged},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,EventOnActionChanged}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | - | - | - |
1 | PredicateFunction | 1 | 0 | ProcessFunction | - | - | - |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | - | EventOnActionChanged | - | - |
1 | PredicateFunction | 1 | 0 | - | EventOnActionChanged | - | - |
boolPredicateFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,nullptr,EventOnActionChanged},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,nullptr,EventOnActionChanged}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
When selecting the transition timer, the condition for the next state will ignore the Predicate function's return value. It is the onlyNextT condition possible during the timer timeout. The predicate function isnullptr.
State transitions can be defined as three options,
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | - | 0 | 1 | ProcessFunction | EventOnActionChanged | 1,000 | TRANS_TIMER |
1 | - | 1 | 0 | ProcessFunction | EventOnActionChanged | 1,000 | TRANS_TIMER |
voidProcessFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {nullptr,0,1,ProcessFunction,EventOnActionChanged,1000,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,1,0,ProcessFunction,EventOnActionChanged,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | - | 0 | 1 | ProcessFunction | - | 1,000 | TRANS_TIMER |
1 | - | 1 | 0 | ProcessFunction | - | 1,000 | TRANS_TIMER |
voidProcessFunction(id_tid);Transitiontransitions[]= { {nullptr,0,1,ProcessFunction,nullptr,1000,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,1,0,ProcessFunction,nullptr,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | - | 0 | 1 | - | EventOnActionChanged | 1,000 | TRANS_TIMER |
1 | - | 1 | 0 | - | EventOnActionChanged | 1,000 | TRANS_TIMER |
voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {nullptr,0,1,nullptr,EventOnActionChanged,1000,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,1,0,nullptr,EventOnActionChanged,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
When selecting the predicate timer, the condition for the next state will ignore the Predicate function's return value during the timer running. The Predicate function's return value will be used for the state selection when the timer timeout. The predicate function is nonnullptr.
State transitions can be defined as three options,
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | EventOnActionChanged | 1,000 | PREDIC_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | EventOnActionChanged | 1,000 | PREDIC_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,EventOnActionChanged,1000,PREDIC_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,EventOnActionChanged,1000,PREDIC_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | - | 1,000 | PREDIC_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | - | 1,000 | PREDIC_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,nullptr,1000,PREDIC_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,nullptr,1000,PREDIC_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | - | EventOnActionChanged | 1,000 | PREDIC_TIMER |
1 | PredicateFunction | 1 | 0 | - | EventOnActionChanged | 1,000 | PREDIC_TIMER |
boolPredicateFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,nullptr,EventOnActionChanged,1000,PREDIC_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,nullptr,EventOnActionChanged,1000,PREDIC_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
When selecting the false-state timer, the condition for the next state will ignore the Predicate function'sFalse value except for theTrue deal during the timer running. The state will be accepted the "False" when the timer timeout. The predicate function is nonnullptr.
State transitions can be defined as three options,
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | EventOnActionChanged | 1,000 | FALSE_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | EventOnActionChanged | 1,000 | FALSE_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,EventOnActionChanged,1000,FALSE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,EventOnActionChanged,1000,FALSE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | - | 1,000 | FALSE_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | - | 1,000 | FALSE_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,nullptr,1000,FALSE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,nullptr,1000,FALSE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | - | EventOnActionChanged | 1,000 | FALSE_TIMER |
1 | PredicateFunction | 1 | 0 | - | EventOnActionChanged | 1,000 | FALSE_TIMER |
boolPredicateFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,nullptr,EventOnActionChanged,1000,FALSE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,nullptr,EventOnActionChanged,1000,FALSE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
When selecting the true-state timer, the condition for the next state will ignore the Predicate function'sTrue value except for theFalse deal during the timer running. The state will be accepted theTrue when the timer timeout. The predicate function is nonnullptr.
State transitions can be defined as three options,
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | EventOnActionChanged | 1,000 | TRUE_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | EventOnActionChanged | 1,000 | TRUE_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,EventOnActionChanged,1000,TRUE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,EventOnActionChanged,1000,TRUE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | ProcessFunction | - | 1,000 | TRUE_TIMER |
1 | PredicateFunction | 1 | 0 | ProcessFunction | - | 1,000 | TRUE_TIMER |
boolPredicateFunction(id_tid);voidProcessFunction(id_tid);Transitiontransitions[]= { {PredicateFunction,0,1,ProcessFunction,nullptr,1000,TRUE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,ProcessFunction,nullptr,1000,TRUE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|
0 | PredicateFunction | 0 | 1 | - | EventOnActionChanged | 1,000 | TRUE_TIMER |
1 | PredicateFunction | 1 | 0 | - | EventOnActionChanged | 1,000 | TRUE_TIMER |
boolPredicateFunction(id_tid);voidEventOnActionChanged(EventArgse);Transitiontransitions[]= { {PredicateFunction,0,1,nullptr,EventOnActionChanged,1000,TRUE_TIMER},// State-0 - NextF = 0, NextT = 1 {PredicateFunction,1,0,nullptr,EventOnActionChanged,1000,TRUE_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
STOP | 0 | HighTempPredicate | 0 | 1 | FanStopProcess | - | - | - |
START | 1 | LowTempPredicate | 1 | 0 | FanStartProcess | - | - | - |
Transitiontransitions[]= { {HighTempPredicate,0,1,FanStopProcess},// State-0 - NextF = 0, NextT = 1 {LowTempPredicate,1,0,FanStartProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumFanState :id_t {STOP,START};Transitiontransitions[]= { {HighTempPredicate,STOP,START,FanStopProcess},// State-0 - NextF = 0, NextT = 1 {LowTempPredicate,START,STOP,FanStartProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
#include"FiniteState.h"#definethermostatPin A0#definestartStatusPin 5#definestopStatusPin 6voidFanStartProcess(id_tid);voidFanStopProcess(id_tid);boolHighTempPredicate(id_tstate);boolLowTempPredicate(id_tstate);enumFanState :id_t {STOP,START};Transitiontransitions[]= { {HighTempPredicate,STOP,START,FanStopProcess},// State-0 - NextF = 0, NextT = 1 {LowTempPredicate,START,STOP,FanStartProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State ObjectconstlongThermostatRead();voidsetup() {pinMode(startStatusPin,OUTPUT);// Set the start status pin modepinMode(stopStatusPin,OUTPUT);// Set the sotp status pin modefiniteStateMachine.begin(STOP);// FSM begins with Initial Transition Id 0}voidloop() {finiteStateMachine.execute();// Execute the FSM}boolHighTempPredicate(id_tstate) {returnThermostatRead() >=40;// Determine Fan Start Action}boolLowTempPredicate(id_tstate) {returnThermostatRead() <=30;// Determine Fan Stop Action}voidFanStartProcess(id_tid) {digitalWrite(stopStatusPin, false);// Update fan stop statusdigitalWrite(startStatusPin, true);// Update fan start status}voidFanStopProcess(id_tid) {digitalWrite(startStatusPin, false);// Update fan start statusdigitalWrite(stopStatusPin, true);// Update fan stop status}constlongThermostatRead() {longvalue=analogRead(thermostatPin);// Read Pushbutton Valuereturnmap(value,0,1023,0,100);// Scaling temperature}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
RED | 0 | TimePredicate | 0 | 1 | - | EventOnActionChanged | - | - |
GREEN | 1 | TimePredicate | 1 | 2 | - | EventOnActionChanged | - | - |
YELLOW | 2 | TimePredicate | 2 | 0 | - | EventOnActionChanged | - | - |
Transitiontransitions[]= { {TimePredicate,0,1,nullptr,EventOnActionChanged},// State-1 - NextF = 0, NextT = 1 {TimePredicate,1,2,nullptr,EventOnActionChanged},// State-2 - NextF = 1, NextT = 2 {TimePredicate,2,0,nullptr,EventOnActionChanged},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumLightState {RED,GREEN,YELLOW};Transitiontransitions[]= { {TimePredicate,RED,GREEN,nullptr,EventOnActionChanged},// State-1 - NextF = 0, NextT = 1 {TimePredicate,GREEN,YELLOW,nullptr,EventOnActionChanged},// State-2 - NextF = 1, NextT = 2 {TimePredicate,YELLOW,RED,nullptr,EventOnActionChanged},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Traffic Light with Customized Timer
#include"FiniteState.h"#defineredLightPin 5#defineyellowLightPin 4#definegreenLightPin 3uint8_tlightPins[]= {redLightPin,greenLightPin,yellowLightPin};// Define an array of light pins.constuint8_tnumberOfLights=sizeof(lightPins) /sizeof(uint8_t);// Calculate the number of lights.typedefstruct {unsigned longdelayTime;unsigned longstartTime;}Timer;TimerdelayTimes[]= { {5000},// RED Delay Time 5 seconds {10000},// GREEN Delay Time 10 seconds {3000},// YELLOW Delay Time 3 seconds};boolTimePredicate(id_tid);// Predicate (Input)voidEventOnActionChanged(EventArgse);// Event StateenumLightState {RED,GREEN,YELLOW};Transitiontransitions[]= { {TimePredicate,RED,GREEN,nullptr,EventOnActionChanged},// State-1 - NextF = 0, NextT = 1 {TimePredicate,GREEN,YELLOW,nullptr,EventOnActionChanged},// State-2 - NextF = 1, NextT = 2 {TimePredicate,YELLOW,RED,nullptr,EventOnActionChanged},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Define Finite-State Objectvoidsetup() {for (uint8_tindex=0;index<numberOfLights;index++) {pinMode(lightPins[index],OUTPUT);// Set Pin ModedigitalWrite(lightPins[index],LOW);// Set Light with the LOW state. }finiteStateMachine.begin(RED);// FSM begins with Initial Transition Id 0}voidloop() {finiteStateMachine.execute();// Execute the FSM}boolTimePredicate(id_tid) {return (millis()-delayTimes[id].startTime >=delayTimes[id].delayTime);// Determine Time Delay}voidEventOnActionChanged(EventArgse) {switch (e.action) {caseENTRY:delayTimes[e.id].startTime=millis();// Reload start timedigitalWrite(lightPins[e.id],HIGH);// Set Light with the HIGH state.break;caseEXIT:digitalWrite(lightPins[e.id],LOW);// Set Light with the LOW state.break; }}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
RED | 0 | - | 0 | 1 | - | EventOnActionChanged | 5,000 | TRANS_TIMER |
GREEN | 1 | - | 1 | 2 | - | EventOnActionChanged | 10,000 | TRANS_TIMER |
YELLOW | 2 | - | 2 | 0 | - | EventOnActionChanged | 3,000 | TRANS_TIMER |
Transitiontransitions[]= { {nullptr,0,1,nullptr,EventOnActionChanged,5000,TRANS_TIMER},// State-1 - NextF = 0, NextT = 1 {nullptr,1,2,nullptr,EventOnActionChanged,10000,TRANS_TIMER},// State-2 - NextF = 1, NextT = 2 {nullptr,2,0,nullptr,EventOnActionChanged,3000,TRANS_TIMER},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumLightState :id_t {RED,GREEN,YELLOW};Transitiontransitions[]= { {nullptr,RED,GREEN,nullptr,EventOnActionChanged,5000,TRANS_TIMER},// State-1 - NextF = 0, NextT = 1 {nullptr,GREEN,YELLOW,nullptr,EventOnActionChanged,10000,TRANS_TIMER},// State-2 - NextF = 1, NextT = 2 {nullptr,YELLOW,RED,nullptr,EventOnActionChanged,3000,TRANS_TIMER},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Traffic Light with Transition Timer
#include"FiniteState.h"#defineredLightPin 5#defineyellowLightPin 4#definegreenLightPin 3uint8_tlightPins[]= {redLightPin,greenLightPin,yellowLightPin};// Define an array of light pins.constuint8_tnumberOfLights=sizeof(lightPins) /sizeof(uint8_t);// Calculate the number of lights.voidEventOnActionChanged(EventArgse);// Event StateenumLightState :id_t {RED,GREEN,YELLOW};Transitiontransitions[]= { {nullptr,RED,GREEN,nullptr,EventOnActionChanged,5000,TRANS_TIMER},// State-1 - NextF = 0, NextT = 1 {nullptr,GREEN,YELLOW,nullptr,EventOnActionChanged,10000,TRANS_TIMER},// State-2 - NextF = 1, NextT = 2 {nullptr,YELLOW,RED,nullptr,EventOnActionChanged,3000,TRANS_TIMER},// State-3 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Define Finite-State Objectvoidsetup() {for (uint8_tindex=0;index<numberOfLights;index++) {pinMode(lightPins[index],OUTPUT);// Set Pin ModedigitalWrite(lightPins[index],LOW);// Set Light with the LOW state. }finiteStateMachine.begin(RED);// FSM begins with Initial Transition Id 0}voidloop() {finiteStateMachine.execute();// Execute the FSM}voidEventOnActionChanged(EventArgse) {switch (e.action) {caseENTRY:digitalWrite(lightPins[e.id],HIGH);// Set Light with the HIGH state.break;caseEXIT:digitalWrite(lightPins[e.id],LOW);// Set Light with the LOW state.break; }}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
LOCKED | 0 | CoinPredicate | 0 | 1 | LockedProcess | - | - | - |
UNLOCKED | 1 | ArmPredicate | 1 | 0 | UnlockedProcess | - | - | - |
Transitiontransitions[]= { {CoinPredicate,0,1,LockedProcess},// State-0 - NextF = 0, NextT = 1 {ArmPredicate,1,0,UnlockedProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumTurnstileState :id_t {LOCKED,UNLOCKED};Transitiontransitions[]= { {CoinPredicate,LOCKED,UNLOCKED,LockedProcess},// State-0 - NextF = 0, NextT = 1 {ArmPredicate,UNLOCKED,LOCKED,UnlockedProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Coin Operated Turnstile with Predicate and Process
#include"FiniteState.h"#include"RepeatButton.h"#definecoinInputPin A0 // Define the Coin input pin.#definearmInputPin A1 // Define the Arm input pin.#definelockedStatusPin 7 // Define the Locked state output pin.#defineunlockedStatusPin 6 // Define the Unlocked state output pin.boolCoinPredicate(id_tid);// Declare Coin Predicate functionboolArmPredicate(id_tid);// Declare Arm Predicate functionvoidLockedProcess(id_tid);// Declare Locked Process functionvoidUnlockedProcess(id_tid);// Declare Unlocked Process functionenumTurnstileState :id_t {LOCKED,UNLOCKED};Transitiontransitions[]= { {CoinPredicate,LOCKED,UNLOCKED,LockedProcess},// State-0 - NextF = 0, NextT = 1 {ArmPredicate,UNLOCKED,LOCKED,UnlockedProcess}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatecoinOperatedTurnstile(transitions,numberOfTransitions);// Finite-State ObjectRepeatButtoncoin;// Declare the Coin RepeatButton objectRepeatButtonarm;// Declare the Arm RepeatButton objectvoidsetup() {coin.buttonMode(coinInputPin,INPUT_PULLUP);// Set the Coin input pin modearm.buttonMode(armInputPin,INPUT_PULLUP);// Set the Arm input pin modepinMode(lockedStatusPin,OUTPUT);// Set the Locked state pin modepinMode(unlockedStatusPin,OUTPUT);// Set the Unlocked state pin modecoinOperatedTurnstile.begin(LOCKED);// FSM begins with Initial Transition Id 0}voidloop() {coin.repeatButton();// Executing the Coin repeat button functionarm.repeatButton();// Executing the Arm repeat button functioncoinOperatedTurnstile.execute();// Execute the FSM}boolCoinPredicate(id_tid) {returncoin.isPressed();// Predicate putting a coin.}boolArmPredicate(id_tid) {returnarm.isPressed();// Predicate pushing the arm.}voidLockedProcess(id_tid) {digitalWrite(lockedStatusPin,HIGH);// Turn on the locked position status.digitalWrite(unlockedStatusPin,LOW);// Turn off the unlocked position status.}voidUnlockedProcess(id_tid) {digitalWrite(lockedStatusPin,LOW);// Turn off the locked position status.digitalWrite(unlockedStatusPin,HIGH);// Turn on the unlocked position status.}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
LOCKED | 0 | CoinPredicate | 0 | 1 | - | EventOnActionChanged | - | - |
UNLOCKED | 1 | ArmPredicate | 1 | 0 | - | EventOnActionChanged | - | - |
Transitiontransitions[]= { {inputPredicate,0,1,nullptr,EventOnActionChanged},// State-0 - NextF = 0, NextT = 1 {inputPredicate,1,0,nullptr,EventOnActionChanged}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumTurnstileState :id_t {LOCKED,UNLOCKED};Transitiontransitions[]= { {inputPredicate,LOCKED,UNLOCKED,nullptr,EventOnActionChanged},// State-0 - NextF = 0, NextT = 1 {inputPredicate,UNLOCKED,LOCKED,nullptr,EventOnActionChanged}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Coin Operated Turnstile with Predicate and Event
#include"FiniteState.h"#include"RepeatButton.h"#definecoinInputPin A0 // Define the Coin input pin.#definearmInputPin A1 // Define the Push input pin.#definelockedStatusPin 7 // Define the Locked state output pin.#defineunlockedStatusPin 6 // Define the Unlocked state output pin.boolinputPredicate(id_tid);// Declare Coin Predicate functionvoidEventOnActionChanged(EventArgse);// Event On Action ChangedenumTurnstileState :id_t {LOCKED,UNLOCKED};Transitiontransitions[]= { {inputPredicate,LOCKED,UNLOCKED,nullptr,EventOnActionChanged},// State-0 - NextF = 0, NextT = 1 {inputPredicate,UNLOCKED,LOCKED,nullptr,EventOnActionChanged}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatecoinOperatedTurnstile(transitions,numberOfTransitions);// Finite-State Objectuint8_tinputPins[numberOfTransitions]= {coinInputPin,armInputPin};// Declare the input pin arrayuint8_toutputPins[numberOfTransitions]= {lockedStatusPin,unlockedStatusPin};// Declare the output pin arrayRepeatButtonturnstileInputs[numberOfTransitions];// Declare the Turnstile Inputs RepeatButton objectvoidsetup() {for (uint8_tindex=0;index<numberOfTransitions;index++) {turnstileInputs[index].buttonMode(inputPins[index],INPUT_PULLUP);// Set the Turnstile repeat button pin modepinMode(outputPins[index],OUTPUT);// Set the Output state pin mode }coinOperatedTurnstile.begin(LOCKED);// FSM begins with Initial Transition Id 0}voidloop() {for (uint8_tindex=0;index<numberOfTransitions;index++) {turnstileInputs[index].repeatButton();// Executing the Turnstile repeat button function. }coinOperatedTurnstile.execute();// Execute the FSM.}boolinputPredicate(id_tid) {returnturnstileInputs[id].isPressed();// Predicate putting a coin and pushing the arm.}voidEventOnActionChanged(EventArgse) {switch (e.action) {caseENTRY:digitalWrite(outputPins[e.id],HIGH);// Turn on the turnstile position status.break;caseEXIT:digitalWrite(outputPins[e.id],LOW);// Turn off the previous turnstile position status.break; }}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
LED_OFF | 0 | - | 0 | 1 | TurnOffProcess | - | 500 | TRANS_TIMER |
LED_ON | 1 | - | 1 | 0 | TrunOnProcess | - | 1,000 | TRANS_TIMER |
Transitiontransitions[]= { {nullptr,0,1,TurnOffProcess,nullptr,500,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,1,0,TrunOnProcess,nullptr,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumLedState :id_t {LED_OFF,LED_ON};Transitiontransitions[]= { {nullptr,LED_OFF,LED_ON,TurnOffProcess,nullptr,500,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,LED_ON,LED_OFF,TrunOnProcess,nullptr,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
#include"FiniteState.h"voidTrunOnProcess(id_tid);// Declare Turn LED On Process functionvoidTurnOffProcess(id_tid);// Declare Turn LED Off Process functionenumLedState :id_t {LED_OFF,LED_ON};Transitiontransitions[]= { {nullptr,LED_OFF,LED_ON,TurnOffProcess,nullptr,500,TRANS_TIMER},// State-0 - NextF = 0, NextT = 1 {nullptr,LED_ON,LED_OFF,TrunOnProcess,nullptr,1000,TRANS_TIMER}// State-1 - NextF = 1, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStateblinkFS(transitions,numberOfTransitions);// Finite-State Objectvoidsetup() {pinMode(LED_BUILTIN,OUTPUT);// Set the LED_BUILTIN pin modeblinkFS.begin(LED_OFF);// FSM begins with Initial Transition Id 0}voidloop() {blinkFS.execute();// Execute the FSM}voidTrunOnProcess(id_tid) {digitalWrite(LED_BUILTIN,HIGH);// Turn on the LED.}voidTurnOffProcess(id_tid) {digitalWrite(LED_BUILTIN,LOW);// Turn off the LED.}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
RELEASED | 0 | ButtonPredicate | 0 | 1 | ReleasedProcess | - | - | - |
DEBOUNCE_T | 1 | ButtonPredicate | 0 | 2 | - | - | 10 | TRUE_TIMER |
PRESSED | 2 | ButtonPredicate | 3 | 2 | PressedProcess | - | - | - |
DEBOUNCE_F | 3 | ButtonPredicate | 0 | 2 | - | - | 10 | FALSE_TIMER |
#definedebounce 10 // Debounce Delay 10 millisecondsTransitiontransitions[]= { {ButtonPredicate,0,1,ReleasedProcess},// State-0 - NextF = 0, NextT = 1 {ButtonPredicate,0,2,nullptr,nullptr,debounce,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {ButtonPredicate,3,2,PressedProcess},// State-2 - NextF = 3, NextT = 2 {ButtonPredicate,0,2,nullptr,nullptr,debounce,FALSE_TIMER}// State-3 - NextF = 0, NextT = 2};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumDebounceState :id_t {RELEASED,DEBOUNCE_T,PRESSED,DEBOUNCE_F};#definedebounce 10 // Debounce Delay 10 millisecondsTransitiontransitions[]= { {ButtonPredicate,RELEASED,DEBOUNCE_T,ReleasedProcess},// State-0 - NextF = 0, NextT = 1 {ButtonPredicate,RELEASED,PRESSED,nullptr,nullptr,debounce,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {ButtonPredicate,DEBOUNCE_F,PRESSED,PressedProcess},// State-2 - NextF = 3, NextT = 2 {ButtonPredicate,RELEASED,PRESSED,nullptr,nullptr,debounce,FALSE_TIMER}// State-3 - NextF = 0, NextT = 2};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
#include"FiniteState.h"#definebuttonPin A0 // Define the Button input pin.#defineledPin 7 // Define the LED output pin.boolButtonPredicate(id_tid);// Declare Read Button Predicate functionvoidReleasedProcess(id_tid);// Declare Released Process functionvoidPressedProcess(id_tid);// Declare Pressed Process functionenumDebounceState :id_t {RELEASED,DEBOUNCE_T,PRESSED,DEBOUNCE_F};#definedebounce 10 // Debounce Delay 10 millisecondsTransitiontransitions[]= { {ButtonPredicate,RELEASED,DEBOUNCE_T,ReleasedProcess},// State-0 - NextF = 0, NextT = 1 {ButtonPredicate,RELEASED,PRESSED,nullptr,nullptr,debounce,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {ButtonPredicate,DEBOUNCE_F,PRESSED,PressedProcess},// State-2 - NextF = 3, NextT = 2 {ButtonPredicate,RELEASED,PRESSED,nullptr,nullptr,debounce,FALSE_TIMER}// State-3 - NextF = 0, NextT = 2};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatedebounceFS(transitions,numberOfTransitions);// Finite-State ObjectboolbuttonState;voidsetup() {pinMode(buttonPin,INPUT_PULLUP);// Set the Button input modepinMode(ledPin,OUTPUT);// Set the LED output pin modedebounceFS.begin(RELEASED);// FSM begins with Initial Transition Id 0}voidloop() {debounceFS.execute();// Execute the FSMdigitalWrite(ledPin,buttonState);// Set LED with the button State.}boolButtonPredicate(id_tid) {return !digitalRead(buttonPin);// Read Button value.}voidReleasedProcess(id_tid) {buttonState= false;// Set the Button state with false value.}voidPressedProcess(id_tid) {buttonState= true;// Set the Button state with true value.}
| State | Id | Predicate | Next State - F | Next State - T | Process | Event | Delay Time (mS) | Timer Type |
|---|---|---|---|---|---|---|---|---|
NORMAL | 0 | AnalogPredicate | 0 | 1 | NormalProcess | - | - | - |
PRE_ALARM | 1 | AnalogPredicate | 0 | 2 | PreAlarmProcess | - | 3,000 | TRUE_TIMER |
HIGH_ALARM | 2 | AnalogPredicate | 2 | 0 | HighAlarmProcess | - | - | - |
#definealarmDelay 3000 // Define alarm dalayTransitiontransitions[]= { {AnalogPredicate,0,1,NormalProcess},// State-0 - NextF = 0, NextT = 1 {AnalogPredicate,0,2,PreAlarmProcess,nullptr,alarmDelay,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {AnalogPredicate,2,0,HighAlarmProcess}// State-2 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.
Or,
enumAnalogState :id_t {NORMAL,PRE_ALARM,HIGH_ALARM};#definealarmDelay 3000 // Define alarm dalayTransitiontransitions[]= { {AnalogPredicate,NORMAL,PRE_ALARM,NormalProcess},// State-0 - NextF = 0, NextT = 1 {AnalogPredicate,NORMAL,HIGH_ALARM,PreAlarmProcess,nullptr,alarmDelay,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {AnalogPredicate,HIGH_ALARM,NORMAL,HighAlarmProcess}// State-2 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Object
#include"FiniteState.h"#defineprocessValuePin A0 // Define the Process value input pin.#definenormalPin 6 // Define the normal status output pin.#definepreAlarmPin 5 // Define the pre-alarm status output pin.#definehighAlarmPin 4 // Define the high-alarm status output pin.enumOperator {LT,// Less than operatorLE,// Less than or equal operatorGT,// Greater than operatorGE// Greater than or equal operator};constlongsetpoint=85;// Alarm Setpointconstlongdeadband=5;// Alarm DeadbandOperatoroperators []= {GE,GE,LT};// Comparison operatorslongsetpoints []= {setpoint,setpoint,setpoint-deadband};// Comparison setpointsconstlongAnalogRead();// Declare Analog Read FunctionvoidProcessAlarmStatus(boolnormal,boolpreAlarm,boolhighAlarm);// Declare Process Alarm Status FunctionlongprocessValue;// Declare processValue variableboolAnalogPredicate(id_tid);// Declare analog predicate FunctionvoidNormalProcess(id_tid);// Declare normal process FunctionvoidPreAlarmProcess(id_tid);// Declare pre-alarm process FunctionvoidHighAlarmProcess(id_tid);// Declare high-alarm process FunctionenumAnalogState :id_t {NORMAL,PRE_ALARM,HIGH_ALARM};#definealarmDelay 3000 // Define alarm dalayTransitiontransitions[]= { {AnalogPredicate,NORMAL,PRE_ALARM,NormalProcess},// State-0 - NextF = 0, NextT = 1 {AnalogPredicate,NORMAL,HIGH_ALARM,PreAlarmProcess,nullptr,alarmDelay,TRUE_TIMER},// State-1 - NextF = 0, NextT = 2 {AnalogPredicate,HIGH_ALARM,NORMAL,HighAlarmProcess}// State-2 - NextF = 2, NextT = 0};constuint8_tnumberOfTransitions=sizeof(transitions) /sizeof(Transition);// Calculate the number of transitions.FiniteStatefiniteStateMachine(transitions,numberOfTransitions);// Finite-State Objectvoidsetup() {pinMode(normalPin,OUTPUT);// Set the normal LED pin modepinMode(preAlarmPin,OUTPUT);// Set the pre-alarm LED pin modepinMode(highAlarmPin,OUTPUT);// Set the hith-alarm LED= pin modefiniteStateMachine.begin(NORMAL);// FSM begins with Initial Transition Id 0}voidloop() {finiteStateMachine.execute();// Execute the FSMprocessValue=AnalogRead();// Read processValue}voidNormalProcess(id_tid) {ProcessAlarmStatus(true, false, false);// Update process alarm status}voidPreAlarmProcess(id_tid) {ProcessAlarmStatus(false, true, false);// Update process alarm status}voidHighAlarmProcess(id_tid) {ProcessAlarmStatus(false, true, true);// Update process alarm status}boolAnalogPredicate(id_tid) {boolvalue;switch (operators[id]) {caseGE:value=processValue >=setpoints[id];// Compare process value with setpointbreak;caseLT:value=processValue<setpoints[id];// Compare process value with setpointbreak;default:value= false;break; }returnvalue;}voidProcessAlarmStatus(boolnormal,boolpreAlarm,boolhighAlarm) {digitalWrite(normalPin,normal);// Update normal statusdigitalWrite(preAlarmPin,preAlarm);// Update pre-alarm statusdigitalWrite(highAlarmPin,highAlarm);// Update high-alarm status}constlongAnalogRead() {longvalue=analogRead(processValuePin);// Read Process Valuereturnmap(value,0,1023,0,100);// Scaling processValue}
WikipediaFinite-State Machine
MathWorksModel Finite State Machines
About
Finite-State Machine (FSM) for Arduino
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.





