/*
Forum: https://forum.arduino.cc/t/changing-led-state-with-ir-sensors/1434325/2
Wokwi: https://wokwi.com/projects/457940661339301889
Simple Signal Light, both directions
starts with green signal
press red or green button (train enters block from LEFT or RIGHT)
signal switches to red
press green or red button (train starts leaving block to the RIGHT or to the LEFT)
release green or red button (train hast completely left the block)
signal switches to green again
ec2021
*/
constexpr byte redPin {12};
constexpr byte greenPin {11};
constexpr byte blockLeftPin {7};
constexpr byte blockRightPin {6};
enum class BLOCK {FREE, OCCUPIED};
BLOCK blockState = BLOCK::FREE;
class blockSensor {
private:
byte pin;
byte state = HIGH;
byte lastState = HIGH;
unsigned long lastChange = 0;
boolean changed() {
byte actState = digitalRead(pin);
if (actState != lastState) {
lastChange = millis();
lastState = actState;
}
if (actState != state && millis() - lastChange > 30) {
state = actState;
return true;
}
return false;
};
public:
void init(byte Pin) {
pin = Pin;
pinMode(pin, INPUT_PULLUP);
};
boolean pressed() {
if (changed()) {
return !state;
} else {
return false;
}
};
boolean released() {
if (changed()) {
return state;
} else {
return false;
}
};
};
blockSensor blockLeft, blockRight;
blockSensor *blockPtr;
void setup() {
Serial.begin(115200);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
blockLeft.init(blockLeftPin);
blockRight.init(blockRightPin);
signalToGreen();
Serial.println("Start");
}
void loop() {
stateMachine();
}
void signalToRed() {
digitalWrite(redPin, HIGH);
digitalWrite(greenPin, LOW);
}
void signalToGreen() {
digitalWrite(redPin, LOW);
digitalWrite(greenPin, HIGH);
}
void stateMachine() {
switch (blockState) {
case BLOCK::FREE:
if (blockLeft.pressed()) {
blockOccupied("LEFT");
blockPtr = &blockRight;
}
if (blockRight.pressed()) {
blockOccupied("RIGHT");
blockPtr = &blockLeft;
}
break;
case BLOCK::OCCUPIED:
if (blockPtr->released()) {
Serial.println("Train left block ...");
signalToGreen();
blockState = BLOCK::FREE;
}
break;
}
}
void blockOccupied(char *msg) {
Serial.print("Train entered block from ");
Serial.println(msg);
signalToRed();
blockState = BLOCK::OCCUPIED;
}