// https://wokwi.com/projects/366646774211372033
// https://forum.arduino.cc/t/approach-island-approach-rr-crossing/1121055
# include "track.h"
// inputs
#define NORTH_APPROACH 5
#define ISLAND_CIRCUIT 6
#define SOUTH_APPROACH 7
// outputs
#define LIGHT_RIGHT 10
#define LIGHT_LEFT 9
#define BELL_RELAY 11
unsigned long now; // current time for all
enum {OFF_, ON_, xx};
byte flashQQ; // are we flashing or no?
# define ACTIVE LOW // my switches pulled high. OMG tangle of sense and == LOW ARGH! LED sense FIX
byte northActive, islandActive, southActive;
void setup() {
Serial.begin(115200);
Serial.println("\napproach - island - approach world!\n");
initTrack();
pinMode(NORTH_APPROACH, INPUT_PULLUP); //Track circuit one. 60ft/39.5m long. Primary circuit the train activates 90% of the time.
pinMode(ISLAND_CIRCUIT, INPUT_PULLUP); //Island circuit. 30ft/9m long. Circuit travels through a #5 Right hand Turnout that diverges.
pinMode(SOUTH_APPROACH, INPUT_PULLUP); //Track circuit two. Same length as number one, but needs to be able to activate the crossing from the other direction.
pinMode(BELL_RELAY, OUTPUT); //RR Bell Coil/SoundByte Speaker.
pinMode(LIGHT_LEFT, OUTPUT); //Left Flashing Light.
pinMode(LIGHT_RIGHT, OUTPUT); //Right Flashing Light.
}
byte iWas, iAm; // previous inputs compare to current inputs informs turning on or off the lights
void loop() {
// just to test the output function switch it on and off with the island value
// flashQQ = digitalRead(ISLAND_CIRCUIT) ? ON_ : OFF_;
outputFSM();
static unsigned long lastTime;
now = millis();
if (now - lastTime < 50) return; // loop throttle 20 Hz also will debounce switches automatically
lastTime = now;
updateTrain();
northActive = digitalRead(NORTH_APPROACH) == ACTIVE;
islandActive = digitalRead(ISLAND_CIRCUIT) == ACTIVE;
southActive = digitalRead(SOUTH_APPROACH) == ACTIVE; // not NORTH!
// soon to be previous inputs
iWas = iAm;
// current inputs encoded
iAm = 4 * islandActive + 2 * northActive + southActive;
tableAdvance();
}
byte table[8][3] = {
{OFF_, ON_, ON_}, // was 0
{OFF_, xx, xx}, // was 1
{OFF_, xx, xx}, // was 2
{xx, xx, xx}, // 3 is impossible
{xx, xx, xx}, // was 4, won't use these entries
{xx, OFF_, xx}, // was 5
{xx, xx, OFF_}, // was 6
{xx, xx, xx}, // was 7, won't use these entries
};
void tableAdvance()
{
if (iAm == iWas) return;
Serial.print(iWas);
Serial.print(" --> "); Serial.print(iAm);
if (iAm >= 4) {
flashQQ = ON_;
Serial.print(" so ON");
Serial.println();
}
else {
byte action = table[iWas][iAm];
// this transition is not possible!
if (action == xx) Serial.println("Rotten Denmark!");
Serial.print(" therefore "); Serial.print(action);
Serial.println();
flashQQ = action ? ON_ : OFF_;
}
}
// change for wiring differences
# define LED_OFF LOW
# define LED_ON HIGH
# define RELAY_ON HIGH
# define RELAY_OFF LOW
void outputFSM()
{
static int phase;
static unsigned long lastTime;
if (now - lastTime < 777) return;
lastTime = now;
if (flashQQ == OFF_) {
digitalWrite(LIGHT_LEFT, LED_OFF);
digitalWrite(LIGHT_RIGHT, LED_OFF);
digitalWrite(BELL_RELAY, RELAY_OFF);
phase = 0;
return;
}
// for now, just a level. comment and change the if/else
digitalWrite(BELL_RELAY, RELAY_ON);
if (!phase) {
digitalWrite(LIGHT_LEFT, LED_ON);
digitalWrite(LIGHT_RIGHT,LED_OFF);
// digitalWrite(BELL_RELAY, RELAY_ON);
}
else {
digitalWrite(LIGHT_LEFT, LED_OFF);
digitalWrite(LIGHT_RIGHT, LED_ON);
// digitalWrite(BELL_RELAY, RELAY_OFF);
}
phase = !phase;
}
TRAIN POSITION
TRAIN LENGTH
SOU
ISL
NOR
MANUAL/AUTO -->