@jensenjosht Sry sry sry, I don't know what part of my brain appears to have been disabled, nor what caused it.
I am now reading your code, which already has applied much of my subsequently suggested advice.
Since you have an enum type, there is no need to
int last = 0; //Previous state case. 0=ST_OFF, 1=ST_APPROACH_N, 2=ST_APPROACH_S, 3=ST_ISLAND, 4=ST_CLEARING_N, 5=ST_CLEARING_S.
int current = 0; //Current state case. 0=ST_OFF, 1=ST_APPROACH_N, 2=ST_APPROACH_S, 3=ST_ISLAND, 4=ST_CLEARING_N, 5=ST_CLEARING_S.
make a comment explaining the use of numbers for last and current, you can use the symbols directly, viz:
current = ST_APPROACH_N;
It looks like you could declare last and current to be CROSSINGSTATES or, in an old fashioned turn, jettison the beauty of CROSSINGSTATES and just use int or byte types for anything that is holding a state value.
In that case, switch (see what I did there?) to an "anonymous enum"
enum {
ST_OFF = 0,
ST_APPROACH_N,
ST_APPROACH_S,
ST_ISLAND,
ST_CLEARING_N,
ST_CLEARING_S,
};
But what is slowing me down (!) and is stretching the FSM idea, is that your use of last and current makes it look like the state of the machine depends on how it got there. You shouldn't need to know the previous state. In a traffic lights situation, the state is manifest - just look at the lights. There are timers, yes, which technically go into the true full state of affairs, so to speak, but timers are something sorta understood.
Which just means to me that you need different states or more of them, perhaps states that are transitional in nature.
Code like this
if (north == LOW && island == LOW && south == HIGH && last == 1) { //Keep the light and bell sequence going if one of the approach circuits and the island circuit are activated.
looks like binary coding of the three inputs being discriminated by logical expressions. It may be easier to form a number 0..7 of these three bits. Perhaps the 8 possibilities have meaningful names.
This
digitalWrite(LIGHT_LEFT, LOW); //Alternating flashing lights at 120 flashes per minute. Code block repeats until a meet break condition is satisfied.
digitalWrite(LIGHT_RIGHT, HIGH);
digitalWrite(BELL_RELAY, LOW);
delay(500);
digitalWrite(LIGHT_LEFT, HIGH);
digitalWrite(LIGHT_RIGHT, LOW);
digitalWrite(BELL_RELAY, LOW);
delay(500);
might not be killing you at all, but in a "real" system this activity would be controlled by... an FSM (you can have as many as you need), albeit a simple one that is either ON or OFF, and which is always called at the loop() level to do (or not do) the blinking and beeping.
Then in three places instead of the literal activity of the above lines you would just
bellsAndLightsState = ACTIVE;
and presumably find a reason elsewhere to
bellsAndLightsState = IDLE;
Now I hope you haven't already so my next request will be new information that might help... I'm a bit confused. In general and always, but here I refer to your description of the A-I-A track layout, which I gather is not symmetrical.
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.
I am guessing a track circuit is a lenght of rails that can, as you described, say whether any train parts are on it.
What happens the other 10% of the time? Why does Track circuit two differ from Track circuit 2, and what does being activated from the other direction even mean?
I think you are on the right track (again, see what I did there?), and that you are way closer to being able to program this that I am to being able to figure out what's going on.
But so far it is still fun, so.
a7
