//
// Wascoe Siding - Blaxland Junction Points & signals interlocking
// R. Parnell 8/10/2023
// Thanks to Bailey Cave during testing and debugging process!
// 15/9/25: this is the final version, simulated on-line with no issues.
// V2. Re-written from 19/2/25
// new idea 18/3/25
// add points in transit alert 31/3/25. Done.
// 1/4/25 - incomplete. not reading analog voltage divider correctly, but code is working around detecting thresholds for NR. Done.
// 2/4/25 points 5 NR and in-transit alarm working fine. To repeat for the other levers. To be checked 2/4/25. Done.
// 4/4/25 changes to thinking in oldroute status - redundant.
// 7/4/26: reconfigured outputs to suit 5,6,7 points and occupancies - 11 outputs required
// 16/4/25. Declared complete and tested on simulator as much as possible. Hopefully, that's it!
// 27/4/25: modify lever inputs as the proximity sensors have a delay in changing state. This results in both N and R inputs being active "low" together for a short moment. The logic expects instantaneous change of state from low to high. Add in code such that if both N & R are high or low, then the points lever is considered to be in-transit.
// 18/5/25: need to change the relay outputs to "active relayOFF" to suit the relay modules. Also check voltage divider values correlate with real world. Make it a variable, selected in the initialisation? Done.
// R6: relay output mod for easy changes to relay bank "active HIGH" or "active LOW". Done 19/5/25
// 24/05/25 Tested to find out Values of 9-12, Normal = 683, Window of 20, Reverse = 523, Window of 20
// 24/05/25 - Converted 5,6 & 7 to a analog Read instead of digital
// 25/5/25 R7 - found a minor bug to fix with 7 points being thrown with ST12 cleared. Does not put ST12 back to stop. Fixed.
// Tied to ground via 1k ohm, since these pins are unused: A9, A10, A11
// ************************************
//
// *** ***** * **** *****
// * * * * * * *
// *** * ***** **** *
// * * * * * * *
// *** * * * * * *
//
// ***************************************
// inputs - active "low" (except for points levers - analog for 9, 10, 11, 12)
// outputs - acitve "high"
// define outputs
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 pts6Nstrt = 24; // inner track - straight through
int pts6Ndiag = 25; // yard to/from main
int pts6TC = 28; // Track circuit
int pts6Rsm = 26; // reversed - station to/from main
int pts6Rsy = 27; // reversed - station to/from yard
//int pts7N = 27;
//int pts7R = 28;
int pts7TC = 29;
int pts7N = 52;
int pts7R = 53;
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
int proximityNvalue = 683; // 2.5V voltage divider
int proximityRvalue = 523; // 3.3V voltage divider
int proxwindow = 20; // analogue proxmity value "window" to set high and low range values
// 41 is equal to +-0.2v range for proximity analog value
// 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 ANALOG
int pts5Rdet = A1; // detection of Reverse ANALOG
int pts5block = A2; // track circuit input
int pts6Ndet = A3; // detection of Normal ANALOG
int pts6Rdet = A4; // detection of Reverse ANALOG
int pts6block = A5; // track circuit input
int pts7Ndet = A6; // detection of Normal ANALOG
int pts7Rdet = A7; // detection of Reverse ANALOG
int pts7block = A8; // track circuit input
// not enough inputs for future block detection of 9, 10, 11 and 12 points
// analogue inputs used for N/R detection of 9-12 points, due to shortage of inputs
int pts9NRdetect = A12; // now analogue 1/4/25
//int pts9normal = A12; // 9-12 temporary for the purpose of displaying mimic and lever reverse warning
int pts10NRdetect = A13;
int pts11NRdetect = A14;
int pts12NRdetect = A15;
//int pts10normal = A13;
//int pts11normal = A14;
//int pts12normal = A15;
// ############### define variables here: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int pts9NRvalue = 0;
int pts10NRvalue = 0;
int pts11NRvalue = 0;
int pts12NRvalue = 0;
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 pointslevertimer = 4000; // time allowed to swing a points lever from one position to the other
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
unsigned long lever5timer; // for starting timer for operating lever from one position to the other
unsigned long lever6timer;
unsigned long lever7timer;
unsigned long lever9timer;
unsigned long lever10timer;
unsigned long lever11timer;
unsigned long lever12timer;
bool warning5 = false; // flag for setting points lever warning alert
bool warning6 = false;
bool warning7 = 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 shuntfromyard = false;
bool shuntfrommain = false;
bool shuntfromstation = false;
bool pts7Normal = false;
bool pts7Reverse = false;
bool pts9Normal = true;
bool pts10Normal = true;
bool pts11Normal = true;
bool pts12Normal = true;
bool pts9Reverse = false;
bool pts10Reverse = false;
bool pts11Reverse = false;
bool pts12Reverse = false;
// remark out the ON/OFF pair below to suit relay modules as required
//*** for active LOW relay modules:
//bool relayON = LOW;
//bool relayOFF = HIGH;
//*** for active HIGH relay modules:
bool relayON = HIGH;
bool relayOFF = LOW; //
bool points5intransit = false;
bool points7intransit = false;
bool points6intransit = false;
bool points9intransit = false;
bool points10intransit = false;
bool points11intransit = false;
bool points12intransit = false;
int route = 100; // 1 of 6 possible combinations of routes with the possible points settings
int STATIONsignalswitchset = 0; // 3 possible combinations of proceed ACW/stop/proceed CW (10, 0 or 1)
int MAINsignalswitchset = 0; // 3 possible combinations of proceed ACW/stop/proceed CW (10, 0 or 1)
bool skippedSTATIONsignals = false;
bool skippedMAINsignals = false;
bool routeA1set = false;
bool routeBset = false;
bool routeCset = false;
bool routeD1set = false;
bool routeEset = false;
bool routeFset = false;
bool routeA2set = false;
bool routeD2set = false;
bool routeMAINset = false;
bool routeAlockedMAIN = false;
bool routeAlockedSTATION = false;
bool routeBlockedMAIN = false;
bool routeBlockedSTATION = false;
bool routeClockedMAIN = false;
bool routeClockedSTATION = false;
bool routeDlockedMAIN = false;
bool routeDlockedSTATION = false;
bool routeElockedMAIN = false;
bool routeElockedSTATION = false;
bool routeFlockedMAIN = false;
bool routeFlockedSTATION = false;
bool routeAlocked = false;
bool routeBlocked = false;
bool routeDlocked = false;
bool routeClocked = false;
bool routeElocked = false;
bool routeFlocked = false;
bool route7Nset = false;
bool points7lockedN = false;
bool points5lockedN = false;
bool points6lockedN = false;
bool points7lockedR = false;
bool points5lockedR = false;
bool points6lockedR = false;
//#########################
void setup() {
//Serial.begin(9600); // open the serial port for debugging
startMillis = millis(); //start timer value for alert
pinMode(emerg, INPUT);
pinMode(M1proceed, INPUT_PULLUP);
pinMode(M2proceed, INPUT_PULLUP);
pinMode(ST12proceed, INPUT_PULLUP);
pinMode(ST1113proceed, INPUT_PULLUP);
pinMode(C2stop, INPUT_PULLUP);
pinMode(C4stop, INPUT_PULLUP);
pinMode(ST15stop, INPUT_PULLUP);
pinMode(M3stop, INPUT_PULLUP);
//pinMode(pts5Ndet, INPUT); // 5N, 5R, 6N, 6R, 7N, 7R now analogue
//pinMode(pts5Rdet, INPUT); // now analogue
pinMode(pts5block, INPUT_PULLUP);
//pinMode(pts6Ndet, INPUT);
//pinMode(pts6Rdet, INPUT);
pinMode(pts6block, INPUT_PULLUP);
//pinMode(pts7Ndet, INPUT);
//pinMode(pts7Rdet, INPUT);
pinMode(pts7block, INPUT_PULLUP);
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(pts6Nstrt, OUTPUT);
pinMode(pts6Rsm, OUTPUT);
pinMode(pts6Ndiag, OUTPUT);
pinMode(pts6Rsy, 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, relayOFF);
digitalWrite(M1yel, relayOFF);
digitalWrite(M1grn, relayOFF);
digitalWrite(M2red, relayOFF);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayOFF);
digitalWrite(ST11red, relayOFF);
digitalWrite(ST11yel, relayOFF);
digitalWrite(ST11grn, relayOFF);
digitalWrite(ST11TO, relayOFF);
digitalWrite(ST13red, relayOFF);
digitalWrite(ST13yelM, relayOFF);
digitalWrite(ST13yelS, relayOFF);
digitalWrite(ST12red, relayOFF);
digitalWrite(ST12yel, relayOFF);
digitalWrite(ST12grn, relayOFF);
digitalWrite(ST12y1, relayOFF);
digitalWrite(ST12y2, relayOFF);
//16/10/23
digitalWrite(pts5N, relayOFF); // normal, reverse, track circuit mimic
digitalWrite(pts5R, relayOFF);
digitalWrite(pts5TC, relayOFF);
digitalWrite(pts6Nstrt, relayOFF);
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Ndiag, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
digitalWrite(pts6TC, relayOFF);
digitalWrite(pts7N, relayOFF);
digitalWrite(pts7R, relayOFF);
digitalWrite(pts7TC, relayOFF);
digitalWrite(pts9N, relayOFF);
digitalWrite(pts9R, relayOFF);
digitalWrite(pts9TC, relayOFF); // not used at this point in time (reserved for possible use later)
digitalWrite(pts10N, relayOFF);
digitalWrite(pts10R, relayOFF);
digitalWrite(pts10TC, relayOFF); // not used at this point in time
digitalWrite(pts11N, relayOFF);
digitalWrite(pts11R, relayOFF);
digitalWrite(pts11TC, relayOFF); // not used at this point in time
digitalWrite(pts12N, relayOFF);
digitalWrite(pts12R, relayOFF);
digitalWrite(pts12TC, relayOFF); // not used at this point in time
digitalWrite(PLRW, relayOFF); // points lever reverse warning
startupsequence(); // quick check of all the outputs
// set all signals to stop, since we don't know much else as we start up!
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
delay(3000);
// ###################################
/// ### end of initialisation ###
/// ### end of initialisation ###
/// ### end of initialisation ###
// ###################################
}
//#########################
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
void loop() {
MAINsignalswitchset = 0; // reset signal proceed values to zero
STATIONsignalswitchset = 0; // reset signal proceed values to zero
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
route = 0; // I think this is redundant. 16/4/25
readinputs();
delay(10); // added for assisting with any switch debounce after reading inputs.
// display points settings and set red signals if against the points
// 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.
if (block5occ == true) {
digitalWrite(pts5TC, relayON);
} else {
digitalWrite(pts5TC, relayOFF);
}
if (block6occ == true) {
digitalWrite(pts6TC, relayON);
} else {
digitalWrite(pts6TC, relayOFF);
}
if (block7occ == true) {
digitalWrite(pts7TC, relayON);
} else {
digitalWrite(pts7TC, relayOFF);
}
//
// 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.
// ######## end of block occupancy display ###############
// at this point - all points settings and occupancies are shown
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.
// ######### end of emergency stop check #############
pointsleverstatus(); // display lever status on mimic and warning light if needed
// 6/3/25: everything above this line is correct and working
//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
// if a lever is moved with a signal cleared, place affected signals to stop. Also place any additional signals to stop if the lever change has caused a potential collision path. In this case, a signal is deemed to have been "skipped". To free-up a skipped signal, it must be placed back to stop and cleared again (safety feature).
if (emergstop == false) {
setsignalstoproceed(); //
}
} // <- this is the end of the main loop void
// ##########################################################################################
void resetSTATIONsignals() {
// this is accessed only if skippedSTATIONsignals is true. Signals must all be placed back to stop to free up ability to set any further proceed aspects
ST11stop();
ST13stop();
ST12stop();
if (ST1113stopVal == true && ST12stopVal == true) {
skippedSTATIONsignals = false;
}
} // <- end of void for resetting station signals
void resetMAINsignals() {
// this is accessed only if skippedMAINsignals is true. Signals must all be placed back to stop to free up ability to set any further proceed aspects
M1stop();
M2stop();
if (M1stopVal == true && M2stopVal == true) {
skippedMAINsignals = false;
}
} // <- end of void for resetting main signals
void setsignalstoproceed() { // determine which signals to set to proceed
// all routes have been determined, and emergency stops is inactive
if (M1stopVal == true || skippedMAINsignals == true) {
M1stop();
}
if (M2stopVal == true || skippedMAINsignals == true) {
M2stop();
}
if (ST1113stopVal == true || skippedSTATIONsignals == true) {
ST11stop();
ST13stop();
}
if (ST12stopVal == true || skippedSTATIONsignals == true) {
ST12stop();
}
// ####### work out if we have skipped signals or not here (9/4/25)
// were any signals cleared?
// if points are intransit AND an associated signal was cleared, then we have skipped signals.
// Skipped signals are determined if a points lever is "in-transit" (ie - not in the Normal or Reverse positions) AND a signal was clear for the respective points lever
//
// If no signals are cleared, then nothing is skipped.
if (points7intransit == true && MAINsignalswitchset >= 1) {
skippedMAINsignals = true;
}
// if (points7intransit == true && MAINsignalswitchset == 1) { // <-bug found 25/5/25. Should be station switch
if (points7intransit == true && STATIONsignalswitchset >= 1) {
skippedSTATIONsignals = true;
}
// points 7 - skipped signals scenarios complete 10/4/25
if (points6intransit == true && STATIONsignalswitchset >= 1) {
skippedSTATIONsignals = true;
} // working
if (points6intransit == true && STATIONsignalswitchset == 10) {
skippedMAINsignals = true; // prevents station anticlockwise movements crashing into main
skippedSTATIONsignals = true; // affects all station road movements
} // working
if (points6intransit == true && pts7Reverse == true && MAINsignalswitchset == 1) {
skippedMAINsignals = true;
}
if (points5intransit == true && shuntfrommain == true) { // shunt signal from main is set, then points 5are moved...
skippedMAINsignals = true;
}
if (points5intransit == true && shuntfromstation == true) { // shunt signal from station is set, and points 5 are in transit...
skippedSTATIONsignals = true;
}
if (points5intransit == true && shuntfromyard == true) { // shunt signal from yard is set, and points 5 are in tranist...
skippedSTATIONsignals = true;
}
if (points6intransit == true && shuntfrommain == true) { // shunt signal from main is set, then points 5are moved...
skippedMAINsignals = true;
}
if (points6intransit == true && shuntfromstation == true) { // shunt signal from station is set, and points 5 are in transit...
skippedSTATIONsignals = true;
}
if (points6intransit == true && shuntfromyard == true) { // shunt signal from yard is set, and points 5 are in tranist...
skippedSTATIONsignals = true;
}
if (points7intransit == true && shuntfrommain == true) { // shunt signal from main is set, then points 5are moved...
skippedMAINsignals = true;
}
if (points7intransit == true && shuntfromyard == true) { // shunt signal from yard is set, and points 5 are in tranist...
skippedSTATIONsignals = true;
}
// all the scenarios here for all the skipped signal possibilities above this line
if (skippedMAINsignals == true) {
resetMAINsignals();
}
if (skippedSTATIONsignals == true) {
resetSTATIONsignals();
}
if (skippedMAINsignals == false || skippedSTATIONsignals == false) {
proceedsignals();
} // in some cases, a change of lever won't affect the other track or another route setting (like changing 5 lever when both 5 and 6 are normal)
} // <- end of void to set signals to proceed
void proceedsignals() {
// carry on and set the proceed indication, based upon route
// set the MAIN signals here:
if (routeMAINset == true && skippedMAINsignals == false) {
points7NormalSignals(); // working 9/4/25. Skipped signals are working for main on straight route.
}
if ((routeBset == true) && (skippedMAINsignals == false) && (skippedSTATIONsignals == false)) {
routeB();
}
if ((routeA1set == true || routeA2set == true) && skippedSTATIONsignals == false) {
routeA1();
}
if ((routeD1set == true || routeD2set == true) && skippedSTATIONsignals == false && skippedMAINsignals == false) {
routeD();
}
if (routeEset == true && skippedSTATIONsignals == false && skippedMAINsignals == false) {
routeE();
}
if (routeCset == true && skippedSTATIONsignals == false) {
routeC();
}
if (routeFset == true && skippedSTATIONsignals == false) {
routeF();
}
} // end of MAINsignalsproceed()
// all routes are correctly set and respective signals clear correctly 11/4/25
// ###########################################################################################
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;
MAINsignalswitchset = 10; // set the switch as showing proceed for main line ACW
} else M1stopVal = true;
if (digitalRead(M2proceed) == LOW) {
M2stopVal = false;
MAINsignalswitchset = 1; // set the switch as showing proceed for main line
} else M2stopVal = true;
if (digitalRead(ST1113proceed) == LOW) {
ST1113stopVal = false;
STATIONsignalswitchset = 10; // 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
STATIONsignalswitchset = 1; // 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) == LOW) {
//if (digitalRead(pts5Ndet) == LOW) { //Old Digital Read - 24/05/25
if (analogRead(pts5Ndet) < 100) {
pts5Normal = true; // Points are normal, if not, then it is false
} else pts5Normal = false;
//if (digitalRead(pts5Rdet) == LOW) { //Old Digital Read - 24/05/25
if (analogRead(pts5Rdet) < 100) {
//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 (analogRead(pts6Ndet) < 100) {
//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) {
if (analogRead(pts6Rdet) < 100) {
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) {
if (analogRead(pts7Ndet) < 100) {
pts7Normal = true; // Points are normal, if not, then it is false
} else pts7Normal = false;
//if (digitalRead(pts7Rdet) == LOW) {
if (analogRead(pts7Rdet) < 100) {
pts7Reverse = true; // Points are reversed, if not, then it is false
route = route + 1;
} else pts7Reverse = false;
pts9NRvalue = analogRead(pts9NRdetect);
pts10NRvalue = analogRead(pts10NRdetect);
pts11NRvalue = analogRead(pts11NRdetect);
pts12NRvalue = analogRead(pts12NRdetect);
if (pts9NRvalue >= (proximityNvalue - proxwindow) && pts9NRvalue < (proximityNvalue + proxwindow)) { //(myVal > lowerBound && myVal < upperBound)
pts9Normal = true; //
} else pts9Normal = false;
if (pts9NRvalue > (proximityRvalue - proxwindow) && pts9NRvalue < (proximityRvalue + proxwindow)) {
pts9Reverse = true;
} else pts9Reverse = false;
if (pts10NRvalue >= (proximityNvalue - proxwindow) && pts10NRvalue < (proximityNvalue + proxwindow)) { //(myVal > lowerBound && myVal < upperBound)
pts10Normal = true; //
} else pts10Normal = false;
if (pts10NRvalue > (proximityRvalue - proxwindow) && pts10NRvalue < (proximityRvalue + proxwindow)) {
pts10Reverse = true;
} else pts10Reverse = false;
if (pts11NRvalue >= (proximityNvalue - proxwindow) && pts11NRvalue < (proximityNvalue + proxwindow)) { //(myVal > lowerBound && myVal < upperBound)
pts11Normal = true; //
} else pts11Normal = false;
if (pts11NRvalue > (proximityRvalue - proxwindow) && pts11NRvalue < (proximityRvalue + proxwindow)) {
pts11Reverse = true;
} else pts11Reverse = false;
if (pts12NRvalue >= (proximityNvalue - proxwindow) && pts12NRvalue < (proximityNvalue + proxwindow)) { //(myVal > lowerBound && myVal < upperBound)
pts12Normal = true; //
} else pts12Normal = false;
if (pts12NRvalue > (proximityRvalue - proxwindow) && pts12NRvalue < (proximityRvalue + proxwindow)) {
pts12Reverse = true;
} else pts12Reverse = false;
} // <- end of reading inputs void
// ##########################################################################################
//##### all possible signal indications below this line:
void M1stop() {
digitalWrite(M1red, relayON);
digitalWrite(M1yel, relayOFF);
digitalWrite(M1grn, relayOFF);
}
void M1caution() {
digitalWrite(M1red, relayOFF);
digitalWrite(M1yel, relayON);
digitalWrite(M1grn, relayOFF);
}
void M1clear() {
digitalWrite(M1red, relayOFF);
digitalWrite(M1yel, relayOFF);
digitalWrite(M1grn, relayON);
}
void M2stop() {
digitalWrite(M2red, relayON);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayOFF);
shuntfrommain = false;
}
void M2caution() {
digitalWrite(M2red, relayOFF);
digitalWrite(M2yel, relayON);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayOFF);
}
void M2clear() {
digitalWrite(M2red, relayOFF);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayON);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayOFF);
}
void M2turnout() {
digitalWrite(M2red, relayON);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayON);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayOFF);
}
void M2yard1() {
digitalWrite(M2red, relayON);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayON);
digitalWrite(M2y2, relayOFF);
shuntfrommain = true;
}
void M2yard2() {
digitalWrite(M2red, relayON);
digitalWrite(M2yel, relayOFF);
digitalWrite(M2grn, relayOFF);
digitalWrite(M2TO, relayOFF);
digitalWrite(M2y1, relayOFF);
digitalWrite(M2y2, relayON);
shuntfrommain = true;
}
void ST11stop() {
digitalWrite(ST11red, relayON);
digitalWrite(ST11yel, relayOFF);
digitalWrite(ST11grn, relayOFF);
digitalWrite(ST11TO, relayOFF);
}
void ST11caution() {
digitalWrite(ST11red, relayOFF);
digitalWrite(ST11yel, relayON);
digitalWrite(ST11grn, relayOFF);
digitalWrite(ST11TO, relayOFF);
}
void ST11clear() {
digitalWrite(ST11red, relayOFF);
digitalWrite(ST11yel, relayOFF);
digitalWrite(ST11grn, relayON);
digitalWrite(ST11TO, relayOFF);
}
void ST11turnout() {
digitalWrite(ST11red, relayON);
digitalWrite(ST11yel, relayOFF);
digitalWrite(ST11grn, relayOFF);
digitalWrite(ST11TO, relayON);
}
void ST12stop() { // semaphore signal with LED signal colour and route setting insert
digitalWrite(ST12red, relayON);
digitalWrite(ST12yel, relayOFF);
digitalWrite(ST12grn, relayOFF);
digitalWrite(ST12y1, relayOFF);
digitalWrite(ST12y2, relayOFF);
shuntfromstation = false;
}
void ST12caution() { // semaphore signal
digitalWrite(ST12red, relayOFF);
digitalWrite(ST12yel, relayON);
digitalWrite(ST12grn, relayOFF);
digitalWrite(ST12y1, relayOFF);
digitalWrite(ST12y2, relayOFF);
}
void ST12clear() { // semaphore signal
digitalWrite(ST12red, relayOFF);
digitalWrite(ST12yel, relayOFF);
digitalWrite(ST12grn, relayON);
digitalWrite(ST12y1, relayOFF);
digitalWrite(ST12y2, relayOFF);
}
void ST12yard1() { // semaphore signal
digitalWrite(ST12red, relayOFF);
digitalWrite(ST12yel, relayOFF);
digitalWrite(ST12grn, relayOFF);
digitalWrite(ST12y1, relayON);
digitalWrite(ST12y2, relayOFF);
shuntfromstation = true;
}
void ST12yard2() { // semaphore signal
digitalWrite(ST12red, relayOFF);
digitalWrite(ST12yel, relayOFF);
digitalWrite(ST12grn, relayOFF);
digitalWrite(ST12y1, relayOFF);
digitalWrite(ST12y2, relayON);
shuntfromstation = true;
}
void ST13stop() {
digitalWrite(ST13red, relayON);
digitalWrite(ST13yelM, relayOFF);
digitalWrite(ST13yelS, relayOFF);
shuntfromyard = false;
}
void ST13main() {
digitalWrite(ST13red, relayOFF);
digitalWrite(ST13yelM, relayON);
digitalWrite(ST13yelS, relayOFF);
shuntfromyard = true;
}
void ST13station() {
digitalWrite(ST13red, relayOFF);
digitalWrite(ST13yelM, relayOFF);
digitalWrite(ST13yelS, relayON);
shuntfromyard = true;
}
void points7NormalSignals() {
if (pts7Normal == true && skippedMAINsignals == false) {
if (M1stopVal == true && M2stopVal == true) {
points7lockedN = false; // added 16/3/25
points7lockedR = false; // added 16/3/25
}
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
points7lockedN = true;
points7lockedR = false;
M2stop();
if (C2nextstop == true) {
// Set M1 to caution
M1caution();
MAINsignalswitchset = 10;
} else {
// set M1 to clear
M1clear();
MAINsignalswitchset = 10;
}
}
if (M2stopVal == false) {
points7lockedN = true; // added 16/3/25
// now check opposite direction etc
points7lockedN = true;
points7lockedR = false;
M1stop();
if (M3next == true) { // if M3 is at stop, then display caution. If not, display clear.
M2caution();
MAINsignalswitchset = 1;
} else {
M2clear();
MAINsignalswitchset = 1;
}
}
} //<- this is the end of setting the main line signal after checking block7 occupancy
}
}
void emergencystop() {
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
}
void routeA1() {
// this sets station signal only. Main signal is covered in it's own void.
// 5N or 5R; 6N, 7N
if (skippedSTATIONsignals == false) { // /13/4/25
// set the STATION signals here:
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();
points6lockedN = true;
points6lockedR = false;
//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();
STATIONsignalswitchset = 10;
} else {
// set ST11 to clear here and ST12 to stop
ST11clear();
STATIONsignalswitchset = 10;
}
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST11stop();
points6lockedN = true;
points6lockedR = false;
//ST12 is set to proceed, now check next block
if (C4nextstop == true) {
// display caution if true, otherwise display clear
ST12caution();
STATIONsignalswitchset = 1;
} else {
// set ST12 to clear here and ST11 to stop
ST12clear();
STATIONsignalswitchset = 1;
}
}
} // end if setSTATIONsignals is FALSE
// } //<- this is the end of block 6 occupancy and signal setting check
} //this is the end of "if skipped signals is false"
if (STATIONsignalswitchset > 0) {
routeAlockedSTATION = true;
// routeBlockedSTATION=false;
// routeClockedSTATION=false;
// routeDlockedSTATION=false;
// routeElockedSTATION=false;
// routeFlockedSTATION=false;
} else routeAlockedSTATION = false;
if (MAINsignalswitchset > 0) {
routeAlockedMAIN = true;
// routeBlockedMAIN=false;
// routeClockedMAIN=false;
// routeDlockedMAIN=false;
// routeElockedMAIN=false;
// routeFlockedMAIN=false;
} else routeAlockedMAIN = false;
} // <- this is the end of routeA void
void routeB() {
if (skippedMAINsignals == false && skippedSTATIONsignals == false && routeAlockedMAIN == false && routeClockedMAIN == false && routeDlockedMAIN == false && routeElockedMAIN == false && routeFlockedMAIN == false && routeAlockedSTATION == false && routeClockedSTATION == false && routeDlockedSTATION == false && routeElockedSTATION == false && routeFlockedSTATION == false) {
if (pts7Reverse == true && pts6Normal == true && pts5Normal == true) {
// 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 {
if (skippedSTATIONsignals == false) {
//see if the respective signal switch is set to proceed, since block is clear
//anticlockwise:
if (ST1113stopVal == false && M2stopVal == true) {
M2stop(); //opposing signal
ST13main();
STATIONsignalswitchset = 10;
points5lockedN = true;
points6lockedN = true;
points7lockedR = true;
points5lockedR = false;
points6lockedR = false;
points7lockedN = false;
routeBlockedSTATION = true;
}
} // end of it for skipped station signals being false
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true && skippedMAINsignals == false && block6occ == false && block5occ == false && block7occ == false) {
ST13stop();
M2yard1();
MAINsignalswitchset = 1;
points5lockedN = true;
points6lockedN = true;
points7lockedR = true;
points5lockedR = false;
points6lockedR = false;
points7lockedN = false;
routeBlockedMAIN = true;
}
if (M2stopVal == true) {
M2stop();
routeBlockedMAIN = false;
}
if (ST1113stopVal == true) {
ST13stop();
routeBlockedSTATION = false;
}
} //<- this is the end of block 6 occupancy and signal setting check
}
} // end of "if" for if either station or main signals are skipped
} // <- this is the end of routeB void
void routeC() {
// 5N, 6R, 7N
//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
STATIONsignalswitchset = 10;
points5lockedN = true;
points6lockedN = true;
points7lockedR = true;
points5lockedR = false;
points6lockedR = false;
points7lockedN = false;
} else {
ST13stop();
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST13stop();
//ST12 is set to proceed
ST12yard1();
STATIONsignalswitchset = 1;
points5lockedN = true;
points6lockedN = true;
points7lockedR = true;
points5lockedR = false;
points6lockedR = false;
points7lockedN = false;
} else {
ST12stop();
}
points7NormalSignals(); //use this void as it is common for route 1 and route 3
} //<- this is the end of block 6 occupancy and signal setting check
} // <- this is the end of routeC void
void routeD() {
// 5N or 5R, 6R, 7R
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();
STATIONsignalswitchset = 10;
points6lockedR = true;
points6lockedN = false;
points7lockedR = true;
points7lockedN = false;
} else {
ST11stop();
M2stop();
points6lockedR = false;
points6lockedN = false;
points7lockedR = false;
points7lockedN = false;
}
//now check M2 stop value and set signal accordingly
if (M2stopVal == false && ST1113stopVal == true) {
ST11stop();
M2turnout();
MAINsignalswitchset = 1;
points6lockedR = true;
points6lockedN = false;
points7lockedR = true;
points7lockedN = false;
}
if (M2stopVal == true && ST1113stopVal == true) {
M2stop();
ST11stop();
points6lockedR = false;
points6lockedN = false;
points7lockedR = false;
points7lockedN = false;
}
} //<- this is the end of route 2 occupancy and signal setting check
} // this is the end of routeD void
void routeE() {
// 5R, 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 {
if (points5intransit == false && points6intransit == false && points7intransit == false) {
//see if the respective signal switch is set to proceed, since block is clear
//anticlockwise:
if (ST1113stopVal == false && M2stopVal == true) {
M2stop(); //opposing signal
ST13main();
STATIONsignalswitchset = 10;
points5lockedR = true;
points6lockedN = true;
points7lockedR = true;
points5lockedN = false;
points6lockedR = false;
points7lockedN = false;
}
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true) {
ST13stop();
M2yard2();
MAINsignalswitchset = 1;
points5lockedR = true;
points6lockedN = true;
points7lockedR = true;
points5lockedN = false;
points6lockedR = false;
points7lockedN = false;
}
if (M2stopVal == true) {
M2stop();
}
if (ST1113stopVal == true) {
ST13stop();
}
} else {
M2stop();
ST13stop();
} // the "else" is as a result of any points being in transit
} //<- this is the end of block 6 occupancy and signal setting check
} // <- this is the end of routeE void
void routeF() {
// 5R, 6R, 7N
// 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
STATIONsignalswitchset = 10;
points5lockedR = true;
points6lockedR = true;
points7lockedN = true;
points5lockedN = false;
points6lockedN = false;
points7lockedR = false;
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST13stop();
//ST12 is set to proceed
ST12yard2();
STATIONsignalswitchset = 1;
points5lockedR = true;
points6lockedR = true;
points5lockedN = false;
points6lockedN = false;
}
if (ST12stopVal == true) {
ST12stop();
}
if (ST1113stopVal == true) {
ST13stop();
}
if (ST1113stopVal == true && ST12stopVal == true) {
points5lockedR = false;
points6lockedR = false;
points5lockedN = false;
points6lockedN = false;
}
points7NormalSignals(); //use this void as it is common for route 1, 3 and 6
} //<- this is the end of block 6 occupancy and signal setting check
} //<- this is the end of "routeF" void
void pointsleverstatus() {
pointsleverwarnings(); // all the warnings in one void (and all working, 15/4/25)
//
// the remainder of this void simply determines the current route setting (8/4/25)
if (pts7Normal == true && pts7Reverse == false) {
routeMAINset = true;
} else routeMAINset = false;
//if (pts5Normal == true && pts6Normal == true && pts7Normal == true){
// if (pts6Normal == true && pts7Normal == true){
if (pts6Normal == true && pts7Normal == true && pts6Reverse == false && pts7Reverse == false) { // 27/4/25
routeA1set = true;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
}
//if (pts5Normal == true && pts6Normal == true && pts7Reverse == true){
if (pts5Normal == true && pts6Normal == true && pts7Reverse == true && pts5Reverse == false && pts6Reverse == false && pts7Normal == false) {
routeA1set = false;
routeBset = true; //
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
routeMAINset = false;
}
// if (pts5Normal == true && pts6Reverse == true){
if (pts5Normal == true && pts6Reverse == true && pts5Reverse == false && pts6Normal == false) {
routeA1set = false;
routeBset = false;
routeCset = true; //
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
route = 10; // 9/4/25
}
//if (pts5Normal == true && pts6Reverse == true && pts7Reverse == true){
if (pts5Normal == true && pts6Reverse == true && pts7Reverse == true && pts5Reverse == false && pts6Normal == false && pts7Normal == false) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = true; //
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
routeMAINset = false;
route = 11;
}
//if (pts5Reverse == true && pts6Normal == true){
if (pts5Reverse == true && pts6Normal == true && pts5Normal == false && pts6Reverse == false) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = true; //
routeEset = false;
routeFset = false;
routeD2set = false;
}
//if (pts5Reverse == true && pts6Normal == true && pts7Reverse == true){
if (pts5Reverse == true && pts6Normal == true && pts7Reverse == true && pts5Normal == false && pts6Reverse == false && pts7Normal == false) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = true;
routeFset = false;
routeD2set = false;
routeMAINset = false;
}
//if (pts5Reverse == true && pts6Reverse == true){
if (pts5Reverse == true && pts6Reverse == true && pts5Normal == false && pts6Normal == false) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = true;
routeD2set = false;
route = 110;
}
//if (pts5Reverse == true && pts6Reverse == true && pts7Reverse == true){
if (pts5Reverse == true && pts6Reverse == true && pts7Reverse == true && pts5Normal == false && pts6Normal == false && pts7Normal == false) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = true;
routeMAINset = false;
route = 111;
}
if (points5intransit == true) {
routeBset = false;
routeCset = false;
routeEset = false;
routeFset = false;
// lever 5 only affects these routes
}
if (points6intransit == true) {
routeA1set = false;
routeBset = false;
routeCset = false;
routeD1set = false;
routeA2set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
// lever 6 only affects these routes
}
if (points7intransit == true) {
routeBset = false;
routeD1set = false;
routeEset = false;
routeFset = false;
routeD2set = false;
routeMAINset = false;
// lever 7 only affects these routes
}
} // end of void
void pointsleverwarnings() {
// this void is all working and don't touch! 15/4/25
// ######## display points lever status for all levers ##############
// ## allocates route values for the setting of the levers ##########
// ## cancel specific route values if points lever is in-transit ####
// ## alert signaller if lever is in-transit for too long ###########
//if (pts5Normal == true) {
if (pts5Normal == true && pts5Reverse == false) { //27/4/25
digitalWrite(pts5N, relayON);
warning5 = false;
points5intransit = false;
} else { // points are either in-transit or reversed
if (points5intransit == false) { digitalWrite(pts5N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning5 = true;
}
if (pts6Normal == false) {
if (points6intransit == false) {
digitalWrite(pts6Nstrt, relayOFF);
digitalWrite(pts6Ndiag, relayOFF);
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
} //stops flicker if points are not normal and in-transit alarm is occurring
warning6 = true;
}
if (pts7Normal == false) {
if (points7intransit == false) { digitalWrite(pts7N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning7 = true;
}
if (pts9Normal == false) {
if (points9intransit == false) { digitalWrite(pts9N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning9 = true;
}
if (pts10Normal == false) {
if (points10intransit == false) { digitalWrite(pts10N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning10 = true;
}
if (pts11Normal == false) {
if (points11intransit == false) { digitalWrite(pts11N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning11 = true;
}
if (pts12Normal == false) {
if (points12intransit == false) { digitalWrite(pts12N, relayOFF); } //stops flicker if points are not normal and in-transit alarm is occurring
warning12 = true;
}
if (pts5Reverse == true && pts5Normal == false) { // 27/4/25
digitalWrite(pts5R, relayON);
warning5 = true;
points5intransit = false;
} else {
digitalWrite(pts5R, relayOFF);
warning5 = false;
}
//if (pts7Normal == true && pts6Normal == true) {
if (pts7Normal == true && pts6Normal == true && pts7Reverse == false && pts6Reverse == false) { // 27/4/25
digitalWrite(pts7N, relayON);
digitalWrite(pts7R, relayOFF);
digitalWrite(pts6Nstrt, relayON);
digitalWrite(pts6Ndiag, relayOFF);
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
points6intransit = false;
points7intransit = false;
warning7 = false;
warning6 = false;
} else { // this "else" added 27/4/27 to turn mimic off, if one/both levers are in-transit
if (points7intransit == true) { digitalWrite(pts7N, relayOFF); }
if (points6intransit == true) { digitalWrite(pts6Nstrt, relayOFF); }
}
//if (pts7Reverse == true && pts6Reverse == true) { //7 points reversed. M1 must be STOP
if (pts7Reverse == true && pts6Reverse == true && pts7Normal == false && pts6Normal == false) { //7 points reversed. M1 must be STOP; 27/4/25
digitalWrite(pts7R, relayON);
digitalWrite(pts7N, relayOFF);
digitalWrite(pts6Rsm, relayON);
digitalWrite(pts6Nstrt, relayOFF);
digitalWrite(pts6Ndiag, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
warning7 = true;
warning6 = true;
points6intransit = false;
points7intransit = false;
M1stop();
} else { //this "else" added 27/4/25 to turn mimics of if one/all levers are in-transit
if (points7intransit == true) { digitalWrite(pts7R, relayOFF); }
if (points6intransit == true) { digitalWrite(pts6Rsm, relayOFF); }
}
//if (pts7Normal == true && pts6Reverse == true) {
if (pts7Normal == true && pts6Reverse == true && pts7Reverse == false && pts6Normal == false) { // 27/4/25
digitalWrite(pts7N, relayON);
digitalWrite(pts7R, relayOFF);
digitalWrite(pts6Rsy, relayON);
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Nstrt, relayOFF);
digitalWrite(pts6Ndiag, relayOFF);
warning6 = true;
warning7 = false;
points6intransit = false;
points7intransit = false;
} else { //this "else" added 27/4/25 to turn mimics off if one/all levers are in-transit
if (points7intransit == true) { digitalWrite(pts7N, relayOFF); }
if (points6intransit == true) { digitalWrite(pts6Rsy, relayOFF); }
}
//if (pts7Reverse == true && pts6Normal == true) { //7 points reversed. M1 must be STOP
if (pts7Reverse == true && pts6Normal == true && pts7Normal == false && pts6Reverse == false) { //7 points reversed. M1 must be STOP; 27/4/25
digitalWrite(pts7R, relayON);
digitalWrite(pts7N, relayOFF);
digitalWrite(pts6Ndiag, relayON);
digitalWrite(pts6Nstrt, relayOFF);
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
warning7 = true;
warning6 = false;
points6intransit = false;
points7intransit = false;
M1stop();
} else { // this "else" added 27/4/25 to turn mimics off if one/all points levers are in-transit
if (points7intransit == true) { digitalWrite(pts7R, relayOFF); }
if (points6intransit == true) { digitalWrite(pts6Ndiag, relayOFF); }
}
// if (pts9Normal == true) {
if (pts9Normal == true && pts9Reverse == false) { // 27/4/25
digitalWrite(pts9N, relayON);
warning9 = false;
points9intransit = false;
} else {
digitalWrite(pts9N, relayOFF);
warning9 = true;
}
//if (pts9Reverse == true){
if (pts9Reverse == true && pts9Normal == false) { // 27/4/25
points9intransit = false;
digitalWrite(pts9R, relayON);
} else {
digitalWrite(pts9R, relayOFF);
}
//if (pts10Normal == true) {
if (pts10Normal == true && pts10Reverse == false) { //27/4/25
digitalWrite(pts10N, relayON);
warning10 = false;
points10intransit = false;
} else {
digitalWrite(pts10N, relayOFF);
warning10 = true;
}
// if (pts10Reverse == true){
if (pts10Reverse == true && pts10Normal == false) { // 27/4/25
points10intransit = false;
digitalWrite(pts10R, relayON);
} else {
digitalWrite(pts10R, relayOFF);
}
//if (pts11Normal == true) {
if (pts11Normal == true && pts11Reverse == false) { //27/4/25
digitalWrite(pts11N, relayON);
warning11 = false;
points11intransit = false;
} else {
digitalWrite(pts11N, relayOFF);
warning11 = true;
}
//if (pts11Reverse == true){
if (pts11Reverse == true && pts11Normal == false) { // 27/4/25
points11intransit = false;
digitalWrite(pts11R, relayON);
} else {
digitalWrite(pts11R, relayOFF);
}
//if (pts12Normal == true) {
if (pts12Normal == true && pts12Reverse == false) { //27/4/25
digitalWrite(pts12N, relayON);
warning12 = false;
points12intransit = false;
} else {
digitalWrite(pts12N, relayOFF);
warning12 = true;
}
//if (pts12Reverse == true){
if (pts12Reverse == true && pts12Normal == false) { // 27/4/25
points12intransit = false;
digitalWrite(pts12R, relayON);
} else {
digitalWrite(pts12R, relayOFF);
}
// if (pts5Normal == false && pts5Reverse == false && points5intransit == false){
// 5 were changed and are in transit. Commence timer. This happens ones, since intransit is now flagged as being true.
if (((pts5Normal == false && pts5Reverse == false) || (pts5Normal == true && pts5Reverse == true)) && points5intransit == false) {
points5intransit = true;
lever5timer = currentMillis; // commence timer for operating points
}
if (((pts6Normal == false && pts6Reverse == false) || (pts6Normal == true && pts6Reverse == true)) && points6intransit == false) {
// if (pts6Normal == false && pts6Reverse == false && points6intransit == false){
// 6 are in transit
points6intransit = true;
lever6timer = currentMillis; // commence timer for operating points
}
//if (pts7Normal == false && pts7Reverse == false && points7intransit == false){ // remarked out 27/4/25 to account for delay in proximity sensor change of state. Similarly, for all other levers.
if (((pts7Normal == false && pts7Reverse == false) || (pts7Normal == true && pts7Reverse == true)) && points7intransit == false) {
// 7 are in transit
points7intransit = true;
lever7timer = currentMillis; // commence timer for operating points
}
if (((pts9Normal == false && pts9Reverse == false) || (pts9Normal == true && pts9Reverse == true)) && points9intransit == false) {
//if (pts9Normal == false && pts9Reverse == false && points9intransit == false){
// 9 are in transit
points9intransit = true;
lever9timer = currentMillis; // commence timer for operating points
}
if (((pts10Normal == false && pts10Reverse == false) || (pts10Normal == true && pts10Reverse == true)) && points10intransit == false) {
// if (pts10Normal == false && pts10Reverse == false && points10intransit == false){
// 10 are in transit
points10intransit = true;
lever10timer = currentMillis; // commence timer for operating points
}
if (((pts11Normal == false && pts11Reverse == false) || (pts11Normal == true && pts11Reverse == true)) && points11intransit == false) {
// if (pts11Normal == false && pts11Reverse == false && points11intransit == false){
// 11 are in transit
points11intransit = true;
lever11timer = currentMillis; // commence timer for operating points
}
if (((pts12Normal == false && pts12Reverse == false) || (pts12Normal == true && pts12Reverse == true)) && points12intransit == false) {
// if (pts12Normal == false && pts12Reverse == false && points12intransit == false){
// 12 are in transit
points12intransit = true;
lever12timer = currentMillis; // commence timer for operating points
}
// ######## end of points lever status #######
// @@@@@@@@ start: flash mimic if points lever is in transit for too long
if (points5intransit == true) {
if (currentMillis - lever5timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts5N, relayON); // turn both N and R mimics on
digitalWrite(pts5R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts5N, relayOFF); // turn both N and R mimics off
digitalWrite(pts5R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points5intransit == true. Lever 5 in-transit alarm working 2/4/25. Repeat for other levers.
if (points6intransit == true) {
if (currentMillis - lever6timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts6Nstrt, relayON); // turn both N and R mimics on
digitalWrite(pts6Ndiag, relayON);
digitalWrite(pts6Rsm, relayON);
digitalWrite(pts6Rsy, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts6Nstrt, relayOFF); // turn both N and R mimics off
digitalWrite(pts6Ndiag, relayOFF); // turn both N and R mimics off
digitalWrite(pts6Rsm, relayOFF);
digitalWrite(pts6Rsy, relayOFF);
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points6intransit == true.. Not teseted yet.
if (points7intransit == true) {
if (currentMillis - lever7timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts7N, relayON); // turn both N and R mimics on
digitalWrite(pts7R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts7N, relayOFF); // turn both N and R mimics off
digitalWrite(pts7R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points7intransit == true.
if (points9intransit == true) {
if (currentMillis - lever9timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts9N, relayON); // turn both N and R mimics on
digitalWrite(pts9R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts9N, relayOFF); // turn both N and R mimics off
digitalWrite(pts9R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points9intransit == true.
if (points10intransit == true) {
if (currentMillis - lever10timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts10N, relayON); // turn both N and R mimics on
digitalWrite(pts10R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts10N, relayOFF); // turn both N and R mimics off
digitalWrite(pts10R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points10intransit == true.
if (points11intransit == true) {
if (currentMillis - lever11timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts11N, relayON); // turn both N and R mimics on
digitalWrite(pts11R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts11N, relayOFF); // turn both N and R mimics off
digitalWrite(pts11R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points11intransit == true.
if (points12intransit == true) {
if (currentMillis - lever12timer >= pointslevertimer) //test whether the period has elapsed
{ // points have been in-transit too long, so flash both mimics to alert signaller
if (pulseHigh == true) {
digitalWrite(pts12N, relayON); // turn both N and R mimics on
digitalWrite(pts12R, relayON); // turn both N and R mimics on
}
if (pulseHigh == false) {
digitalWrite(pts12N, relayOFF); // turn both N and R mimics off
digitalWrite(pts12R, relayOFF); // turn both N and R mimics off
} // <- add this in (31/3/25). If so, pulse the respective points mimics using pulseHigh base rate
}
} // end IF points12intransit == true.
// // @@@@@@@@ end: flash mimic if points lever is in transit for too long
//
// START: points lever alert warning light
//
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, relayOFF);
}
if (alertON == true && pulseHigh == true) {
digitalWrite(PLRW, relayON); // points lever reverse warning ON
}
if (alertON = true && pulseHigh == false) {
digitalWrite(PLRW, relayOFF); // turn off for the pulse
}
//
// this void is all working and don't touch! 15/4/25. Modified 27/4/25
// ############### end points lever alert warning light ###############
} // end of pointsleverwarning void #####################################
void startupsequence() {
M1caution();
M2caution();
ST12caution();
ST11caution();
ST13main();
delay(3200);
M1clear();
M2clear();
ST12clear();
ST11clear();
ST13station();
delay(3200);
M2turnout();
ST11turnout();
delay(3200);
ST12yard1();
M2yard1();
delay(3200);
ST12yard2();
M2yard2();
delay(3200);
}Points warning indicator
Track circuit - lever 5
Next signals - stop or clear
Emergency stop
Block occupancy - levers 5, 6, 7
Signal M1
Signal M2
Signal ST11
Signal ST13
Signal ST12
2 o'clock = normal
12 o'clock = reverse