//
// Wascoe Siding - Blaxland Junction Points & signals interlocking
// R. Parnell 8/10/2023
// V2. Re-written from 19/2/25
// ************************************
// *** ***** * **** *****
// * * * * * * *
// *** * ***** **** *
// * * * * * * *
// *** * * * * * *
//
// ***************************************
// inputs - active "low"
// outputs - acitve "high"
// define outputs
// 26/2/25 - lever input logic level. Proximity sensor output is normally HIGH and active "open circuit".
// Therefore, code amended to allow for active "HIGH" sensor inputs
int M1red = 0; // M1 red
int M1yel = 1; // yellow
int M1grn = 2; // green
int M2red = 3;
int M2yel = 4;
int M2grn = 5;
int M2TO = 6;
int M2y1 = 7;
int M2y2 = 8;
int ST11red = 9;
int ST11yel = 10;
int ST11grn = 11;
int ST11TO = 12;
int ST13red = 13;
int ST13yelM = 14;
int ST13yelS = 15;
int ST12red = 16;
int ST12yel = 17;
int ST12grn = 18;
int ST12y1 = 19;
int ST12y2 = 20;
int pts5N = 21; // normal, reverse, track circuit mimic
int pts5R = 22;
int pts5TC = 23;
int pts6N = 24;
int pts6R = 25;
int pts6TC = 26;
int pts7N = 27;
int pts7R = 28;
int pts7TC = 29;
int pts9N = 30;
int pts9R = 31;
int pts9TC = 32; // not used at this point in time (reserved for possible use later)
int pts10N = 33;
int pts10R = 34;
int pts10TC = 35; // not used at this point in time
int pts11N = 36;
int pts11R = 37;
int pts11TC = 38; // not used at this point in time
int pts12N = 39;
int pts12R = 40;
int pts12TC = 41; // not used at this point in time
int PLRW = 42; // points lever reverse warning
// define inputs:
int emerg = 43; // emergency stop input
int M1proceed = 44;
int M2proceed = 45;
int ST12proceed = 46;
int ST1113proceed = 47;
int C2stop = 48; // is next signal C2 at stop?
int C4stop = 49;
int ST15stop = 50;
int M3stop = 51;
int pts5Ndet = A0; // detection of Normal
int pts5Rdet = A1; // detection of Reverse
int pts5block = A2; // track circuit input
int pts6Ndet = A3; // detection of Normal
int pts6Rdet = A4; // detection of Reverse
int pts6block = A5; // track circuit input
int pts7Ndet = A6; // detection of Normal
int pts7Rdet = A7; // detection of Reverse
int pts7block = A8; // track circuit input
// not enough inputs for future block detection of 9, 10, 11 and 12 points
int pts9normal = A12; // 9-12 temporary for the purpose of displaying mimic and lever reverse warning
int pts10normal = A13;
int pts11normal = A14;
int pts12normal = A15;
unsigned long startMillis; // for starting countdown of timer
unsigned long warningONmillis = 600; // on/off 50% duty cycle time period for points lever reversed flash
unsigned long currentMillis; // what will be the current value to compare countdown to
boolean pulseHigh = false; // base rate continuously cycling in the background
bool alertON = false; // if alert lamp is on or not
bool warning5 = false; // flag for setting points lever warning alert
bool warning6 = false;
bool warning7 = false;
bool warning8 = false;
bool warning9 = false;
bool warning10 = false;
bool warning11 = false;
bool warning12 = false;
bool block5occ = false;
bool block6occ = false;
bool block7occ = false;
bool block9occ = false; // block 9 to 12 included to "future proof" programming
bool block10occ = false;
bool block11occ = false;
bool block12occ = false;
bool emergstop = false;
bool M1stopVal = false;
bool M2stopVal = false;
bool ST1113stopVal = false;
bool ST12stopVal = false;
bool C4nextstop = false;
bool C2nextstop = false;
bool ST15next = false;
bool M3next = false;
bool pts5Normal = false;
bool pts5Reverse = false;
bool pts6Normal = false;
bool pts6Reverse = false;
bool pts6N7N = true; // possible routes for 6 points, given other circumstances. Station road straight through
bool pts6N7R = false; // main to/from yard
bool pts6R7N = false; // station to/from yard
bool pts6R7R = false; // station to/from main
bool pts7Normal = false;
bool pts7Reverse = false;
bool pts9Normal = true;
bool pts10Normal = true;
bool pts11Normal = true;
bool pts12Normal = true;
int route = 100; // 1 of 6 possible combinations of routes with the possible points settings
int signalswitchset = 10000; // 4 possible combinations of proceed/stop for signal switch settings
int oldroute = 0;
int oldsignalswitchset = 0;
int ignoring5route = 0;
bool skippedsignals = false;
int yard = 0;
//#########################
void setup() {
Serial.begin(9600); // open the serial port for debugging
startMillis = millis(); //start timer value for alert
pinMode(emerg, INPUT);
pinMode(M1proceed, INPUT);
pinMode(M2proceed, INPUT);
pinMode(ST12proceed, INPUT);
pinMode(ST1113proceed, INPUT);
pinMode(C2stop, INPUT);
pinMode(C4stop, INPUT);
pinMode(ST15stop, INPUT);
pinMode(M3stop, INPUT);
pinMode(pts5Ndet, INPUT);
pinMode(pts5Rdet, INPUT);
pinMode(pts5block, INPUT);
pinMode(pts6Ndet, INPUT);
pinMode(pts6Rdet, INPUT);
pinMode(pts6block, INPUT);
pinMode(pts7Ndet, INPUT);
pinMode(pts7Rdet, INPUT);
pinMode(pts7block, INPUT);
pinMode(pts9normal, INPUT);
pinMode(pts10normal, INPUT);
pinMode(pts11normal, INPUT);
pinMode(pts12normal, INPUT);
pinMode(M1red, OUTPUT);
pinMode(M1yel, OUTPUT);
pinMode(M1grn, OUTPUT);
pinMode(M2red, OUTPUT);
pinMode(M2yel, OUTPUT);
pinMode(M2grn, OUTPUT);
pinMode(M2TO, OUTPUT);
pinMode(M2y1, OUTPUT);
pinMode(M2y2, OUTPUT);
pinMode(ST11red, OUTPUT);
pinMode(ST11yel, OUTPUT);
pinMode(ST11grn, OUTPUT);
pinMode(ST11TO, OUTPUT);
pinMode(ST13red, OUTPUT);
pinMode(ST13yelM, OUTPUT);
pinMode(ST13yelS, OUTPUT);
pinMode(ST12red, OUTPUT);
pinMode(ST12yel, OUTPUT);
pinMode(ST12grn, OUTPUT);
pinMode(ST12y1, OUTPUT);
pinMode(ST12y2, OUTPUT);
//16/10/23
pinMode(pts5N, OUTPUT); // normal, reverse, track circuit mimic
pinMode(pts5R, OUTPUT);
pinMode(pts5TC, OUTPUT);
pinMode(pts6N, OUTPUT);
pinMode(pts6R, OUTPUT);
pinMode(pts6TC, OUTPUT);
pinMode(pts7N, OUTPUT);
pinMode(pts7R, OUTPUT);
pinMode(pts7TC, OUTPUT);
pinMode(pts9N, OUTPUT);
pinMode(pts9R, OUTPUT);
pinMode(pts9TC, OUTPUT); // not used at this point in time (reserved for possible use later)
pinMode(pts10N, OUTPUT);
pinMode(pts10R, OUTPUT);
pinMode(pts10TC, OUTPUT); // not used at this point in time
pinMode(pts11N, OUTPUT);
pinMode(pts11R, OUTPUT);
pinMode(pts11TC, OUTPUT); // not used at this point in time
pinMode(pts12N, OUTPUT);
pinMode(pts12R, OUTPUT);
pinMode(pts12TC, OUTPUT); // not used at this point in time
pinMode(PLRW, OUTPUT); // points lever reverse warning
digitalWrite(M1red, LOW);
digitalWrite(M1yel, LOW);
digitalWrite(M1grn, LOW);
digitalWrite(M2red, LOW);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, LOW);
digitalWrite(ST11red, LOW);
digitalWrite(ST11yel, LOW);
digitalWrite(ST11grn, LOW);
digitalWrite(ST11TO, LOW);
digitalWrite(ST13red, LOW);
digitalWrite(ST13yelM, LOW);
digitalWrite(ST13yelS, LOW);
digitalWrite(ST12red, LOW);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, LOW);
//16/10/23
digitalWrite(pts5N, LOW); // normal, reverse, track circuit mimic
digitalWrite(pts5R, LOW);
digitalWrite(pts5TC, LOW);
digitalWrite(pts6N, LOW);
digitalWrite(pts6R, LOW);
digitalWrite(pts6TC, LOW);
digitalWrite(pts7N, LOW);
digitalWrite(pts7R, LOW);
digitalWrite(pts7TC, LOW);
digitalWrite(pts9N, LOW);
digitalWrite(pts9R, LOW);
digitalWrite(pts9TC, LOW); // not used at this point in time (reserved for possible use later)
digitalWrite(pts10N, LOW);
digitalWrite(pts10R, LOW);
digitalWrite(pts10TC, LOW); // not used at this point in time
digitalWrite(pts11N, LOW);
digitalWrite(pts11R, LOW);
digitalWrite(pts11TC, LOW); // not used at this point in time
digitalWrite(pts12N, LOW);
digitalWrite(pts12R, LOW);
digitalWrite(pts12TC, LOW); // not used at this point in time
digitalWrite(PLRW, LOW); // points lever reverse warning
// set all signals to stop, since we don't know much else!
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
delay (2000);
// ###################################
/// ### end of initialisation ###
/// ### end of initialisation ###
/// ### end of initialisation ###
// ###################################
}
//#########################
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
void loop() {
currentMillis=millis();
if (currentMillis - startMillis >= warningONmillis) //test whether the period has elapsed
{
pulseHigh = !pulseHigh; //if so, change the state. Uses a neat trick to change the state
startMillis = currentMillis; //IMPORTANT to save the start time of the current state.
} //pulseHigh will change state from true to false every 600mS or so
// inset code to see if points have changed whilst a proceed signal was already given. 22/2/25
if (route >= 100) {
route = route - 100;
// ignoring5route = route - 100; // remarked out and changed to line above 28/2/5
} //else ignoring5route = route; // 28/2/25
oldroute = route; // 22/2/25 put the old route value into "oldroute" to see if it has changed
oldsignalswitchset = signalswitchset; //22/2/25 old value to see if it has changed
route = 0; // reset route options to zero
signalswitchset = 0; // reset signal proceed values to zero
readinputs();
Serial.println("oldroute, route value ="); // debugging
Serial.println(oldroute); // debugging
Serial.println(route); // debugging
Serial.println("oldsignalswitch, signalswitchset value ="); // debugging
Serial.println(oldsignalswitchset); // debugging
Serial.println(signalswitchset); // debugging
delay(10); // added for assisting with any switch debounce after reading inputs.
// display points settings and set red signals if against the points
// points 5,6,7 have been programmed for possible future inclusing of points detection in both N and R
// since no point blade detection at the time of writing, points 5, 6, 7 are assumed to be set to "reverse"
// if the lever is not set to "normal"
// Feb 2025 update: include code to detect points levers in reverse position, since hardware is about to be installed
if (pts5Normal == true) {
//16/10/23
digitalWrite(pts5N, HIGH);
warning5 = false;
} else { // points are either in-transit or reversed
//16/10/23
digitalWrite(pts5N, LOW);
warning5 = true;
}
if (pts5Reverse == true) {
digitalWrite(pts5R, HIGH);
warning5 = true;
// route = route + 100; // route will be 5 or 6 into yard 2. Moved to where inputs are checked.
} else {
digitalWrite(pts5R, LOW);
warning5 = false;
}
if (pts7Normal == true && pts6Normal == true) {
digitalWrite(pts7N, HIGH);
digitalWrite(pts7R, LOW);
digitalWrite(pts6N, HIGH);
digitalWrite(pts6N, LOW);
warning7 = false;
warning6 = false;
Serial.println("7N6N"); // debugging
}
if (pts7Reverse == true && pts6Reverse == true) { //7 points reversed. M1 must be STOP
digitalWrite(pts7R, HIGH);
digitalWrite(pts7N, LOW);
digitalWrite(pts6R, HIGH);
digitalWrite(pts6N, LOW);
warning7 = true;
warning6 = true;
M1stop();
// route = route + 11; // moved to section when inputs are read
Serial.println("7R6R"); // debugging
}
if (pts7Normal == true && pts6Reverse == true) {
digitalWrite(pts7N, HIGH);
digitalWrite(pts7R, LOW);
digitalWrite(pts6R, HIGH);
digitalWrite(pts6N, LOW);
warning6 = true;
warning7 = false;
Serial.println("7N6R"); // debugging
}
if (pts7Reverse == true && pts6Normal == true) { //7 points reversed. M1 must be STOP
digitalWrite(pts7R, HIGH);
digitalWrite(pts7N, LOW);
digitalWrite(pts6N, HIGH);
digitalWrite(pts6R, LOW);
warning7 = true;
warning6 = false;
M1stop();
Serial.println("7R6N"); // debugging
}
if (pts9Normal == true) {
digitalWrite(pts9N, HIGH);
warning9 = false;
Serial.println("9N"); // debugging
} else {
digitalWrite(pts9N, LOW);
warning9 = true;
}
if (pts10Normal == true) {
digitalWrite(pts10N, HIGH);
warning10 = false;
} else {
digitalWrite(pts10N, LOW);
warning10 = true;
}
if (pts11Normal == true) {
digitalWrite(pts11N, HIGH);
warning11 = false;
} else {
digitalWrite(pts11N, LOW);
warning11 = true;
}
if (pts12Normal == true) {
digitalWrite(pts12N, HIGH);
warning12 = false;
} else {
digitalWrite(pts12N, LOW);
warning12 = true;
}
currentMillis = millis();
//
// START: points lever alert warning light (warning working 28/2/25)
//
if (warning5 == true || warning6 == true || warning7 == true || warning9 == true || warning10 == true || warning11 == true || warning12 == true) {
//turn warning on
alertON = true;
}
if (warning5 == false && warning6 == false && warning7 == false && warning9 == false && warning10 == false && warning11 == false && warning12 == false) {
//turn warning off
alertON = false;
digitalWrite(PLRW, LOW);
}
if (alertON == true && pulseHigh == true) {
digitalWrite(PLRW, HIGH); // points lever reverse warning ON
}
if (alertON = true && pulseHigh == false) {
digitalWrite(PLRW, LOW); // turn off for the pulse
}
//
// end points lever alert warning light
//
// display track circuit occupancy status of each block
// check block occupancy here. Display respective mimics and set appropriate signals to stop
//Should blocks be occupied, then skip the setting signals bit.
// affected signals for block occupancy:
// block 5 - ST13 - stop
// ST12 and M2 only if routes set
// block 6 - ST11 & ST12 stop
// M2 and ST13 if routes set
// block 7 - M2 and M1 stop
// ST11 and ST13 if routes set
if (block5occ == true) {
digitalWrite(pts5TC, HIGH);
} else {
digitalWrite(pts5TC, LOW);
}
if (block6occ == true) {
digitalWrite(pts6TC, HIGH);
} else {
digitalWrite(pts6TC, LOW);
}
if (block7occ == true) {
digitalWrite(pts7TC, HIGH);
} else {
digitalWrite(pts7TC, LOW);
}
//
// not enough inputs for blocks 9 to 12 to be programmed. Requires separate controller. Not wired or configured
// for detection or signals at time of writing. 13/10/23.
// at this point - all points settings and occupancies are shown.
// now check for emergnecy stop. If no emerg, check what routes are set and then signals settings etc
if (emergstop == true) {
emergencystop(); //
}
// 21/2/25: if emergency stop is on, keep displaying occupancy of blocks and points lever mimics, but don't clear any signals.
//for each given route setting option, place known affected conflicting signals to stop
// then see if block affecting that route is occupied or not.
// then check if signal switch is set to proceed.
// then check if next signal is at stop or not,
// show respective aspect
// Insert the signal setting into it's own void - only accessible if a lever has not been changed without first having all signals set to stop.
yard = route;
if (yard > 99){
yard = yard - 100;
}
if ((signalswitchset > 0) && (oldroute != yard)){
Serial.println("emerg stop for signals and levers"); // debugging
//if any levers other than 5 have changed, but signals were not at stop - place all signals to stop!
emergencystop(); //<-add code. The only way out of this situation is to place all signals back to stop, then go again.
skippedsignals = true; //<- added 23/2/25 as a means of testing if all signals have been set back to stop
Serial.println("You have skipped signals back to stop!!!!!!!!!!!!!!!!!"); // debugging
} //else skippedsignals = false;
// 19/2/25 - insert void for "process inputs"
Serial.println("skippedsignals status"); // debugging
Serial.println(skippedsignals); // debugging
if (skippedsignals == false && emergstop == false){
setsignalstoproceed(); // the only way to set any signals is if all signals were placed to stop before changing any lever (except #5)
// if any lever is changed and the signals were not as stop, setsignalstoproceed will be true and cannot access the void to set the proceed indications
}
if (skippedsignals == true){
resetsignals();
}
} // <- this is the end of the main loop void
// ##########################################################################################
void resetsignals(){
// this is accessed only if skippedsignals is true. Signals must all be placed back to stop to free up ability to set any further proceed aspects
Serial.println("Resetting signals void"); // debugging
if (M1stopVal == true && M2stopVal == true && ST1113stopVal == true && ST12stopVal == true){
skippedsignals = false;
}
}
void setsignalstoproceed(){
Serial.println("Signals can be set to proceed hereproceed hereproceed hereproceed hereproceed hereproceed hereproceed here"); // debugging
if (M1stopVal == true){
M1stop();
}
if (M2stopVal == true){
M2stop();
}
if (ST1113stopVal == true){
ST11stop();
ST13stop();
}
if (ST12stopVal == true){
ST12stop();
}
if (route == 0 || route == 100) {
route5x6N7N();
}
// 2222222222222222222222222222222222222222222222222222222222
if (route == 11 || route == 111){
route5x6R7R();
}
// route 2 - points 5NorR, 6R, 7R
//333333333333333333333333333333333333333333333333333333333333333333333333333
// route 3 - points 5N, 6R, 7N
if (route == 010){
route5N6R7N();
}
//444444444444444444444444444444444444444444444444444444444444444444
// route 4 - points 5N, 6N, 7R
if (route == 1){
route5N6N7R();
}
//55555555555555555555555555555555555555555555555555555555555555
// route 5 - points 5R, 6N,7R
if (route == 101){
route5R6N7R();
}
//666666666666666666666666666666666666666666666666666666
// route 6 - points 5R, 6R, 7N
if (route==110) {
route5R6R7N();
}
} // <- end of checking signals for proceed indications
void route5R6R7N(){
// ST11 stop
// M1, M2, ST12, ST13 available to set to proceed
ST11stop(); //it's a given that this one will be at stop
if (block6occ == true || block5occ == true) {
ST13stop();
ST12stop();
}
if (block6occ == false && block5occ == false) {
//see if the respective signal switch is set to proceed, since block is clear
if (ST1113stopVal == false) {
ST12stop(); //opposing signal
ST13station();//ST13 is set to proceed
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST13stop();
//ST12 is set to proceed
ST12yard2();
}
if (ST12stopVal == true) {
ST12stop();
}
if (ST1113stopVal == true) {
ST13stop();
}
} //<- this is the end of block 6 occupancy and signal setting check
points7NormalSignals(); //use this void as it is common for route 1, 3 and 6
} //<- this is the end of "route 6" subroutine\
// ###########################################################################################
void readinputs() {
// read all input values
if (digitalRead(emerg) == LOW ) {
emergstop = true;
} else emergstop = false;
if (digitalRead(pts5block) == LOW ) {
block5occ = true;
} else block5occ = false;
if (digitalRead(pts6block) == LOW ) {
block6occ = true;
} else block6occ = false;
if (digitalRead(pts7block) == LOW ) {
block7occ = true;
} else block7occ = false;
if (digitalRead(M1proceed) == LOW) {
M1stopVal = false;
signalswitchset = 1000; // set the switch as showing proceed for main line
} else M1stopVal = true;
if (digitalRead(M2proceed) == LOW) {
M2stopVal = false;
signalswitchset = 1000; // set the switch as showing proceed for main line
} else M2stopVal = true;
if (digitalRead(ST1113proceed) == LOW) {
ST1113stopVal = false;
signalswitchset = signalswitchset + 10000; // set the switch as showing proceed for station road
} else ST1113stopVal = true;
if (digitalRead(ST12proceed) == LOW) {
ST12stopVal = false; // the switch is set to proceed - therefore, not at stop
signalswitchset = signalswitchset + 10000; // set the switch as showing proceed for station road
} else ST12stopVal = true;
if (digitalRead(C2stop) == LOW) {
C2nextstop = true; // next signal is at stop, so this value is true
} else C2nextstop = false;
if (digitalRead(C4stop) == LOW) {
C4nextstop = true; // next signal is at stop, so this value is true
} else C4nextstop = false;
if (digitalRead(ST15stop) == LOW) {
ST15next = true; // next signal is at stop, so this value is true
} else ST15next = false;
if (digitalRead(M3stop) == LOW) {
M3next = true; // next signal is at stop, so this value is true
} else M3next = false;
if (digitalRead(pts5Ndet) == HIGH) {
//if (digitalRead(pts5Ndet) == LOW) { //swapped LOW for HIGH on lever inputs 26/2/25
pts5Normal = true; // Points are normal, if not, then it is false
} else pts5Normal = false;
//if (digitalRead(pts5Rdet) == LOW) {
if (digitalRead(pts5Rdet) == HIGH) {
pts5Reverse = true; // Points are reversed, if not, then it is false
route = route + 100; // route will be 5 or 6 into yard 2.
} else pts5Reverse = false;
//if (digitalRead(pts6Ndet) == LOW) {
if (digitalRead(pts6Ndet) == HIGH) {
pts6Normal = true; // Points are normal, if not, then it is false
} else pts6Normal = false;
//if (digitalRead(pts6Rdet) == LOW) {
if (digitalRead(pts6Rdet) == HIGH) {
pts6Reverse = true; // Points are reversed, if not, then it is false
route = route + 10;
} else pts6Reverse = false;
//if (digitalRead(pts7Ndet) == LOW) {
if (digitalRead(pts7Ndet) == HIGH) {
pts7Normal = true; // Points are normal, if not, then it is false
} else pts7Normal = false;
//if (digitalRead(pts7Rdet) == LOW) {
if (digitalRead(pts7Rdet) == HIGH) {
pts7Reverse = true; // Points are reversed, if not, then it is false
route = route + 1;
} else pts7Reverse = false;
//if (digitalRead(pts9normal) == LOW) {
if (digitalRead(pts9normal) == HIGH) { // points 9-12 are only checked if normal, since there are no signals for these at this time of creating the code
pts9Normal = true; // next signal is at stop, so this value is true
} else pts9Normal = false;
//if (digitalRead(pts10normal) == LOW) {
if (digitalRead(pts10normal) == HIGH) {
pts10Normal = true; // next signal is at stop, so this value is true
} else pts10Normal = false;
//if (digitalRead(pts11normal) == LOW) {
if (digitalRead(pts11normal) == HIGH) {
pts11Normal = true; // next signal is at stop, so this value is true
} else pts11Normal = false;
//if (digitalRead(pts12normal) == LOW) {
if (digitalRead(pts12normal) == HIGH) {
pts12Normal = true; // next signal is at stop, so this value is true
} else pts12Normal = false;
} // <- end of reading inputs void
// ##########################################################################################
//##### signal indications:
void M1stop() {
digitalWrite(M1red, HIGH);
digitalWrite(M1yel, LOW);
digitalWrite(M1grn, LOW);
}
void M1caution() {
digitalWrite(M1red, LOW);
digitalWrite(M1yel, HIGH);
digitalWrite(M1grn, LOW);
}
void M1clear() {
digitalWrite(M1red, LOW);
digitalWrite(M1yel, LOW);
digitalWrite(M1grn, HIGH);
}
void M2stop() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, LOW);
}
void M2caution() {
digitalWrite(M2red, LOW);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, LOW);
}
void M2clear() {
digitalWrite(M2red, LOW);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, LOW);
}
void M2turnout() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, LOW);
}
void M2yard1() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, LOW);
}
void M2yard2() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, HIGH);
}
void ST11stop() {
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, LOW);
digitalWrite(ST11grn, LOW);
digitalWrite(ST11TO, LOW);
}
void ST11caution() {
digitalWrite(ST11red, LOW);
digitalWrite(ST11yel, HIGH);
digitalWrite(ST11grn, LOW);
digitalWrite(ST11TO, LOW);
}
void ST11clear() {
digitalWrite(ST11red, LOW);
digitalWrite(ST11yel, LOW);
digitalWrite(ST11grn, HIGH);
digitalWrite(ST11TO, LOW);
}
void ST11turnout() {
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, LOW);
digitalWrite(ST11grn, LOW);
digitalWrite(ST11TO, HIGH);
}
void ST12stop() { // semaphore signal
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, LOW);
}
void ST12caution() { // semaphore signal
digitalWrite(ST12red, LOW);
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, LOW);
}
void ST12clear() { // semaphore signal
digitalWrite(ST12red, LOW);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, LOW);
}
void ST12yard1() { // semaphore signal
digitalWrite(ST12red, LOW);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, LOW);
}
void ST12yard2() { // semaphore signal
digitalWrite(ST12red, LOW);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, HIGH);
}
void ST13stop() {
digitalWrite(ST13red, HIGH);
digitalWrite(ST13yelM, LOW);
digitalWrite(ST13yelS, LOW);
}
void ST13main() {
digitalWrite(ST13red, LOW);
digitalWrite(ST13yelM, HIGH);
digitalWrite(ST13yelS, LOW);
}
void ST13station() {
digitalWrite(ST13red, LOW);
digitalWrite(ST13yelM, LOW);
digitalWrite(ST13yelS, HIGH);
}
void points7NormalSignals() {
// common for route 1 and 3
if (block7occ == true) {
M1stop();
M2stop();
} else {
// block 7 is not occupied, check signal switch setting
if (M1stopVal == false) {
//M1 is set to proceed. Set M2 to stop and see if M1 caution or clear
M2stop();
if (C2nextstop == true) {
// Set M1 to caution
M1caution();
} else {
// set M1 to clear
M1clear();
}
}
if (M2stopVal == false) {
// now check opposite direction etc
M1stop();
if (M3next == true) { // if M3 is at stop, then display caution. If not, display clear.
M2caution();
} else {
M2clear();
}
}
} //<- this is the end of setting the main line signal after checking block7 occupancy
}
void emergencystop () {
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
}
void route5x6N7N () {
//route 1 set
ST13stop(); //it's a given that this one will be at stop
if (block6occ == true) {
ST12stop();
ST11stop();
} else {
//see if the respective signal switch is set to proceed, since block is clear
if (ST1113stopVal == false) {
ST12stop();
//ST11 is set to proceed, now checking next block
if (ST15next == true) { // true if at stop, false if at proceed
//display caution if true, otherwise display clear
//set ST11 to caution and ST12 to stop
ST11caution();
} else {
// set ST11 to clear here and ST12 to stop
ST11clear();
}
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST11stop();
//ST12 is set to proceed, now check next block
if (C4nextstop == true) {
// display caution if true, otherwise display clear
ST12caution();
} else {
// set ST12 to clear here and ST11 to stop
ST12clear();
}
}
} //<- this is the end of block 6 occupancy and signal setting check
points7NormalSignals();
} //<- this is the end of "route 1" subroutine
void route5x6R7R () {
ST13stop(); //it's a given that this one will be at stop
M1stop();
ST12stop();
if (block6occ == true || block7occ == true) {
M2stop();
ST11stop();
} else {
//see if the respective signal switch is set to proceed, since block is clear
if (ST1113stopVal == false && M2stopVal == true) {
M2stop();
ST11turnout();
} else {
ST11stop();
M2stop();
}
//now check M2 stop value and set signal accordingly
if (M2stopVal == false && ST1113stopVal == true) {
ST11stop();
M2turnout();
//ST12 is set to proceed
Serial.println("turning out from main to station"); //debuggin
}
if (M2stopVal == true && ST1113stopVal == true) {
M2stop();
ST11stop();
}
} //<- this is the end of route 2 occupancy and signal setting check
} //<- this is the end of "route 2" subroutine
void route5N6R7N() {
//route 1 set
ST11stop(); //it's a given that this one will be at stop
if (block6occ == true || block5occ == true) {
ST13stop();
ST12stop();
} else {
//see if the respective signal switch is set to proceed, since block is clear
if (ST1113stopVal == false) {
ST12stop(); //opposing signal
ST13station();//ST13 is set to proceed
} else {
ST13stop();
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST13stop();
//ST12 is set to proceed
ST12yard1();
} else {
ST12stop();
}
} //<- this is the end of block 6 occupancy and signal setting check
points7NormalSignals(); //use this void as it is common for route 1 and route 3
} //<- this is the end of "route 3" subroutine
void route5N6N7R() {
//route 4 set
// points 5N, 6N, 7R
// STOP = M1, ST11, ST12
// M2 and ST13 available for proceed indications
M1stop(); //it's a given that this one will be at stop
ST11stop(); //it's a given that this one will be at stop
ST12stop(); //it's a given that this one will be at stop
if (block6occ == true || block5occ == true || block7occ == true) {
M2stop();
ST13stop();
} else {
//see if the respective signal switch is set to proceed, since block is clear
//anticlockwise:
if (ST1113stopVal == false && M2stopVal == true) {
M2stop(); //opposing signal
ST13main();
}
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true) {
ST13stop();
//ST12 is set to proceed
M2yard1();
}
if (M2stopVal == true && ST1113stopVal == true) {
M2stop();
ST13stop();
}
} //<- this is the end of block 6 occupancy and signal setting check
} //<- this is the end of "route 4" subroutine
void route5R6N7R() {
// STOP = M1, ST11, ST12
// M2 and ST13 available for proceed indications
M1stop(); //it's a given that this one will be at stop
ST11stop(); //it's a given that this one will be at stop
ST12stop(); //it's a given that this one will be at stop
if (block6occ == true || block5occ == true || block7occ == true) {
M2stop();
ST13stop();
} else {
//see if the respective signal switch is set to proceed, since block is clear
//anticlockwise:
if (ST1113stopVal == false && M2stopVal == true) {
M2stop(); //opposing signal
ST13main();
} else {
ST13stop();
M2stop();
Serial.println("ST13stopped");//debugging
}
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true) {
ST13stop();
//ST12 is set to proceed
M2yard2();
} else {
M2stop();
ST13stop();
}
} //<- this is the end of block 6 occupancy and signal setting check
} //<- this is the end of "route 5" subroutine