This repository has been archived by the owner on Mar 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
14a7637
commit e3a222f
Showing
1 changed file
with
96 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,123 +1,141 @@ | ||
#include <YA_FSM.h> | ||
#include <Servo.h> | ||
#include "YA_FSM.h" | ||
#include "Blinker.h" | ||
|
||
const byte SIG_TRAIN_IN = 2; | ||
const byte SIG_TRAIN_OUT = 3; | ||
#define SIG_TRAIN_IN 3 | ||
#define SIG_TRAIN_OUT 2 | ||
#define SERVO_PIN 6 | ||
|
||
const byte OUT_BAR_LOW = 11; | ||
const byte OUT_BAR_HIGH = 12; | ||
const byte OUT_LIGHT_BELL = 13; | ||
#define PASS_NOT_ALLOWED 11 | ||
#define PASS_ALLOWED 12 | ||
#define OUT_LIGHT_BELL 13 | ||
|
||
// After the train has passed, wait a little time to be sure | ||
#define MOVE_TIME 1000 // Time needed for GATE moving (up and down) | ||
#define WAIT_FREE 10000 // Wait time after train has gone (in case another train is arriving) | ||
#define BLINK_TIME 250 | ||
|
||
#define GATE_CLOSED 0 | ||
#define GATE_OPENED 90 | ||
|
||
// Create new FSM | ||
YA_FSM stateMachine; | ||
|
||
// Create a Blinker (included utility class) for led blink handling | ||
Blinker blinker(OUT_LIGHT_BELL, BLINK_TIME); | ||
|
||
// Handle the gate position | ||
Servo theGate; | ||
uint16_t servoPos = GATE_OPENED; | ||
|
||
// State Alias | ||
enum State {GATE_OPEN, GATE_LOWERING, GATE_CLOSE, GATE_WAIT, GATE_RISING }; | ||
|
||
// Helper for print labels instead integer when state change | ||
const char* const stateName[] PROGMEM = { "Gate OPEN", "Lowering GATE", "Gate CLOSE", "Wait time", "Rising GATE"}; | ||
|
||
// After the train has passed, wait a little time to be sure | ||
#define MOVE_TIME 5000 // Time needed for GATE moving (up and down) | ||
#define WAIT_FREE 15000 | ||
#define BLINK_TIME 250 | ||
|
||
// Instead of bool function() callback, in this example we will use | ||
// bool variables to trig two transitions (the others will trig on timout) | ||
bool theTrainIsComing = false; | ||
bool theTrainIsGone = false; | ||
|
||
void setup() { | ||
// Input/Output configuration | ||
pinMode(SIG_TRAIN_IN, INPUT_PULLUP); | ||
pinMode(SIG_TRAIN_OUT, INPUT_PULLUP); | ||
pinMode(OUT_BAR_LOW, OUTPUT); | ||
pinMode(OUT_BAR_HIGH, OUTPUT); | ||
pinMode(OUT_LIGHT_BELL, OUTPUT); | ||
|
||
Serial.begin(115200); | ||
while (!Serial) { ; } // Wait for serial to be ready (native USB board only) | ||
|
||
Serial.println(F("Starting State Machine...\n")); | ||
setupStateMachine(); | ||
|
||
onEnter(); // Call manually the onEnter() function to set outputs | ||
Serial.print(F("Active state: ")); | ||
Serial.println(stateMachine.ActiveStateName()); | ||
} | ||
|
||
void loop() { | ||
// Update State Machine | ||
stateMachine.Update(); | ||
|
||
// Update the bool variables according to the signal inputs | ||
theTrainIsGone = digitalRead(SIG_TRAIN_OUT) == LOW; | ||
theTrainIsComing = digitalRead(SIG_TRAIN_IN) == LOW; | ||
|
||
if (theTrainIsComing) { | ||
// Reset enter time of GATE_WAIT (if active) so timeout became | ||
// longer enough to wait two ore more trains one after the other | ||
stateMachine.SetEnteringTime(GATE_WAIT); | ||
} | ||
} | ||
|
||
|
||
// Define "on entering" callback function (the same for all states) | ||
void onEnter(){ | ||
void onEnter(){ | ||
switch (stateMachine.GetState() ){ | ||
case GATE_CLOSE: | ||
digitalWrite(OUT_BAR_LOW, HIGH); | ||
digitalWrite(PASS_NOT_ALLOWED, HIGH); | ||
Serial.println(F("The GATE is actually close")); | ||
break; | ||
case GATE_RISING: | ||
digitalWrite(OUT_BAR_LOW, LOW); | ||
case GATE_RISING: | ||
servoPos = GATE_OPENED; | ||
digitalWrite(OUT_LIGHT_BELL, LOW); | ||
Serial.println(F("The GATE is going to be opened")); | ||
break; | ||
case GATE_OPEN: | ||
digitalWrite(OUT_BAR_HIGH, HIGH); | ||
digitalWrite(PASS_NOT_ALLOWED, LOW); | ||
digitalWrite(PASS_ALLOWED, HIGH); | ||
Serial.println(F("The GATE is actually open")); | ||
break; | ||
case GATE_LOWERING: | ||
digitalWrite(OUT_BAR_HIGH, LOW); | ||
servoPos = GATE_CLOSED; | ||
digitalWrite(PASS_ALLOWED, LOW); | ||
digitalWrite(PASS_NOT_ALLOWED, HIGH); | ||
Serial.println(F("A new train is coming! Start closing the GATE.")); | ||
Serial.println(F("The GATE is going to be closed")); | ||
break; | ||
case GATE_WAIT: | ||
Serial.println(F("The GATE is stille closed and we have to wait a little")); | ||
Serial.println(F("Train passed, but we have to wait a little time more")); | ||
break; | ||
} | ||
} | ||
|
||
// Blink and play the bell while gate is moving or closed | ||
void onStateMoveOpen(){ | ||
static uint32_t bTime; | ||
if(millis() - bTime > BLINK_TIME) { | ||
bTime = millis(); | ||
digitalWrite(OUT_LIGHT_BELL, !digitalRead(OUT_LIGHT_BELL)); | ||
} | ||
// Blink and play the bell while gate is moving or closed | ||
void blinkAndHorn(){ | ||
blinker.blink(true); | ||
} | ||
|
||
|
||
// Setup the State Machine | ||
void setupStateMachine() { | ||
|
||
/* | ||
* Follow the order of enumeration for the state definition, if used. | ||
* Index of states will be increased in library on every AddState() | ||
* In this way, enumerated index of skecth will match the library index. | ||
void setupStateMachine() { | ||
/* | ||
Follow the order of defined enumeration for the state definition (will be used as index) | ||
You can add the states with 3 different overrides: | ||
Add States => name, timeout, minTime, onEnter cb, onState cb, onLeave cb | ||
Add States => name, timeout, onEnter cb, onState cb, onLeave cb | ||
Add States => name, onEnter cb, onState cb, onLeave cb | ||
*/ | ||
|
||
// Add States => name,timeout, onEnter cb, onState cb, onLeave cb | ||
stateMachine.AddState(stateName[GATE_OPEN], 0, onEnter, nullptr, nullptr); | ||
stateMachine.AddState(stateName[GATE_LOWERING], MOVE_TIME, onEnter, onStateMoveOpen, nullptr); | ||
stateMachine.AddState(stateName[GATE_CLOSE], 0, onEnter, onStateMoveOpen, nullptr); | ||
stateMachine.AddState(stateName[GATE_WAIT], WAIT_FREE, onEnter, onStateMoveOpen, nullptr); | ||
stateMachine.AddState(stateName[GATE_RISING], MOVE_TIME, onEnter, onStateMoveOpen, nullptr); | ||
stateMachine.AddState(stateName[GATE_OPEN], onEnter, nullptr, nullptr); | ||
stateMachine.AddState(stateName[GATE_LOWERING], MOVE_TIME, onEnter, blinkAndHorn, nullptr); | ||
stateMachine.AddState(stateName[GATE_CLOSE], onEnter, blinkAndHorn, nullptr); | ||
stateMachine.AddState(stateName[GATE_WAIT], WAIT_FREE, onEnter, blinkAndHorn, nullptr); | ||
stateMachine.AddState(stateName[GATE_RISING], MOVE_TIME, onEnter, blinkAndHorn, nullptr); | ||
|
||
// Add transitions with related trigger input callback functions | ||
stateMachine.AddTransition(GATE_OPEN, GATE_LOWERING, theTrainIsComing); | ||
stateMachine.AddTransition(GATE_LOWERING, GATE_CLOSE, [](){return stateMachine.CurrentState()->timeout;} ); | ||
stateMachine.AddTransition(GATE_CLOSE, GATE_WAIT, theTrainIsGone); | ||
stateMachine.AddTransition(GATE_WAIT, GATE_RISING, [](){return stateMachine.CurrentState()->timeout;} ); | ||
stateMachine.AddTransition(GATE_RISING, GATE_OPEN, [](){return stateMachine.CurrentState()->timeout;} ); | ||
stateMachine.AddTransition(GATE_OPEN, GATE_LOWERING, theTrainIsComing); | ||
stateMachine.AddTransition(GATE_CLOSE, GATE_WAIT, theTrainIsGone); | ||
|
||
// Add "timed" transitions: it will be triggered on state timeout | ||
stateMachine.AddTransition(GATE_LOWERING, GATE_CLOSE); | ||
stateMachine.AddTransition(GATE_WAIT, GATE_RISING); | ||
stateMachine.AddTransition(GATE_RISING, GATE_OPEN); | ||
} | ||
|
||
|
||
void setup() { | ||
// Input/Output configuration | ||
pinMode(SIG_TRAIN_IN, INPUT_PULLUP); | ||
pinMode(SIG_TRAIN_OUT, INPUT_PULLUP); | ||
pinMode(PASS_NOT_ALLOWED, OUTPUT); | ||
pinMode(PASS_ALLOWED, OUTPUT); | ||
|
||
Serial.begin(115200); | ||
Serial.println(F("Starting State Machine...\n")); | ||
setupStateMachine(); | ||
|
||
onEnter(); // Call first time the onEnter() function to set outputs | ||
Serial.print(F("Active state: ")); | ||
Serial.println(stateMachine.ActiveStateName()); | ||
|
||
theGate.attach(SERVO_PIN); | ||
} | ||
|
||
void loop() { | ||
theGate.write(servoPos); | ||
|
||
// Update State Machine | ||
stateMachine.Update(); | ||
|
||
// Update the bool variables according to the signal inputs | ||
theTrainIsGone = digitalRead(SIG_TRAIN_OUT) == LOW; | ||
theTrainIsComing = digitalRead(SIG_TRAIN_IN) == LOW; | ||
|
||
if (theTrainIsComing) { | ||
// Reset enter time of GATE_WAIT so timeout became longer enough | ||
// to wait two ore more trains one after the other | ||
stateMachine.SetEnteringTime(GATE_WAIT); | ||
if (stateMachine.GetState() == GATE_WAIT ) { | ||
delay(500); | ||
Serial.println(F("Another train is arriving, wait more time!")); | ||
} | ||
} | ||
} |