//Track_Train_ESP.ino//Tracking Train with ESP8266//Due to pin limitations serial in and serial out//After change in status program will send out train status to serial//Program will turn on signals in RED-AMBER-GREEN sequence when train detected//Program assumes only one train in the block//Program resets (wdt)if no change in status after 20 seconds.//WDT assumes some external source has set sequence.//Assumes 4 sensors giving states {coming,arriving,departing,going} //Assumes train is shorter than distance between sensors//Between sensors are the states {approaching,station,leaving}//With no trains the state will be waiting
#define BOTH_WAYS 0
#include <Signals3_Serial_Class.h> //4 three aspect signals interfaced via serial chip#include <LDR_Serial_Sensor_Class.h> //4 LDR sensors interface via serial chip
#define WDT_TIME 20000 //20 seconds - 20s OK on the bench - in practice minutes?
#if BOTH_WAYS enum where_is_train {waiting,coming0,approaching0,arriving0,station0,departing0,leaving0,going0, coming1,approaching1,arriving1,station1,departing1,leaving1,going1,} the_train;#else enum where_is_train {waiting,coming,approaching,arriving,station,departing,leaving,going} the_train;#endif
//Instances of objects of the 2 classes
Signals3_Serial_Class signal(D2,D1); //serial & clock pinsLDR_Serial_Sensor_Class sensor(D0,D5,D6); //serial, load & clock pins
void setup() { signal.begin( ); sensor.begin( ); Serial.begin(115200); the_train = waiting;}#if BOTH_WAYS//tests for next state - no other action//returns next state. where_is_train train(int s0, int s1, int s2, int s3){ switch (the_train) { case waiting : if (s0) the_train = coming0; if (s3) the_train = coming1; break; case coming0 : if (!s0) the_train = approaching0; break; case approaching0 : if (s1)the_train = arriving0; break; case arriving0 : if (!s1)the_train = station0; break; case station0 : if (s2) the_train = departing0; break; case departing0 : if (!s2) the_train = leaving0; break; case leaving0 : if (s3)the_train = going0; break; case going0 : if (!s3) the_train = waiting; break; case coming1 : if (!s3) the_train = approaching1; break; case approaching1 : if (s2)the_train = arriving1; break; case arriving1 : if (!s2)the_train = station1; break; case station1 : if (s1) the_train = departing1; break; case departing1 : if (!s1) the_train = leaving1; break; case leaving1 : if (s0)the_train = going1; break; case going1 : if (!s0) the_train = waiting; break; } return the_train;}
where_is_train dump(where_is_train loc){ //static where_is_train save_loc=going; static where_is_train save_loc=station0; static long wdt; if (millis( )>(wdt + WDT_TIME)) { loc = waiting; //reset - need to return state wdt = millis( ); } if (loc != save_loc){ save_loc = loc; wdt = millis( ); switch (loc) { case waiting : Serial.println("No trains"); break; case coming0 : Serial.println("Coming from North"); break; case approaching0 : Serial.println("Approaching from North"); break; case arriving0 : Serial.println("Arriving from North"); break; case station0 : Serial.println("Train from North in station"); break; case departing0 : Serial.println("Departing to South"); break; case leaving0 : Serial.println("Leaving to South"); break; case going0 : Serial.println("Going to South"); break; case coming1 : Serial.println("Coming from South"); break; case approaching1 : Serial.println("Approaching from South"); break; case arriving1 : Serial.println("Arriving from South"); break; case station1 : Serial.println("Train from South in station"); break; case departing1 : Serial.println("Departing to North"); break; case leaving1 : Serial.println("Leaving to North"); break; case going1 : Serial.println("Going to North"); break; } } return loc; //needed return when reset state with wdt}#elsewhere_is_train train(int s0, int s1, int s2, int s3){ switch (the_train) { case waiting : if (s0) the_train = coming; break; case coming : if (!s0) the_train = approaching; break; case approaching : if (s1)the_train = arriving; break; case arriving : if (!s1)the_train = station; break; case station : if (s2) the_train = departing; break; case departing : if (!s2) the_train = leaving; break; case leaving : if (s3)the_train = going; break; case going : if (!s3) the_train = waiting; break; } return the_train;}
//display train status on serial//only display if a change in state//resest watchdog on each chage in state
where_is_train dump(where_is_train loc){ static where_is_train save_loc=going; static long wdt; if (millis( )>(wdt + WDT_TIME)) { loc = waiting; //reset - need to return state wdt = millis( ); } if (loc != save_loc){ save_loc = loc; wdt = millis( ); switch (loc) { case waiting : Serial.println("No trains"); break; case coming : Serial.println("Coming"); break; case approaching : Serial.println("Approaching"); break; case arriving : Serial.println("Arriving"); break; case station : Serial.println("In station"); break; case departing : Serial.println("Departing"); break; case leaving : Serial.println("Leaving"); break; case going : Serial.println("Going"); break; } } return loc; //needed return when reset state with wdt}#endif
void loop() { int s0 = sensor.train_over_sensor(4); //shorthand for sensors int s1 = sensor.train_over_sensor(1); int s2 = sensor.train_over_sensor(2); int s3 = sensor.train_over_sensor(3); signal.signal_control(3,s0); //control signals signal.signal_control(2,s1); //RED then AMBER - GREEN signal.signal_control(0,s2); signal.signal_control(1,s3); the_train = train(s0,s1,s2,s3); //test for next state //Serial.write((the_train+'0')); //numeric value for state the_train = dump(the_train); //text message for state //delay (500);}