/*
train crossing activated either from east or west
https://forum.arduino.cc/t/2-pushbutton-on-off/1293385/7
2024-08-21 by noiasca
code in thread
*/
class Crossing {
protected:
const uint8_t pinA; // contact low active
const uint8_t pinB; // contact low active
const uint32_t delayOpen {5000}; // time after the last axcel has passed to open the crossing
enum State {IDLE, FROM_A, FROM_B, WAIT_A, WAIT_B} state = IDLE; // the states for the internal state machine
uint32_t previousMillis = 0; // time management
using Callback = void(*)(void);
Callback fctOpen, fctClose; // callback functions for open/close the crossing
public:
Crossing(const uint8_t pinA, const uint8_t pinB, Callback fctClose, Callback fctOpen) : pinA(pinA), pinB(pinB), fctOpen(fctOpen), fctClose(fctClose) {}
// to be called in setup
void begin() {
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
}
// the FSM to be called in loop
void update() {
switch (state) {
case IDLE:
if (digitalRead(pinA) == LOW) {
state = FROM_A;
fctClose();
}
else if (digitalRead(pinB) == LOW) {
state = FROM_B;
fctClose();
}
break;
case FROM_A:
if (digitalRead(pinB) == LOW) {
previousMillis = millis();
Serial.println("first axel passed");
state = WAIT_A;
}
break;
case WAIT_A :
if (digitalRead(pinB) == LOW) {
previousMillis = millis();
}
if (millis() - previousMillis > delayOpen) {
fctOpen();
state = IDLE;
}
break;
case FROM_B:
if (digitalRead(pinA) == LOW) {
Serial.println("first axel passed");
previousMillis = millis();
state = WAIT_B;
}
break;
case WAIT_B :
if (digitalRead(pinA) == LOW) {
previousMillis = millis();
}
if (millis() - previousMillis > delayOpen) {
fctOpen();
state = IDLE;
}
break;
}
}
};
constexpr uint8_t lightPin {4}; // just as demo - this crossing as only a steady light
void block() {
Serial.println("what ever needed to block that crossing");
digitalWrite(lightPin, HIGH);
}
void unblock() {
Serial.println("what ever needed to unblock that crossing");
digitalWrite(lightPin, LOW);
}
Crossing crossing(2, 3, block, unblock); // a crossing with two contacts and two function what to do to block or unblock
void setup() {
Serial.begin(115200);
crossing.begin(); // start the contact/button
}
void loop() {
crossing.update();
}
//