//
// Wascoe Siding Loco Points interlocking
// R. Parnell 8/10/2023
//
// V5: 16/1/24 - bugs seemed to have been removed. Simulation Ok. Removal of
// "serial print" to tidy up code and allow respective output to be used for signal lamp output.
// Found value for route 3 to be "010" instead of "10".
// 15/1/24: working through flickering issue and resolving.
// Need to add feature whereby if conflicting signal switches are set,
// nothing happens. A unique scenario can exist when 7 points are reversed.
// V4: 14/1/24 - further simulation debugging, working through errors...
// V3: 12/1/24 - heartbeat not working, other minor issues. Suspect accidental changing of code
// that was still valid for compilation and accidentally saved. The bug to be found!
// Update: heartbeater timer was set to Zero! Fixed up and tested.
// - signals flicker on red when set to proceed. To be sorted out.
// 14/1/24 - flicker probably as a result of using serial print for debugging as D)/D1 are used
// as outputs.
// V2 4/1/24: a realisation that the outputs should be active LOW, not high, to drive the relays.
// This version reworks the outputs to the opposite state of V1.
// 18/11/23 - points lever warning not working correctly. Pulses very randomly in any input state.
// ************************************
// *** ***** * **** *****
// * * * * * * *
// *** * ***** **** *
// * * * * * * *
// *** * * * * * *
//
// ***************************************
// inputs - active "low"
// 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 HBon=0;
bool HBtoggle = false; // PLwarning LED toggle
//16/10/23
int displaydelay = 40; // minimum time to display each signal aspect
// points mimics redefined.
// 6 outputs all up.
// 5N, 5R (one relay, NC or NO contacts)
// Group A (part of 7 points on the main line)
// Group B (7 points "N" on main and station road)
// Group C (7 points "R")
// Group D (6R & 7R) OR (6N &7N)
// Group E (6N & 7R) OR (6R & 7N)
int pts5NR = 21; // normal, reverse, track circuit mimic
//int pts5R = 22;
int groupA = 22;
int groupB = 23;
int groupC = 24;
int groupD = 25;
int groupE = 26;
int pts5TC = 27;
int pts6TC = 28;
int pts7TC = 29;
//int pts6N = 24;
//int pts6R = 25;
// int pts7N = 27;
// int pts7R = 28;
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
int intransitLED = A9; // if any points are not normal or reverse 19/11/23
// not enough inputs for future block detection of 9, 10, 11 and 12 points
int hbLED = A10;
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 HBMillis = 500;
unsigned long HBtimer = 500;
unsigned long HBstartMillis = 0;
unsigned long HBcurrentMillis = 0;
//unsigned long warningONcurrentmillis;
//unsigned long warningOFFcurrentmillis;
//unsigned long startMillis; // for starting countdown after blockwas occupied
//unsigned long warningmillis = 600; // time period for warning flashing on/off 50% duty cycle
unsigned long currentMillis; // what will be the current value to compare countdown to
bool leveralerton = false; // lever warning indicator toggle
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 intransit5= false; // added 19/11/23
bool intransit6= false; // added 19/11/23
bool intransit7= false; // added 19/11/23
bool intransit8= false; // added 19/11/23
bool intransit9= false; // added 19/11/23
bool intransit10= false; // added 19/11/23
bool intransit11= false; // added 19/11/23
bool intransit12= false; // added 19/11/23
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
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
//#########################
void setup() {
//Serial.begin(9600); // open the serial port at 9600 bps:
// serial port for debugging purposes only
// startMillis = millis(); //start timer value for alert
HBstartMillis = millis();
// digital inputs:
pinMode(emerg, INPUT_PULLUP); //INPUT_PULLUP
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);
// analogue inputs
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);
pinMode(intransitLED, OUTPUT);
pinMode(hbLED, OUTPUT);
pinMode(pts5NR, OUTPUT); // normal/reverse
//pinMode(pts5R, OUTPUT);
pinMode(groupA, OUTPUT); // 16/10/23
pinMode(groupB, OUTPUT);
pinMode(groupC, OUTPUT);
pinMode(groupD, OUTPUT);
pinMode(groupE, OUTPUT);
//pinMode(pts6N, OUTPUT);
//pinMode(pts6R, OUTPUT);
//pinMode(pts7N, OUTPUT);
// pinMode(pts7R, OUTPUT);
pinMode(pts5TC, OUTPUT);
pinMode(pts6TC, 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
// turn all outputs off (HIGH)
digitalWrite(M1red, HIGH);
digitalWrite(M1yel, HIGH);
digitalWrite(M1grn, HIGH);
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, HIGH);
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, HIGH);
digitalWrite(ST11grn, HIGH);
digitalWrite(ST11TO, HIGH);
digitalWrite(ST13red, HIGH);
digitalWrite(ST13yelM, HIGH);
digitalWrite(ST13yelS, HIGH);
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, HIGH);
//16/10/23
digitalWrite(pts5NR, HIGH); // normal, reverse, track circuit mimic
//digitalWrite(pts5R, LOW);
digitalWrite(groupA, HIGH);
digitalWrite(groupB, HIGH);
digitalWrite(groupC, HIGH);
digitalWrite(groupD, HIGH);
digitalWrite(groupE, HIGH);
digitalWrite(pts5TC, HIGH);
digitalWrite(pts6TC, HIGH);
digitalWrite(pts7TC, HIGH);
digitalWrite(pts9N, HIGH);
digitalWrite(pts9R, HIGH);
digitalWrite(pts9TC, HIGH); // not used at this point in time (reserved for possible use later)
digitalWrite(pts10N, HIGH);
digitalWrite(pts10R, HIGH);
digitalWrite(pts10TC, HIGH); // not used at this point in time
digitalWrite(pts11N, HIGH);
digitalWrite(pts11R, HIGH);
digitalWrite(pts11TC, HIGH); // not used at this point in time
digitalWrite(pts12N, HIGH);
digitalWrite(pts12R, HIGH);
digitalWrite(pts12TC, HIGH); // not used at this point in time
digitalWrite(PLRW, HIGH); // points lever reverse warning
// set all signals to stop, since we don't know much else!
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
// ###################################
/// ### end of initialisation ###
/// ### end of initialisation ###
/// ### end of initialisation ###
// ###################################
}
//#########################
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
// START LOOP ##
void loop() {
readinputs();
//currentMillis = millis();
// suspect that the flasher uses up too much memory and causes erractic behaviour. 19/11/23
// flash heartbeat LED along the way
HBcurrentMillis = millis();
if (HBcurrentMillis - HBstartMillis >= HBtimer){
HBtoggle = !HBtoggle; // invert the status from true/false to false/true
digitalWrite(hbLED,HBtoggle); // turn HB on/off
HBstartMillis = HBcurrentMillis;
}
route = 0; // reset route options to zero
//HBtimer = millis();
// 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"
// pts5NR relay. HIGH = "normal" mimic
// HIGH = "reverse" mimic
if ((pts5Normal==true)&&(pts5Reverse==false)) {
digitalWrite(pts5NR, HIGH);
warning5 = false;
intransit5=false;
} else if ((pts5Normal == false)&&(pts5Reverse==true)) {
digitalWrite(pts5NR, LOW);
warning5 = true;
intransit5=false;
route = route + 100; // route will be 5 or 6 into yard 2
} else if ((pts5Normal==false)&&(pts5Reverse==false)){
digitalWrite(pts5NR, LOW);
warning5 = true;
intransit5=true;
}
if ((pts6Normal==false)&&(pts6Reverse==false)) intransit6=true;
if ((pts7Normal==false)&&(pts7Reverse==false)) intransit7=true;
if ((pts6Normal==true)&&(pts6Reverse==false)) intransit6=false;
if ((pts7Normal==true)&&(pts7Reverse==false)) intransit7=false;
if ((pts6Normal==false)&&(pts6Reverse==true)) intransit6=false;
if ((pts7Normal==false)&&(pts7Reverse==true)) intransit7=false;
// 6
if ((pts7Normal == true) && (pts6Normal == true)) {
digitalWrite(groupA,LOW);
digitalWrite(groupB,LOW);
digitalWrite(groupD,LOW);
digitalWrite(groupC,HIGH);
digitalWrite(groupE,HIGH);
ST13stop();
warning7 = false;
warning6 = false;
}
if ((pts7Reverse == true) && (pts6Reverse == true)) { //7 points reversed. M1 must be STOP
digitalWrite(groupA,LOW);
digitalWrite(groupC,LOW);
digitalWrite(groupD,LOW);
digitalWrite(groupB,HIGH);
digitalWrite(groupE,HIGH);
warning7 = true;
warning6 = true;
M1stop();
ST13stop();
ST12stop();
route = route + 11;
// Serial.println("7R & 6R");//debugging
}
if ((pts7Normal == true) && (pts6Reverse == true)) {
digitalWrite(groupA,LOW);
digitalWrite(groupB,LOW);
digitalWrite(groupE,LOW);
digitalWrite(groupC,HIGH);
digitalWrite(groupD,HIGH);
ST11stop();
warning6 = true;
warning7 = false;
route = route + 10;
}
if ((pts7Reverse == true) && (pts6Normal == true)) { //7 points reversed. M1 must be STOP
//Serial.println("7 reversed, 6 normal");//debugging
digitalWrite(groupA,LOW);
digitalWrite(groupC,LOW);
digitalWrite(groupE,LOW);
digitalWrite(groupB,HIGH);
digitalWrite(groupD,HIGH);
warning7 = true;
warning6 = false;
M1stop();
ST11stop();
//Serial.println("ST11 stoppped line 498"); //debugging
ST12stop();
route = route + 1;
//Serial.println("7R & 6N");//debugging
}
//bool pts6routeNstation = true; // possible routes for 6 points, given other circumstances
//bool pts6routeNX = false; // normal - crossing route from main to/from yard
//bool pts6routeSTM = false; // station to/from main
//bool pts6routeyardSTN = false; // station to/from yard
//bool pts6Normal = false;
//bool pts6Reverse = false;
if (pts9Normal == true) {
digitalWrite(pts9N, LOW);
warning9 = false;
} else {
digitalWrite(pts9N, HIGH);
warning9 = true;
}
if (pts10Normal == true) {
digitalWrite(pts10N, LOW);
warning10 = false;
} else {
digitalWrite(pts10N, HIGH);
warning10 = true;
}
if (pts11Normal == true) {
digitalWrite(pts11N, LOW);
warning11 = false;
} else {
digitalWrite(pts11N, HIGH);
warning11 = true;
}
if (pts12Normal == true) {
digitalWrite(pts12N, LOW);
warning12 = false;
} else {
digitalWrite(pts12N, HIGH);
warning12 = true;
}
// currentMillis = millis();
//
// points lever alert warning light
//
if ((intransit6==true)||(intransit5==true)||(intransit7==true)||(intransit9==true)||(intransit10==true)||(intransit11==true)||(intransit12==true)) digitalWrite(intransitLED,LOW);
if ((intransit5==false)&&(intransit6==false)) digitalWrite(intransitLED,HIGH);
if ((warning5 == false) && (warning6 == false) && (warning7 == false) && (warning9 == false) && (warning10 == false) && (warning11 == false) && (warning12 == false)) {
//turn warning off
leveralerton = false;
} else leveralerton = true;
if (leveralerton==true){ //just turn it on steady
//Serial.println("lever alert is on"); // debugging
digitalWrite(PLRW, LOW);
}
else digitalWrite(PLRW, HIGH);
//
// 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, LOW);
} else {
digitalWrite(pts5TC, HIGH);
}
if (block6occ == true) {
digitalWrite(pts6TC, LOW);
} else {
digitalWrite(pts6TC, HIGH);
}
if (block7occ == true) {
digitalWrite(pts7TC, LOW);
} else {
digitalWrite(pts7TC, HIGH);
}
//
// 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
// add in section below such that if a switch is set to stop, then the respective signals
// will display stop. 15/1/24
if (ST1113stopVal == true) {
ST11stop();
ST13stop();
}
if (ST12stopVal == true){
ST12stop();
}
if (M1stopVal == true){
M1stop();
}
if (M2stopVal == true){
M2stop();
}
if (emergstop == true) {
M1stop();
M2stop();
ST12stop();
ST11stop();
ST13stop();
}
else {
//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
// route 1: 6N and 7N (route value 0 or 100)
// 1111111111111111111111111111111111111111111111111111
if (route == 0 || route == 100) {
//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();
}
}
if(ST1113stopVal == true){
ST11stop();
}
if (ST12stopVal == true){
ST12stop();
}
//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
// 2222222222222222222222222222222222222222222222222222222222
// route 2 - points 5NorR, 6R, 7R
if (route == 11 || route == 111) {
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(); // <- this appears to be erroneous 14/1/24
//Serial.println("M2 stopped by line 676"); //debugging
}
//now check M2 stop value and set signal accordingly
if (M2stopVal == false && ST1113stopVal == true) {
ST11stop();
M2turnout();
//ST12 is set to proceed
} else {
// set ST12 to clear here and ST11 to stop
M2stop();
//ST11stop(); // <- this appears to be erroneous 14/1/24
//Serial.println("ST11 stoppped line 697"); //debugging
}
} //<- this is the end of route 2 occupancy and signal setting check
} //<- this is the end of "route 2" subroutine
//333333333333333333333333333333333333333333333333333333333333333333333333333
// route 3 - points 5N, 6R, 7N
if (route == 10) {
// Serial.println("route 3 - 5N, 6R, 7N"); //debugging
//route 1 set
ST11stop(); //it's a given that this one will be at stop
if (block6occ == true || block5occ == true) {
ST13stop();
ST12stop();
} else {
// Serial.println("checking switch ST1113 and ST12"); // debugging
//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
}
if (ST1113stopVal == true) {
ST13stop();
}
//now check ST12 stop value and set signal accordingly
if (ST12stopVal == false) {
ST13stop();
//ST12 is set to proceed
ST12yard1();
} else {
ST12stop();
}
if (ST12stopVal == true) {
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
//444444444444444444444444444444444444444444444444444444444444444444
// route 4 - points 5N, 6N, 7R
if (route == 1) {
//route 4 set
// 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(); // <- this appears to be erroneous 14/1/23
}
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true) {
ST13stop();
//ST12 is set to proceed
M2yard1();
}
/*else {
M2stop();
Serial.println("M2 stopped by line 764"); // debugging
ST13stop();
Serial.println("ST13 set to stop by line 783");//debugging
} */ //this group from else is deemed erroneous 15/1/24. Simulated OK as remarked out.
} //<- this is the end of block 6 occupancy and signal setting check
} //<- this is the end of "route 4" subroutine
//55555555555555555555555555555555555555555555555555555555555555
// route 5 - points 5R, 6N,7R
if (route==101) {
// 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(); // <- this line appears to be erroneous 14/1/24
//Serial.println("M2 stopped by line 796"); // debugging
} */ //this group from else remarked out 15/1/24
//now check M2 stop value and set signal accordingly
//clockwise:
if (M2stopVal == false && ST1113stopVal == true) {
ST13stop();
//ST12 is set to proceed
M2yard2();
}
/* else {
M2stop();
Serial.println("M2 stopped by line 807"); // debugging
ST13stop();
Serial.println("ST13 stopped by line 828"); //debugging
} */ // remarked out from else, seems erroneous from simulation 15/1/24
} //<- this is the end of block 6 occupancy and signal setting check
} //<- this is the end of "route 5" subroutine
//666666666666666666666666666666666666666666666666666666
// route 6 - points 5R, 6R, 7N
if (route==110) {
// 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();
} 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
ST12yard2();
} 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, 3 and 6
} //<- this is the end of "route 6" subroutine
} // <- this is the end of the "else" from emergency stop being active or not
} // <- this is the end of the main loop void
// ##########################################################################################
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;
} else M1stopVal = true;
if (digitalRead(M2proceed) == LOW) {
M2stopVal = false;
} else M2stopVal = true;
if (digitalRead(ST1113proceed) == LOW) {
ST1113stopVal = false;
} else ST1113stopVal = true;
if (digitalRead(ST12proceed) == LOW) {
ST12stopVal = false; // the switch is set to proceed - therefore, not at stop
} 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;
// #5 points:
if (digitalRead(pts5Ndet) == LOW) pts5Normal = true;
else (pts5Normal = false);
if (digitalRead(pts5Rdet) == LOW) pts5Reverse = true;
else (pts5Reverse = false);
// #6 points:
if (digitalRead(pts6Ndet) == LOW) {
pts6Normal = true;
} else pts6Normal = false;
if (digitalRead(pts6Rdet) == LOW) {
pts6Reverse = true;
} else pts6Reverse = false;
// #7 points:
if (digitalRead(pts7Ndet) == LOW) {
pts7Normal = true;
} else pts7Normal = false;
if (digitalRead(pts7Rdet) == LOW) {
pts7Reverse = true;
} else pts7Reverse = false;
if (digitalRead(pts9normal) == LOW) { // points 9-12 are only checked if normal, since there are no signals for these at this time of creating the code
pts9Normal = true;
} else pts9Normal = false;
if (digitalRead(pts10normal) == LOW) {
pts10Normal = true;
} else pts10Normal = false;
if (digitalRead(pts11normal) == LOW) {
pts11Normal = true;
} else pts11Normal = false;
if (digitalRead(pts12normal) == LOW) {
pts12Normal = true;
} else pts12Normal = false;
//Serial.println("end of reading inputs"); // debugging
} // <- end of reading inputs void
// ##########################################################################################
//##### signal indications:
// added short delay to display each aspect, for switch debounce and rapid changing switches by signaller
void M1stop() {
digitalWrite(M1red, LOW);
digitalWrite(M1yel, HIGH);
digitalWrite(M1grn, HIGH);
//Serial.println("M1 stop"); // debugging
delay (displaydelay);
}
void M1caution() {
digitalWrite(M1red, HIGH);
digitalWrite(M1yel, LOW);
digitalWrite(M1grn, HIGH);
//Serial.println("M1 caution"); // debugging
delay (displaydelay);
}
void M1clear() {
digitalWrite(M1red, HIGH);
digitalWrite(M1yel, HIGH);
digitalWrite(M1grn, LOW);
//Serial.println("M1 clear"); // debugging
delay (displaydelay);
}
void M2stop() {
digitalWrite(M2red, LOW);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, HIGH);
//Serial.println("M2 stop"); // debugging
delay (displaydelay);
}
void M2caution() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, LOW);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, HIGH);
//Serial.println("M2 caution"); // debugging
delay (displaydelay);
}
void M2clear() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, LOW);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, HIGH);
//Serial.println("M1 clear"); // debugging
delay (displaydelay);
}
void M2turnout() {
// for turnouts and yard routes, red lamp/marker light will activate via diode gate within signal head
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, LOW);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, HIGH);
//Serial.println("M2 turnout "); // debugging
delay (displaydelay);
}
void M2yard1() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, LOW);
digitalWrite(M2y2, HIGH);
//Serial.println("M2 yard 1 "); // debugging
delay (displaydelay);
}
void M2yard2() {
digitalWrite(M2red, HIGH);
digitalWrite(M2yel, HIGH);
digitalWrite(M2grn, HIGH);
digitalWrite(M2TO, HIGH);
digitalWrite(M2y1, HIGH);
digitalWrite(M2y2, LOW);
//Serial.println("M2 yard 2 "); // debugging
delay (displaydelay);
}
void ST11stop() {
digitalWrite(ST11red, LOW);
digitalWrite(ST11yel, HIGH);
digitalWrite(ST11grn, HIGH);
digitalWrite(ST11TO, HIGH);
//Serial.println("ST11 stop"); // debugging
delay (displaydelay);
}
void ST11caution() {
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, LOW);
digitalWrite(ST11grn, HIGH);
digitalWrite(ST11TO, HIGH);
//Serial.println("ST11 caution"); // debugging
delay (displaydelay);
}
void ST11clear() {
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, HIGH);
digitalWrite(ST11grn, LOW);
digitalWrite(ST11TO, HIGH);
// Serial.println("ST11 clear"); // debugging
delay (displaydelay);
}
void ST11turnout() {
digitalWrite(ST11red, HIGH);
digitalWrite(ST11yel, HIGH);
digitalWrite(ST11grn, HIGH);
digitalWrite(ST11TO, LOW);
//Serial.println(" ST11 turnout "); // debugging
delay (displaydelay);
}
void ST12stop() { // semaphore signal
digitalWrite(ST12red, LOW); // also guard's indicator 4/1/24
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, HIGH);
//Serial.println("ST12 stop"); // debugging
delay (displaydelay);
}
void ST12caution() { // semaphore signal
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, LOW);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, HIGH);
//Serial.println(" ST12 caution"); // debugging
delay (displaydelay);
}
void ST12clear() { // semaphore signal
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, LOW);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, HIGH);
// Serial.println(" ST12 clear"); // debugging
delay (displaydelay);
}
void ST12yard1() { // semaphore signal
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, LOW);
digitalWrite(ST12y2, HIGH);
//Serial.println("ST12 yard 1"); // debugging
delay (displaydelay);
}
void ST12yard2() { // semaphore signal
digitalWrite(ST12red, HIGH);
digitalWrite(ST12yel, HIGH);
digitalWrite(ST12grn, HIGH);
digitalWrite(ST12y1, HIGH);
digitalWrite(ST12y2, LOW);
//Serial.println(" ST12 yard 2"); // debugging
delay (displaydelay);
}
void ST13stop() {
digitalWrite(ST13red, LOW);
digitalWrite(ST13yelM, HIGH);
digitalWrite(ST13yelS, HIGH);
//Serial.println("ST13 stop"); // debugging
delay (displaydelay);
}
void ST13main() {
digitalWrite(ST13red, HIGH);
digitalWrite(ST13yelM, LOW);
digitalWrite(ST13yelS, HIGH);
// Serial.println("ST13 main"); // debugging
delay (displaydelay);
}
void ST13station() {
digitalWrite(ST13red, HIGH);
digitalWrite(ST13yelM, HIGH);
digitalWrite(ST13yelS, LOW);
//Serial.println("ST13 station"); // debugging
delay (displaydelay);
}
void points7NormalSignals() {
// common for route 1 and 3
if (M1stopVal == true){
M1stop();
}
if (M2stopVal == true){
M2stop();
}
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();
// Serial.println("M2 stopped by line 1123"); // debugging
if (C2nextstop == true) {
// Set M1 to caution
M1caution();
} else {
// set M1 to clear
M1clear();
}
}
if (M2stopVal == false) {
// now check opposite direction etc
M1stop();
// Serial.println("M2 stopVal is false");//debugging
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
}