//
// Wascoe Siding Loco Points interlocking
// R. Parnell 2019
//
// V10 - slow serial communication speed down to improve reliability and reduce false data causing issues
//
// Version 8 - 30/7/21. Reorganised loco track circuit occupancy into a single void to help with debounce issues which may be causing breif activation of loco points.
// Work on a "caution" aspect to display for a few seconds, following a block occupancy. Red -> yellow -> green instead of Red -> green.
// - after block becomes unoccupied, check millis value (Arduino timer)
// - add period of time for "caution" to millis value {endtime = millis value + caution value
// - if signal setting is clear, then show "caution" instead, until entdtime millis value is greater than current millis value
// - "<pointsfailed>" changed to "<pointsfailed7>" to help distance the text from <pointsnotfailed> 7/11/21
//
// Version 7 - March 2021. Ensure signals are red before changing points. Can defeat programming by quickly pressing buttons/switches.
// Phantom activation of loco departure track circuit. To debug.
// Changing points - they keep attempting to change after successfully having changed over. To debug.
//
//
// Version 6 - 6/12/20. When points change, it keeps trying to change them for 2 or 3 cycles after they have successfully changed over.
// Added short delays in serial data in case there is a backlog of requests to change points.
// increased point detection to 2 seconds from 1.5 seconds
// reduced block occupancy delay from 5 seconds to 3.5 seconds
//
//
// Version 5 - 28/11/20. Set "local" panel mimic to not flash points during transit, as this also operates the points motor and causes a pulsating motor operation.
// added 1 second delay to loco track circuit occupancy to assist with debounce
//
// Version 4- 25/11/20. Hopefully fixed erroneous signal change issue
// monitored serial data and found regular corruption.
// It appears that a random "corrupt" word became equal to a valid word
// ie: "setACWclear" was corrupted to "setclear" which was also valid.
// Data words changed to more unique words that are impossible to truncate to a valid word.
//
// Version 3- commenced 13/11/20
// *Increased points operation time period to 12 seconds to suit new, slower motor
// *Added a flashing mimic diagram indication during the 12 second operation to show
// that something is acutually happening
//
// Version 2 - commenced 25/7/20 to remove a couple of bugs:
// *Random glitch of S2 momentary clearing, then returning to required state.
// *Signal switch set to stop during occupancy of block - currently flicks back to previous state
//
// Uses Arduino Mega 2560 R3. Idential programming for local and remote units.
// An input pin determines what section of programming to operate on - local or remote.
//
// With contributed ideas and
// suggestions from various Wascoe Siding members during discussions throughout 2019.
//
// final testing and debugging from 22/10/19
//
// Note: uses Serial port1, not Serial port 0.
// pin 18/19 not 0/1 as serial port 0 is also the USB comms port and
// serial 1 can pick up comms at any time.
// If data coming in on Serial 0 when powered up, the sketch
// halts indefinitely as it expects the USB port to be talking to it.
// Aruidno Mega 2560 limitation.
// define outputs
// all outputs at signal box (remote end) are active LOW to suit external switching
// all outputs at loco (local end) are active HIGH to suit relay modules
// global variables/inputs/outputs listed here:
int SIG2red = 24; // signal 2 red = pin D24
int SIG2yel = 25; // signal 2 yelow = pin D25
int SIG3grn = 27; // signal 3 green = pin D27
int SIG3yel = 29; // signal 3 yelow = pin D29
int SIG3red = 31; // signal 3 red = pin D31
int SIG1grn = 33; // signal 1 green = pin D33
int SIG1yel = 35; // signal 1 yeLOW = pin D35
int SIG1red = 37; // signal 1 red = pin D37
int SIG1MN = 39; // signal 1 MAIN route ind = pin D39
int SIG1LOCO = 41; // signal 1 LOCO route ind = pin D41
int pointN = 43; // points Normal indicator = pin D43
int pointR = 45; // points Reverse indicator = pin D45
int LOCAL = 47; // local control mode = D47
int REMOTE = 49; // Remote control mode = D49
int blockocc = 51; // block occupancy indicator = pin D51
int emergSTOP = 53; // emergency STOp indicator = pin D53
int locotrack = 22; // loco track circuit occupancy
int ptsfailed = 23; // points failed indicator
int SWstopval = 1000; // STOP signal selector switch on panel
int setlocal = A11; // jumper to select either local or remote
int setremote = A12; // jumper to select either local or remote
//int localRX = A14; // used to validate local data coming in
//int remoteRX = A15; // used to validata remote data coming in
int SWITCHpointsN = A4; // switch input points Normal A4
int SWITCHpointsR = A5; // switch input points reverse A5
int SWITCHanticlear = A6; // switch inputs for signal indications clockwise and anticlockwise
int SWTICHanticaution = A7;
int SWITCHstop = A8;
int SWITCHcwcaution = A9;
int SWITCHclear = A10;
int setlocalval = 1000; // set input as inactive (LOW)
int setremoteval = 1000; // set input as inactive (LOW)
int Rxdata = false; //global variable to determine if data is being received. Zero = no, 1 = yes
int dt = 3000; // set test time of each lamp (mS), reduced for debugging
const byte numChars = 32;
char receivedChars[numChars];
int newData = false;
int pointsREVERSE = false;
int pointsNORMAL = false;
int datacount = 0;
int pointsFAILED = false;
int pointsNval = 1000;
int pointsRval = 1000;
int stoptime = 0;
int sSSWstopval = 1000;
int pointsdetectN = A2;
int pointsdetectR = A3;
int zdatacount = 0;
int SSWstopval = 1000; // set switch value to high
int zzstop = 0; // time counter for switch being at stop
int locotrackcircuitval = 1000; // put here 30/7/21
int locotrackcct = A13; // switch inputs for signal indications clockwise and anticlockwise
int blockstatus = A0;
int SWITCHemergSTOP = A1;
// for setting signal to "caution" after the block has become unoccupied - if signal is set to full clear
int blockwasoccupied = false; //
unsigned long startMillis; // for starting countdown after blockwas occupied
unsigned long cautiontimer = 7000; // time period for countdown
unsigned long currentMillis; // what will be the current value to compare countdown to
//#########################
void setup() {
// Loco points signal controller
// March 2019
// R. Parnell
}
//#########################
void loop() {
Serial1.begin(2400); // to talk to other unit via wire link. Changed to 2400 from 9600 21/2/22
Serial.begin(9600); // to talk to USB port for debugging
// Serial11.begin(9600);
// Serial1.println("Start - setting up. 13/6/19.");
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
// Common to both local and remote units - define output pins as follows:
pinMode(SIG2red, OUTPUT);
pinMode(SIG2yel, OUTPUT);
pinMode(SIG3red, OUTPUT);
pinMode(SIG3yel, OUTPUT);
pinMode(SIG3grn, OUTPUT);
pinMode(SIG1red, OUTPUT);
pinMode(SIG1yel, OUTPUT);
pinMode(SIG1grn, OUTPUT);
pinMode(SIG1MN, OUTPUT);
pinMode(SIG1LOCO, OUTPUT);
pinMode(pointN, OUTPUT);
pinMode(pointR, OUTPUT);
pinMode(LOCAL, OUTPUT);
pinMode(REMOTE, OUTPUT);
pinMode(blockocc, OUTPUT);
pinMode(emergSTOP, OUTPUT);
pinMode(locotrack, OUTPUT);
pinMode(ptsfailed, OUTPUT); // points failure
//check for either local or remote mode. Display indicator and set variable
delay (300);
determinelocalremote();
// if neither local or remote, then oscillate between the indicators until such time as something is set
// Can proceed if only 1 local or remote input is HIGH.
//once local or remote is set, do the respective loop for that operating mode
// turn all outputs off
// DO THIS AFTER DETERMINING LOCAL OR REMOTE UNIT as opposite active output states for local and remote
if (setremoteval < 300) {
// I am the remote (signal box) end
// turn off all outputs for signal box end
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, LOW);
digitalWrite(pointN, LOW);
digitalWrite(pointR, LOW);
digitalWrite(LOCAL, LOW);
digitalWrite(REMOTE, LOW);
digitalWrite(blockocc, LOW);
digitalWrite(emergSTOP, LOW);
digitalWrite(ptsfailed, LOW); // points failure
digitalWrite(locotrack, LOW);
Serial1.println("testing each signal box lamp output");
delay (250);
Testremotelamps(); // run through test lamp sequencer
}
if (setlocalval < 300) {
// I am the local end
// turn off all outputs for local end
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
digitalWrite(pointN, HIGH);
digitalWrite(pointR, HIGH);
digitalWrite(LOCAL, HIGH);
digitalWrite(REMOTE, HIGH);
digitalWrite(blockocc, HIGH);
digitalWrite(emergSTOP, HIGH);
digitalWrite(ptsfailed, HIGH); // points failure
digitalWrite(locotrack, HIGH);
Serial1.println("testing each LOCAL lamp output");
delay (250);
Testlamps();
}
//now all signals are at stop, wait 5 seconds then set points for main
// Serial1.println("all signals stop after testing lamps");
//ALLRED();
if (setlocalval < 300) digitalWrite(pointN, HIGH); // set points to normal in case they are not already
delay (4000); //remarked out to save time during debugging
//Serial1.begin(9600); remarked out 21/2/22 since serial link speed is already established.
if (setlocalval < 300 ) goto Localmodeloop;
if (setremoteval < 300) goto Remotemodeloop;
// ###################################
/// ### end of initialisation ###
/// ### end of initialisation ###
/// ### end of initialisation ###
// ###################################
// LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL
//
// # #
// # ### ### ### #
// # # # # # #
// # # # # ##### #
// # # # # # # #
// ##### ### ### #### #
//
// LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL LOCAL start
Localmodeloop: // LOCAL MODE LOOP START ###################
// localmodeloop should only be run once, then carry on through localmodeloop2 indefinitely.
ALLRED();
digitalWrite(SWITCHstop, INPUT_PULLUP);
// check for red signal setting. Loop through until it has been set red for 5 seconds
//Serial1.println ("I am running the local mode loop....."); // debugging
stoptime = 0;
SSWITCHSTOP:
// Serial.println ("SSWITCHSTOP loop"); // debugging
SSWstopval = analogRead(SWITCHstop); // read the input status
delay (15);
if (SSWstopval > 300) {
goto SSWITCHSTOP;
stoptime = 0;
}
if (SSWstopval < 300) stoptime = stoptime + 1;
if (stoptime == 89) goto localmodeloop2;
// Serial1.println ("I am in the first part of local mode loop waiting for switch to be set to stop....."); // debugging
goto SSWITCHSTOP;
// this section in localmodeloop above working OK 11/10/19
// the above section runs ONCE, then enters localmodeloop2 indefinitely...
//#######################################################################################################################################
localmodeloop2: // ##############
// this is the main "local mode" loop which runs indefinietly once started
//Serial.println ("I am in localmodeloop2");//debugging
digitalWrite(LOCAL, LOW); //turn Local output on (green LED on front cabinet door) labelled "NORMAL"
checkcriticalinputs(); // check critical inputs
receiveremotedata(); //
decodeREMOTEdata(); // checks data loop from other end and sets REMOTE LED and input as required
// a loop withing decodeREMOTEdata() clycles through until RXdata is lost
// Serial1.println ("I have checked and decoded any remote data"); //debugging
zdatacount = 0; // sets number of times Rxdata has been false
Rxdataloop:
if (Rxdata == false) zdatacount = zdatacount + 1;
if (zdatacount < 90) Rxdata = true; //value increased to 90 from 50 7/11/21
if (zdatacount == 90) Rxdata = false; //value increased to 90 from 50 7/11/21
if (Rxdata == true) {
// then don't check local switches. Continue to act on incoming data
// Serial.println("Incoming data is TRUE - I'm acting upon incoming data");//debugging
checkcriticalinputs(); // check critical inputs
receiveremotedata();
decodeREMOTEdata();
}
if (zdatacount < 50) goto Rxdataloop; //loop back while ever data is coming in
if (Rxdata == false) {
// if false, check signal switch to be at stop for 5 seconds, then check switches
stoptime = 0;
TIMEatSTOP:
sSSWstopval = analogRead(SWITCHstop); // read the input status
delay (15);
//check critical inputs in here
//check for incoming data. If data incoming, then reset the STOP time and act on data
checkcriticalinputs(); // check critical inputs
receiveremotedata();
decodeREMOTEdata();
//Serial1.println("Stoptime loop counter (up to 50)");//debugging
//Serial1.println(stoptime);//debugging
//Serial1.println ("switch at stop time not elapsed and no Rx data. Looping through many times"); // debugging
if (sSSWstopval > 300 && Rxdata == false) goto TIMEatSTOP; // if swtich is not at stop, keep checking
if (sSSWstopval < 300 && Rxdata == false) stoptime = stoptime + 1; // not that it is at stop, count time
if (stoptime < 50 && Rxdata == false) goto TIMEatSTOP; // if time not elapsed, go back and wait
if (Rxdata == true) goto Endofsubroutine;
//Serial.println ("STOPPED for required time, now check switches");//debugging
// 11/10/19 dinner
// at this point, data is not coming in and switch has been at stop for required time
// now check switches continuously and act upon them.
// if signal switch remains at stop for 5 seconds during these checks, then check for incoming data and get out of the loop
NoActivityLoop:
delay (10);
// Serial.println("I'm in the no data coming in loop - getting out by data coming in, checking switches. then 5 seconds at stop");//debugging
// Serial.println("zzstop value:");//debugging
// Serial.println(zzstop);//debugging
//insert routine to check points button switches here. If not pressed, then check other switches 17/11/19. Fixed 17/11/19.
Onlyonebutton:
int SWpointsNval = 1000;
int SWpointsRval = 1000;
SWpointsNval = analogRead(SWITCHpointsN);
SWpointsRval = analogRead(SWITCHpointsR);
if (SWpointsNval < 300 && SWpointsRval < 300) goto Onlyonebutton; // if both points buttons are active, then ignore them until only one is active
if (SWpointsNval < 300) {
// Serial.println("Points NORMAL button has been pressed"); //debugging
POINTSnormal(); // points N switch is active, go and set them to Normal
stoptime = 0;
zzstop = 0;
}
if (SWpointsRval < 300) {
// Serial.println("Points REVERSE button has been pressed"); //debugging
POINTSreverse(); // points R switch is active, go and set them to Reverse
stoptime = 0;
zzstop = 0;
}
checkcriticalinputs(); // check critical inputs
sSSWstopval = analogRead(SWITCHstop); // read the input status
if (sSSWstopval > 300) {
// Serial.println(" I'm in the NoActivityLoop. Apparently the signal switch is not at stop");//debugging
checkswitches(); // if switch is not at stop, go and check other switches and act upon setting
goto NoActivityLoop; // since the switches are in use, keep checking them
}
if (sSSWstopval <=300 ) ALLSTOP(); // added 25/3/22
// now see if any data is coming in
receiveremotedata(); //
decodeREMOTEdata();
// zzstop = zzstop - 1; //decrement counter as enough time has elapsed at stop
// }
// if data is coming in, wait for signal switch to be at stop for 5 seconds then go and act on data
if (Rxdata == false) goto NoActivityLoop;
// Serial1.println ("we now have data and switch still has been at stop for required time. Check incoming data again");//debugging
Endofsubroutine:
delay (1); // do nothing as I have jumped to the end
Serial1.println("End of local mode loop subroutine"); //debugging
}
goto localmodeloop2;
// ## end of loco mode loop ## @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// ## NOTE: outputs are ACTIVE LOW for remote end
// ## start of remote mode loop ##
// ## NOTE: outputs are ACTIVE HIGH for local end
//***************************************************************************************
// ############################################
// ####
// #### Remote mode loop ####
// ####
// ############################################
// this is happening at the remote (signal box) end
// check switches and send switch state to other end
// listen for incoming data and act
// if no data incoming, then display alert
Remotemodeloop:
digitalWrite(REMOTE, HIGH);
Serial1.println ("I am running the remote mode loop.....");
checkremoteswitches(); // check signal box switches
receiveLOCALdata(); // receive and decode data from local end
decodeLOCALdata();
if (Rxdata == false) zzstop = zzstop + 1;
if (Rxdata == true) zzstop = 0;
if (zzstop == 80) {
// there is no data coming form local end, flash emerg, points fail, local and remote LEDs
digitalWrite(REMOTE, HIGH);
digitalWrite(LOCAL, HIGH);
digitalWrite(emergSTOP, HIGH);
digitalWrite(ptsfailed, HIGH);
zzstop = zzstop - 1;
delay (80);
digitalWrite(REMOTE, LOW);
digitalWrite(LOCAL, LOW);
digitalWrite(emergSTOP, LOW);
digitalWrite(ptsfailed, LOW);
delay (80);
digitalWrite(LOCAL, HIGH);
}
// check signal box emergency switch input
// Send switch setting data
//decode data and display accordingly
goto Remotemodeloop;
}
//########################################################################################################
//########################################################################################################
void checkcriticalinputs() {
// note: critical inputs can only occur from local unit end
//Serial.println ("I am checking criticalinputs subroutine");// debugging
POINTSnotset(); // check that points are set one way or the other
// removed to become global variable 30/7/21. int locotrackcct = A13; // switch inputs for signal indications clockwise and anticlockwise
pinMode(locotrackcct, INPUT);
pinMode(SWITCHemergSTOP, INPUT);
pinMode(blockstatus, INPUT);
digitalWrite(SWITCHemergSTOP, INPUT_PULLUP); // set pull-up on analog pin
digitalWrite(blockstatus, INPUT_PULLUP);
digitalWrite(locotrackcct, INPUT_PULLUP);
int blockval = 1000; // set input as inactive
int emergval = 1000; // set emergency input as inactive
// int locotrackcircuitval = 1000; removed 30/7/21 to universal variable
//locotrackcircuitval = analogRead(locotrackcct); // read input
locotrackocc(); //check loco track circuit occupancy
blockval = analogRead(blockstatus); // read input status
emergval = analogRead(SWITCHemergSTOP); // read input
// all working above this remark 16/6/19
if (blockval < 300) {
digitalWrite(blockocc, LOW);
ALLSTOP();
//Serial.println("block is occupied"); // debugging 25/3/22
BLOCKLOOP:
Serial1.println("<blockocc1>");
//locotrackcircuitval = analogRead(locotrackcct); // read input
locotrackocc(); //check loco track circuit occupancy
blockval = analogRead(blockstatus); // read input status
emergval = analogRead(SWITCHemergSTOP); // read input
if (emergval < 300) {
Serial1.println("<emergstop1>");
digitalWrite(emergSTOP, LOW);
}
if (emergval > 300) {
Serial1.println("<emergstop0>");
digitalWrite(emergSTOP, HIGH);
}
if (blockval < 300) goto BLOCKLOOP;
if (emergval < 300) goto BLOCKLOOP;
for (int i = 0; i <= 10; i++) {
safetydelay();
// block has now become unoccupied
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
// locotrackcircuitval = analogRead(locotrackcct); // read input
// if (locotrackcircuitval < 300) LOCOOCCUPIED();
// if (locotrackcircuitval > 300) LOCOUNOCCUPIED();
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second
locotrackocc(); //check loco track circuit occupancy
blockwasoccupied = true; // flag that something has occupied the block - inserted here 25/3/22
startMillis = millis(); // read millis value for "caution" timer - inserted here 25/3/22
Serial1.println("<blockocc0>");
//30/7/21
digitalWrite(blockocc, HIGH);
// now it is activated, wait for it to be inactive.
// once inactive, wait 5 seconds.
// during this, check emergency input and show status
}
if (blockval > 300) {
Serial1.println("<blockocc0>");
digitalWrite(blockocc, HIGH);
}
if (emergval < 300) {
digitalWrite(emergSTOP, LOW);
ALLSTOP();
ELOOP:
Serial1.println("<emergstop>");
locotrackocc(); //check loco track circuit occupancy
blockval = analogRead(blockstatus); // read input status
emergval = analogRead(SWITCHemergSTOP); // read input
if (blockval < 300) {
Serial1.println("<blockocc1>");
digitalWrite(blockocc, LOW);
// receivedChars = "setstop";
}
if (blockval > 300) {
Serial1.println("<blockocc0>");
digitalWrite(blockocc, HIGH);
}
if (emergval < 300) goto ELOOP;
if (blockval < 300) goto ELOOP;
for (int i = 0; i <= 7; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 7; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 7; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 7; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
for (int i = 0; i <= 7; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 1 second to allow motor to operate
locotrackocc(); //check loco track circuit occupancy
// loco occupancy values reduced to 300 from 500 - 8/3/21 to prevent possible false triggering.
// time delay after block occupancy reduced to 3.5 seconds (5 x [7x10ms loops]) after feedback from board 6/12/20
Serial1.println("<emergstop0>");
// now it is activated, wait for it to be inactive.
// once inactive, wait 5 seconds.
// during this, check block occupancy and show status
}
if (emergval > 300) {
Serial1.println("<emergstop0>");
}
}
// end of checking critical inputs. This routine working fine 16/6/19
//#########################
// outputs change output status only. Serial1 data is sent from either local or remote mode loops.
void LOCOOCCUPIED() {
Serial1.println("<locoocc1>");
digitalWrite(locotrack, LOW); // turn on LOCO T/C on local panel
delay (1000); //added 28/11/20
}
void LOCOUNOCCUPIED() {
Serial1.println("<locooccupied0>");
digitalWrite(locotrack, HIGH); // turn off LOCO T/C on local panel
}
void EMERGSTOP() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<emergstop1>"); // send "emergstop" to remote
}
//##########################################
void ALLRED() { // note - ALLRED for when block occupied or points operating
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<allstop1>"); // send message to remote
}
// #########################
void sigboxALLRED() { // as displayed in signal box
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, LOW);
}
//#########################
void ALLSTOP() { // all signals at stop as set by signal switch
ALLRED(); // the outputs are the same as ALLSTOP()
}
// #########################################
//
// ### # # ##### ### # # #### ##### ###
// # # # # # # # # # # #
// # ##### ### # ### #### # ###
// # # # # # # # # # #
// ### # # ##### ### # # # # ###
//
// #########################################
void POINTSnotset() { // Check points blade position. If not N or R, then emergency stop.
//Serial1.println ("I am running the checking points (pointsnotset subroutine)....."); // debugging
pinMode(pointsdetectN, INPUT);
pinMode(pointsdetectR, INPUT);
digitalWrite(pointsdetectN, INPUT_PULLUP); // set pull-up
digitalWrite(pointsdetectR, INPUT_PULLUP);
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points initial detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 2nd detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 3rd detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 4th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 5th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 6th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 7th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 8th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 9th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 10th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 11th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsNval > 300 && pointsRval > 300) {
POINTSFAIL();
safetydelay();
safetydelay();
// Serial.println("points 12th detect fail");//debugging
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
//allow signaller to try again since still failed
//
// after subroutine, go back to "POINTS" within this routine
int SWITCHpointsN = A4; // button switch input points Normal A4
int SWITCHpointsR = A5; // button switch input points reverse A5
pinMode(SWITCHpointsN, INPUT);
pinMode(SWITCHpointsR, INPUT);
digitalWrite(SWITCHpointsN, INPUT_PULLUP); // set pull-up
digitalWrite(SWITCHpointsR, INPUT_PULLUP);
int SWITCHpointsNval = 1000; // set input as inactive
int SWITCHpointsRval = 1000; // set input as inactive
POINTSFAIL();
FAILLOOP:
// Serial.println ("points failure - looping through until they are set");
// ploop:
Serial1.println ("<pointsfailed7>");
digitalWrite(pointR, HIGH);
digitalWrite(pointN, HIGH);
digitalWrite(ptsfailed, HIGH);
safetydelay();
Serial1.println ("<pointsnotfailed>");
// Serial.println ("turning off points fail lamp to flash it during failure");// turn off sigbox points failed lamp to "flash" it.
digitalWrite(ptsfailed, LOW);
safetydelay();
// now that points have failed, enable points control button and keep checking blades until sorted out
pointsNval = analogRead(pointsdetectN); // check points blades
pointsRval = analogRead(pointsdetectR);
SWITCHpointsNval = analogRead(SWITCHpointsN); // read the input status
SWITCHpointsRval = analogRead(SWITCHpointsR); // read the input status
if (SWITCHpointsNval < 300) {
digitalWrite(pointR, HIGH);
digitalWrite(pointN, LOW);
Serial1.println("<pointssetnormal>");
pointsNORMAL = true;
for (int i = 0; i <= 25; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 2.5 seconds to allow motor to operate
// 8/3/21 - the 2.5 second delay may not be relevant with slow motor operaion####
}
if (SWITCHpointsRval < 300) {
// 8/3/21 - this section operates point motor once blade has been detected one way or the other. Reconsider this. (Linked to mimic display?)
digitalWrite(pointN, HIGH);
digitalWrite(pointR, LOW);
Serial1.println("<pointssetreverse>");
pointsREVERSE = true;
for (int i = 0; i <= 25; i++) {
safetydelay();
} // loop through 100mS delay, flicking LED for a total of 2.5 seconds to allow motor to operate
}
if (pointsNval < 300) goto ENDFAILLOOP;
if (pointsRval < 300) goto ENDFAILLOOP;
goto FAILLOOP;
ENDFAILLOOP:
if (pointsNval < 300) {
digitalWrite(pointR, HIGH);
digitalWrite(pointN, LOW);
pointsREVERSE = false;
pointsNORMAL = true;
Serial1.println("<pointssetnormal>");
}
if (pointsRval < 300) {
digitalWrite(pointN, HIGH);
digitalWrite(pointR, LOW);
pointsREVERSE = true;
pointsNORMAL = false;
Serial1.println("<pointssetreverse>");
}
POINTSNOTFAILED();
Serial1.println("<pointsnotfailed>");
}
// end of checking for points failure - POINTSnotset()###################################
//#######################################################################
void POINTSFAIL() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
digitalWrite(pointN, HIGH); // as points have failed, turn off both route settings
digitalWrite(pointR, HIGH); // as points have failed, turn off both route settings
digitalWrite(blockocc, HIGH);
digitalWrite(emergSTOP, HIGH);
digitalWrite(ptsfailed, LOW); // points failure alert
// vloop:
Serial1.println("<pointsfailed7>"); // send to remote
pointsFAILED = true;
pointsREVERSE = false;
pointsNORMAL = false;
// Serial.println("Points have failed - please check. POINTSFAIL()");
}
void POINTSNOTFAILED() {
digitalWrite(emergSTOP, HIGH);
digitalWrite(ptsfailed, HIGH);
pointsFAILED = false;
Serial1.println("<pointsnotfailed>");
// Serial.println("points no longer failed"); //debugging
// do nothing else
}
// #########################################
// set points to normal, check points blade position then carry on.
void POINTSnormal() {
ALLRED(); // added 8/3/21
digitalWrite(pointR, HIGH);
digitalWrite(pointN, LOW);
// 13/11/20: insert flashing mimic diagram and 12 second delay here
// 28/11/20: removed local flashing of mimic as it is connected to the motor and pulsates it. Send command to flash signal box end only.
for (int i = 0; i <= 30; i++) {
safetydelay();
safetydelay();
// digitalWrite(pointN, HIGH); // removed 28/11/20
digitalWrite(emergSTOP, HIGH); // added 28/11/20 to falsh emergstop LED instead.
Serial1.println("<normaltransiton>");
safetydelay();
safetydelay();
// digitalWrite(pointN, LOW); // removed 28/11/20
digitalWrite(emergSTOP, LOW); // added 28/11/20
Serial1.println("<normaltransitoff>");
} // loop through 100mS delay, flicking mimic LEDs during motor operation for a total of 12 seconds
// end of modification 13/11/20
safetydelay();
Serial1.println("<pointssetnormal>");
pointsNORMAL = true;
// operate points, then check for point blade detection. Once detected that they have changed, carry on.
for (int i = 0; i <= 20; i++) {
safetydelay();
} // loop through 100mS delay 15 times, flicking LED for a total of 1.5 seconds to allow motor to operate
// loop increased to 20 times (2 seconds) 6/12/20, to help with slow motor operaion.
int pointsdetectN = A2;
int pointsdetectR = A3;
pinMode(pointsdetectN, INPUT);
pinMode(pointsdetectR, INPUT);
digitalWrite(pointsdetectN, INPUT_PULLUP); // set pull-up
digitalWrite(pointsdetectR, INPUT_PULLUP);
int pointsNval = 1000; // set input as inactive
int pointsRval = 1000; // set input as inactive
// check if blade has made it across. Loop for a short time period until it has made it.
// make provision to intervene if point
// blades don't make it over in reasonable time frame
POINTSN:
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsdetectN > 300) {
POINTSFAIL();
pointsREVERSE = false;
pointsNORMAL = false;
}
if (pointsdetectN < 300) {
// Serial1.println(" Points have been set NORMAL");
POINTSNOTFAILED();
// yloop:
Serial1.println("<pointsnotfailed>");
// receiveACK();
// decodeACK();
// if(RxACK == false) goto yloop; // loop until ack
pointsREVERSE = false;
pointsNORMAL = true;
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay 10 times, flicking LED for a total of 1 second to allow motor to operate
}
// 7/11/21: insert command to send message to signal box that points change is complete. Wait for acknowledgement
// of the message. Loop around until message is received. Once received, continue.
}
// #########################################
// set points to REVERSE, check points blade position then carry on.
void POINTSreverse() {
ALLRED(); // added 8/3/21
digitalWrite(pointR, LOW);
digitalWrite(pointN, HIGH);
// 13/11/20: insert flashing mimic diagram and 12 second delay here
// 28/11/20: removed local flashing of mimic as it is connected to the motor and pulsates it. Send command to flash signal box end only.
for (int i = 0; i <= 30; i++) {
safetydelay();
safetydelay();
// digitalWrite(pointR, HIGH); // removed 28/11/20. Added emergency stop lamp to flash at local panel only.
digitalWrite(emergSTOP, HIGH); // added 28/11/20
Serial1.println("<reversetransiton>");
safetydelay();
safetydelay();
// digitalWrite(pointR, LOW); // removed 28/11/20
digitalWrite(emergSTOP, LOW); // added 28/11/20 to flash emergstop LED instead.
Serial1.println("<reversetransitoff>");
} // loop through 100mS delay, flicking mimic LEDs during motor operation for a total of 12 seconds
// end of modification 13/11/20
safetydelay();
Serial1.println("<pointssetreverse>");
pointsREVERSE = true;
for (int i = 0; i <= 15; i++) {
safetydelay();
} // loop through 100mS delay 25 times, flicking LED for a total of 1.5 seconds to allow motor to operate
int pointsdetectN = A2;
int pointsdetectR = A3;
pinMode(pointsdetectN, INPUT);
pinMode(pointsdetectR, INPUT);
digitalWrite(pointsdetectN, INPUT_PULLUP); // set pull-up
digitalWrite(pointsdetectR, INPUT_PULLUP);
int pointsNval = 1000; // set input as inactive
int pointsRval = 1000; // set input as inactive
//pointsNval = analogRead(pointsdetectN); // check points blades
//pointsRval = analogRead(pointsdetectR);
// check if blade has made it across. Loop for a short time period until it has made it.
// make provision to intervene if point
// blades don't make it over in reasonable time frame
POINTSR:
pointsNval = analogRead(pointsdetectN); // read the input status
pointsRval = analogRead(pointsdetectR); // read the input status
if (pointsdetectR > 300) {
POINTSFAIL();
pointsREVERSE = false;
pointsNORMAL = false;
}
if (pointsdetectR < 300) {
// Serial.println(" Points have been set REVERSE");
POINTSNOTFAILED();
// aaloop:
Serial1.println("<pointsnotfailed1>");
// receiveACK();
// decodeACK();
// if(RxACK == false) goto aaloop; // loop until ack
pointsREVERSE = true;
pointsNORMAL = false;
for (int i = 0; i <= 10; i++) {
safetydelay();
} // loop through 100mS delay 10 times, flicking LED for a total of 1 second to allow motor to operate
}
// 7/11/21: insert command to send message to signal box that points change is complete. Wait for acknowledgement
// of the message. Loop around until message is received. Once received, continue.
}
//############################################
//
// ### ##### ### ##### # # ####
// # # # # # ## # # #
// ### # # # # # # # #
// # # # ### # # ## # #
// ### ##### #### ##### # # ####
//
//############################################
void clockwiseclear() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH); // loco departure signal
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH); // main line anticlockwise signal
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, LOW); // main line clockwise signal
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<clockwiseclear1>"); // send message to remote
}
//#########################
void sigboxclockwiseclear() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW); // loco departure signal
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW); // main line anticlockwise signal
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, HIGH); // main line clockwise signal
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, LOW);
}
//#########################
//#########################
void clockwisecaution() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<clockwisecaution1>"); // send message to remote
}
//###########################
void sigboxclockwisecaution() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, LOW);
}
//#########################
void clockwiseloco() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, LOW);
Serial1.println("<clockwiseloco1>"); // send message to remote
}
//#########################
void sigboxclockwiseloco() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, HIGH);
}
//#########################
void locodepart() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<locodepart>"); // send message to remote
}
//#########################
void sigboxlocodepart() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, LOW);
}
//#########################
void anticlockwiseclear() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<anticlockwiseclear2>"); // send message to remote
}
//#########################
void sigboxanticlockwiseclear() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, LOW);
}
//#########################
void anticlockwisecaution() {
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, HIGH);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, HIGH);
Serial1.println("<anticlockwisecaution2>"); // send message to remote
}
//#########################
void sigboxanticlockwisecaution() {
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, LOW);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, LOW);
}
//@@@@@@@@@@@@@@@@@@@ LOCAL unit - receive data from other end
//@@@@@@@@@@@@@@@@@@@@ check switch settings
void checkswitches() { // check physical switch inputs at local end only and act accordingly
// this routine only happens if data has been lost.
// to get out of this routine, switch for STOP must be held in this position for 5 seconds
int SWstopval = 1000; // set switch value to high
int CWcautionval = 1000;
int CWclearval = 1000;
int ACWcautionval = 1000;
int ACWclearval = 1000;
int SWpointsNval = 1000; // "normal" button
int SWpointsRval = 1000; // "reverse" button
digitalWrite(SWITCHpointsN, INPUT_PULLUP);
digitalWrite(SWITCHpointsR, INPUT_PULLUP);
digitalWrite(SWTICHanticaution, INPUT_PULLUP);
digitalWrite(SWITCHanticlear, INPUT_PULLUP);
digitalWrite(SWITCHstop, INPUT_PULLUP);
digitalWrite(SWITCHcwcaution, INPUT_PULLUP);
digitalWrite(SWITCHclear, INPUT_PULLUP);
SWITCHSTOP:
int switchisatstop = false;
SWstopval = analogRead(SWITCHstop); // read the input status
delay (5);
if (SWstopval < 300) {
ALLSTOP(); // if active, display indication
zzstop = zzstop + 1; // increment counter for switch being at stop for time period
// if any other button or switch is selected, counter resets
switchisatstop = true;
Onlyonebutton:
SWpointsNval = analogRead(SWITCHpointsN);
SWpointsRval = analogRead(SWITCHpointsR);
if (SWpointsNval < 300 && SWpointsRval < 300) goto Onlyonebutton; // if both points buttons are active, then ignore them until only one is active
if (SWpointsNval < 300) {
// Serial.println("Points NORMAL button has been pressed"); //debugging
POINTSnormal(); // points N switch is active, go and set them to Normal
stoptime = 0;
zzstop = 0;
}
if (SWpointsRval < 300) {
// Serial.println("Points REVERSE button has been pressed"); //debugging
POINTSreverse(); // points R switch is active, go and set them to Reverse
stoptime = 0;
zzstop = 0;
}
}
// if switch is at stop, goto end
if (SWstopval <= 300) goto ENDSWITCHCHECK;
if (pointsREVERSE == true) tofromloco(); // act on signal setting switches
if (pointsNORMAL == true) mainlinesignals(); // act on signal setting switches
ENDSWITCHCHECK:
delay (1); // effectively do nothing
}
void tofromloco() {
// Serial.println(" Checking switches for signals to/from loco");
int SWITCHanticlear = A6; // switch inputs for signal indications clockwise and anticlockwise
int SWTICHanticaution = A7;
int SWITCHcwcaution = A9;
int SWITCHclear = A10;
int CWcautionval = 1000;
int CWclearval = 1000;
int ACWcautionval = 1000;
int ACWclearval = 1000;
digitalWrite(SWITCHcwcaution, INPUT_PULLUP);
digitalWrite(SWITCHclear, INPUT_PULLUP);
digitalWrite(SWTICHanticaution, INPUT_PULLUP);
digitalWrite(SWITCHanticlear, INPUT_PULLUP);
CWcautionval = analogRead(SWITCHcwcaution); // read input
CWclearval = analogRead(SWITCHclear);
ACWcautionval = analogRead(SWTICHanticaution);
ACWclearval = analogRead(SWITCHanticlear);
if (CWcautionval < 300) {
clockwiseloco();
stoptime = 0;
zzstop = 0;
// Serial1.println("<clockwiseloco>"); // send data to other end
}
if (CWclearval < 300) {
clockwiseloco();
stoptime = 0;
zzstop = 0;
}
// if (CWclearval < 300) Serial1.println("<clockwiseloco>"); // send data to other end
if (ACWcautionval < 300) {
locodepart();
stoptime = 0;
zzstop = 0;
}
// if (ACWcautionval < 300) Serial1.println("<locodepart>"); // send data to other end
if (ACWclearval < 300) {
locodepart();
stoptime = 0;
zzstop = 0;
}
// if (ACWclearval < 300) Serial1.println("<locodepart>"); // send data to other end
// Serial1.println("I have checked to/from loco signal");
// delay (2000); // for debugging
}
void mainlinesignals() {
// this is where the local panel sets the signal indicatios
// bug 25/3/22 - not going back to stop when switch is selected. Needs block occupancy to work. [same for "tofromloco"]
// If a signal is set to clear, goes back to caution after a train passes, then clears a few seconds later - is working 25/3/22.
Serial.println("checking other signal switches"); // 25/3/22 debugging
digitalWrite(SWITCHstop, INPUT_PULLUP);
SWstopval = 1000;
int CWcautionval = 1000;
int CWclearval = 1000;
int ACWcautionval = 1000;
int ACWclearval = 1000;
int SWITCHanticlear = A6; // switch inputs for signal indications clockwise and anticlockwise
int SWTICHanticaution = A7;
int SWITCHcwcaution = A9;
int SWITCHclear = A10;
digitalWrite(SWITCHcwcaution, INPUT_PULLUP);
digitalWrite(SWITCHclear, INPUT_PULLUP);
digitalWrite(SWTICHanticaution, INPUT_PULLUP);
digitalWrite(SWITCHanticlear, INPUT_PULLUP);
SWstopval = analogRead(SWITCHstop); // read the input status
CWcautionval = analogRead(SWITCHcwcaution); // read input
CWclearval = analogRead(SWITCHclear);
ACWcautionval = analogRead(SWTICHanticaution);
ACWclearval = analogRead(SWITCHanticlear);
currentMillis = millis(); // added 25/3/22
if (currentMillis - startMillis >= cautiontimer){
blockwasoccupied = false; // since the time has elapsed, the block was not recently occupied
}
if (CWcautionval < 300) {
clockwisecaution();
stoptime = 0;
zzstop = 0;
}
if (CWclearval < 300) {
if (blockwasoccupied == true)clockwisecaution(); // 25/3/22. Code to set to caution if block has just been occupied
else {clockwiseclear();}
stoptime = 0;
zzstop = 0;
}
if (ACWcautionval < 300) {
anticlockwisecaution();
stoptime = 0;
zzstop = 0;
}
if (ACWclearval < 300) {
if (blockwasoccupied == true)anticlockwisecaution(); // 25/3/22. Code to set to caution if block has just been occupied
else {anticlockwiseclear();}
stoptime = 0;
zzstop = 0;
}
if (SWstopval <= 300) { // added 25/3/22
ALLSTOP();
delay (100);
}
}
//#########################
//@@@@@@@@@@@@@@@@@@@@ check switch settings
void checkremoteswitches() {// check physical switch inputs in signal box and act accordingly
delay (20); // added 6/12/20. Could be causing issues, especially when changing points at other end.
// only inputs to check are physical switches and emergency stop input,
// 8 all up
// Serial1.println("I am checking signal box switches routine");
int SWstopval = 1000; // set switch value to high
int CWcautionval = 1000;
int CWclearval = 1000;
int ACWcautionval = 1000;
int ACWclearval = 1000;
int sigboxemergstop = 1000;
int pointsnormal = 1000;
int pointsreverse = 1000;
int SWTICHanticaution = A7;
int SWITCHanticlear = A6;
int SWITCHstop = A8;
int SWITCHcwcaution = A9;
int SWITCHclear = A10;
int SWITCHsigboxemerg = A1;
int SWITCHsigboxnormal = A4;
int SWITCHsigboxreverse = A5;
digitalWrite(SWTICHanticaution, INPUT_PULLUP);
digitalWrite(SWITCHanticlear, INPUT_PULLUP);
digitalWrite(SWITCHstop, INPUT_PULLUP);
digitalWrite(SWITCHcwcaution, INPUT_PULLUP);
digitalWrite(SWITCHclear, INPUT_PULLUP);
digitalWrite(SWITCHsigboxemerg, INPUT_PULLUP);
digitalWrite(SWITCHsigboxnormal, INPUT_PULLUP);
digitalWrite(SWITCHsigboxreverse, INPUT_PULLUP);
CWcautionval = analogRead(SWITCHcwcaution); // read input
CWclearval = analogRead(SWITCHclear);
ACWcautionval = analogRead(SWTICHanticaution);
ACWclearval = analogRead(SWITCHanticlear);
SWstopval = analogRead(SWITCHstop);
sigboxemergstop = analogRead(SWITCHsigboxemerg);
pointsnormal = analogRead(SWITCHsigboxnormal);
pointsreverse = analogRead(SWITCHsigboxreverse);
if (CWcautionval < 300) {
Serial1.println("<setcaution1>"); // send data to other end
}
if (CWclearval < 300) {
Serial1.println("<setclear1>"); // send data to other end
}
if (ACWcautionval < 300) {
Serial1.println("<setACWcaution2>"); // send data to other end
}
if (ACWclearval < 300) {
Serial1.println("<setACWclear2>"); // send data to other end
}
if (SWstopval < 300) {
Serial1.println("<setstop>"); // send data to other end
}
if (sigboxemergstop < 300) {
Serial1.println("<setsigboxemerg>"); // send data to other end
SigBoxEmerg(); // goes to this routine until emerg input inactive
}
if (pointsnormal < 300) {
normalloop:
Serial1.println("<setnormal>"); // send data to other end
pointsnormal = analogRead(SWITCHsigboxnormal);
if (pointsnormal < 300) goto normalloop;
}
if (pointsreverse < 300) {
reverseloop:
Serial1.println("<setreverse>"); // send data to other end
pointsreverse = analogRead(SWITCHsigboxreverse);
if (pointsreverse < 300) goto reverseloop;
}
}
// @@@@@@
void SigBoxEmerg() {
// signal box emergency input has been activated. Loop through until inactive
int sigboxemergstop = 1000;
int SWITCHsigboxemerg = A1;
sigboxALLRED();
// insert line to turn emergency LED on remote panel, then off at end of emerg
digitalWrite(emergSTOP, HIGH);
delay (2);
SigBoxEmergLoop:
Serial1.println("<setsigboxemerg>"); // send data to other end
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
// now that emergency input is inactive, tell other end
// EndSBemerg:
digitalWrite(emergSTOP, LOW); // turn off sigbox emergency LED now issue has finished.
Serial1.println("<setsigboxemerg>"); // send data to other end
delay (1000); // wait 5 seconds after emergency is over
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
Serial1.println("<setsigboxemerg>"); // send data to other end
delay (1000); // wait 5 seconds after emergency is over
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
Serial1.println("<setsigboxemerg>"); // send data to other end
delay (1000); // wait 5 seconds after emergency is over
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
Serial1.println("<setsigboxemerg>"); // send data to other end
delay (1000); // wait 5 seconds after emergency is over
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
Serial1.println("<setsigboxemerg>"); // send data to other end
delay (1000); // wait 5 seconds after emergency is over
sigboxemergstop = analogRead(SWITCHsigboxemerg);
if (sigboxemergstop < 300) goto SigBoxEmergLoop; // send data to other end
Serial1.println("<endsigboxemerg>"); // send data to other end
delay (20);
Serial1.println("<endsigboxemerg>"); // send data to other end
delay (20);
Serial1.println("<endsigboxemerg>"); // send data to other end
delay (20);
Serial1.println("<endsigboxemerg>"); // send data to other end
}
//#########################
void undetermined() { // flash local/remote LEDs if both inputs are invalid. Unit can either be LOCAL or REMOTE, not both or neither.
digitalWrite(LOCAL, LOW);
digitalWrite(REMOTE, LOW);
delay (600);
digitalWrite(LOCAL, HIGH);
digitalWrite(REMOTE, HIGH);
delay (600);
Serial1.println("northing will be happening until local or remote is set");
}
//#######################
void Testlamps() {
// run through test of each output
// runs once, at power up/initialisation
digitalWrite(SIG2red, LOW);
digitalWrite(LOCAL, LOW);
delay (dt);
digitalWrite(SIG2red, HIGH);
digitalWrite(SIG2yel, LOW);
digitalWrite(LOCAL, HIGH);
delay (dt);
digitalWrite(SIG2yel, HIGH);
digitalWrite(LOCAL, LOW);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(SIG3red, LOW);
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(SIG3red, HIGH);
digitalWrite(SIG3yel, LOW);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(SIG3yel, HIGH);
digitalWrite(SIG3grn, LOW);
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(SIG3grn, HIGH);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(SIG1red, LOW);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(SIG1red, HIGH);
digitalWrite(SIG1yel, LOW);
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(SIG1yel, HIGH);
digitalWrite(SIG1grn, LOW);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(SIG1grn, HIGH);
digitalWrite(SIG1MN, LOW);
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(SIG1MN, HIGH);
digitalWrite(SIG1LOCO, LOW);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(SIG1LOCO, HIGH);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(blockocc, LOW);
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(blockocc, HIGH);
digitalWrite(emergSTOP, LOW);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(emergSTOP, HIGH);
digitalWrite(locotrack, LOW); // loco track circuit
delay (dt);
digitalWrite(LOCAL, HIGH);
digitalWrite(locotrack, HIGH);
digitalWrite(ptsfailed, LOW); // points failure
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(ptsfailed, HIGH);
// Serial.println("lamp test finished");
//end of test of all lamps
//now, set all signals to stop, turn everything else off
digitalWrite(pointN, HIGH);
digitalWrite(pointR, HIGH);
digitalWrite(REMOTE, HIGH);
digitalWrite(blockocc, HIGH);
digitalWrite(emergSTOP, HIGH);
digitalWrite(ptsfailed, HIGH);
digitalWrite(locotrack, HIGH);
ALLRED(); // set all signals to stop
}
//#######################
void Testremotelamps() {
dt = 700; // set sigbox test lamp time to .7 second
// run through test of each output
// runs once, at power up/initialisation
digitalWrite(SIG2red, HIGH);
delay (dt);
digitalWrite(SIG2red, LOW);
digitalWrite(SIG2yel, HIGH);
delay (dt);
digitalWrite(SIG2yel, LOW);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(SIG3red, HIGH);
delay (dt);
digitalWrite(SIG3red, LOW);
digitalWrite(SIG3yel, HIGH);
delay (dt);
digitalWrite(SIG3yel, LOW);
digitalWrite(SIG3grn, HIGH);
delay (dt);
digitalWrite(SIG3grn, LOW);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(SIG1red, HIGH);
delay (dt);
digitalWrite(SIG1red, LOW);
digitalWrite(SIG1yel, HIGH);
delay (dt);
digitalWrite(SIG1yel, LOW);
digitalWrite(SIG1grn, HIGH);
delay (dt);
digitalWrite(SIG1grn, LOW);
digitalWrite(SIG1MN, HIGH);
delay (dt);
digitalWrite(SIG1MN, LOW);
digitalWrite(SIG1LOCO, HIGH);
delay (dt);
digitalWrite(SIG1LOCO, LOW);
// xxxxxxxxxxxxxxxxxxxxx
digitalWrite(LOCAL, HIGH);
delay (dt);
digitalWrite(LOCAL, LOW);
digitalWrite(REMOTE, HIGH);
delay (dt);
digitalWrite(REMOTE, LOW);
digitalWrite(blockocc, HIGH);
delay (dt);
digitalWrite(blockocc, LOW);
digitalWrite(emergSTOP, HIGH);
delay (dt);
digitalWrite(emergSTOP, LOW);
digitalWrite(ptsfailed, HIGH); // loco track circuit
delay (dt);
digitalWrite(ptsfailed, LOW);
digitalWrite(locotrack, HIGH); // points failure
delay (dt);
digitalWrite(locotrack, LOW);
// Serial.println("signal box panel lamp test finished");
//end of test of all lamps
//now, set all signals to stop, turn everything else off
digitalWrite(pointN, LOW);
digitalWrite(pointR, LOW);
digitalWrite(LOCAL, LOW);
digitalWrite(REMOTE, LOW);
digitalWrite(blockocc, LOW);
digitalWrite(emergSTOP, LOW);
digitalWrite(ptsfailed, LOW);
digitalWrite(locotrack, LOW);
sigboxALLRED(); // set all signals to stop
}
void receiveremotedata() {
// this is the local end receiving data from the signal box (remote) end
delay (80); // give time for other end to send data. If no data coming in within this time, then
// 6/12/20 - delay reduced from 180ms to 80ms
//digitalWrite(LOCAL, HIGH);
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
// if (Serial1.available() > 0) {
while (Serial1.available() > 0 && newData == false) {
rc = Serial1.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
// ####################################
//
// #### # # #### # ##### #
// # # # # # # # # # # #
// #### # # # ##### # #####
// # # # # # # # # # # #
// # # # # #### # # # # #
//
// ####################################
void decodeREMOTEdata() {
// what is being received at local end from signal box
// likely an issue or turned off.
// without above delay, local unit is too quick to decode any data 16/10/19
// Rxdataloop:
//Serial1.println("Start of Rx data loop"); // for debugging
Rxdata = false;
digitalWrite(REMOTE, HIGH); // flicker "remote" LED when data coming in
delay (5);
if (newData == true) {
Serial.print("This just in from the signalbox ... ");
Serial.println(receivedChars);
newData = false;
if (strcmp(receivedChars, "setsigboxemerg") == 0) {
digitalWrite(REMOTE, LOW);
digitalWrite(emergSTOP, LOW);
ALLSTOP();
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
// set signal box LEDs to stop and show emergstop LEd.
}
if (strcmp(receivedChars, "endsigboxemerg") == 0) {
digitalWrite(REMOTE, LOW);
digitalWrite(emergSTOP, HIGH);
Rxdata = true;
datacount = 0;
zdatacount = 0;
// turn off emerg LED on panel,
delay (50);
}
if (strcmp(receivedChars, "setcaution1") == 0) {
digitalWrite(REMOTE, LOW);
if (pointsREVERSE == true) {
clockwiseloco();
}
if (pointsNORMAL == true) {
clockwisecaution();
}
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
if (strcmp(receivedChars, "setstop") == 0) {
digitalWrite(REMOTE, LOW);
ALLRED();
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
currentMillis = millis();
if (currentMillis - startMillis >= cautiontimer){
blockwasoccupied = false; // since the time has elapsed, the block was not recently occupied
}
if (strcmp(receivedChars, "setclear1") == 0) {
digitalWrite(REMOTE, LOW);
if (pointsREVERSE == true) {
clockwiseloco();
}
if (pointsNORMAL == true) {
// 30/7/21: set to caution if block has just become unoccupied
//block has just become unoccupied. Check that delay has elapsed. If not, display caution until it has elapsed
currentMillis = millis();
if (currentMillis - startMillis <= cautiontimer) { //modified 25/3/22
if (blockwasoccupied == true) clockwisecaution(); //test whether the period has elapsed
// if block just occupied and time not elapsed, show caution, otherwise show clear
}
else{
clockwiseclear();
}
}
// "caution delay" above added 30/7/21
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
if (strcmp(receivedChars, "setACWclear2") == 0) {
// 30/7/21: insert logic to display "caution" instead of clear, if block has just become unoccupied
digitalWrite(REMOTE, LOW);
if (pointsREVERSE == true) {
locodepart();
}
if (pointsNORMAL == true) {
currentMillis = millis();
if (currentMillis - startMillis <= cautiontimer){
if(blockwasoccupied == true) anticlockwisecaution(); //test whether the period has elapsed
else{
anticlockwiseclear();
}
}
if (currentMillis - startMillis >= cautiontimer){
blockwasoccupied = false; // since the time has elapsed, the block was not recently occupied
}
// "caution delay" above added 30/7/21
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
if (strcmp(receivedChars, "setnormal") == 0) {
digitalWrite(REMOTE, LOW);
POINTSnormal();
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
if (strcmp(receivedChars, "setreverse") == 0) {
digitalWrite(REMOTE, LOW);
POINTSreverse();
Rxdata = true;
datacount = 0;
zdatacount = 0;
delay (50);
}
if (strcmp(receivedChars, "setACWcaution2") == 0) {
digitalWrite(REMOTE, LOW);
if (pointsREVERSE == true) {
locodepart();
}
if (pointsNORMAL == true) {
anticlockwisecaution();
}
Rxdata = true;
datacount = 0;
zdatacount = 0;
// turn loco occupied LED off
delay (50);
}
}
}
}
void determinelocalremote() {
// happens once, just after power-up
pinMode(setlocal, INPUT);
pinMode(setremote, INPUT);
digitalWrite(setlocal, INPUT_PULLUP); // set pull-up on analog pin
digitalWrite(setremote, INPUT_PULLUP);
//Serial.println("detect local or remote");
delay (10);
LOCALREMOTE: // check what setting this device is configured to be
digitalWrite(LOCAL, HIGH); // active low on local end - turn off
digitalWrite(REMOTE, LOW); // active high on remote end - turn off
setlocalval = analogRead(setlocal); // read the input status
setremoteval = analogRead(setremote); // read the input status
if (setlocalval < 300 && setremoteval < 300) undetermined(); // flash local/remote until sorted out
if (setlocalval > 300 && setremoteval > 300) undetermined(); // flash local/remote until sorted out
if (setlocalval < 300 && setremoteval < 300) goto LOCALREMOTE; // go back to LOCALREMOTE if both inputs invalid
if (setlocalval > 300 && setremoteval > 300) goto LOCALREMOTE;
if (setlocalval < 300 ) {
digitalWrite(LOCAL, LOW); // active low on local end
digitalWrite(REMOTE, HIGH);
// Serial1.print("I have set local value to be true"); // debugging
// setaslocal = true;
// setasremote = false;
}
if (setremoteval < 300) {
digitalWrite(LOCAL, LOW); // active high on local end
digitalWrite(REMOTE, HIGH);
// setasremote = true;
// setaslocal = false;
}
//if (setlocalval < 300) Serial1.println(" debugging: I am set as local as defined by low input ");
//if (setremoteval < 300) Serial1.println(" debugging: I am set as remote (signal box) as defined by low input ");
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void receiveLOCALdata() {
//receiving data in signal box from other end
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
// if (Serial1.available() > 0) {
while (Serial1.available() > 0 && newData == false) {
rc = Serial1.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//#########################
void safetydelay() {
Serial1.println("<safetydelay>");
delay (100);
}
//########################
void decodeLOCALdata() {
// decode data in signal box from other end
Rxdata = false;
digitalWrite(LOCAL, LOW); // flicker Local LED when data coming in
delay (15);
if (newData == true) {
newData = false;
if (strcmp(receivedChars, "emergstop1") == 0) { //strcmp means "String Compare". Compares "receivedChars" to the word next to it
digitalWrite(LOCAL, HIGH);
digitalWrite(emergSTOP, HIGH);
sigboxALLRED();
Rxdata = true;
// set signal box LEDs to stop and show emergstop LED.
}
if (strcmp(receivedChars, "allstop1") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxALLRED();
Rxdata = true;
// set signal box LEDs to stop and show emergstop LED.
}
if (strcmp(receivedChars, "emergstop0") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(emergSTOP, LOW);
Rxdata = true;
// turn off emerg LED on panel.
}
if (strcmp(receivedChars, "blockocc1") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(blockocc, HIGH);
sigboxALLRED();
Rxdata = true;
// turn on block occupied and all red LEDs, don't send data
}
if (strcmp(receivedChars, "blockocc0") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(blockocc, LOW);
Rxdata = true;
// turn off block occupied LED
}
if (strcmp(receivedChars, "locoocc1") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(locotrack, HIGH);
Rxdata = true;
// loco occupied LED
}
if (strcmp(receivedChars, "locooccupied0") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(locotrack, LOW);
Rxdata = true;
// turn loco occupied LED off
}
if (strcmp(receivedChars, "clockwiseclear1") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxclockwiseclear();
Rxdata = true;
}
if (strcmp(receivedChars, "clockwisecaution1") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxclockwisecaution();
Rxdata = true;
}
if (strcmp(receivedChars, "clockwiseloco1") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxclockwiseloco();
Rxdata = true;
}
if (strcmp(receivedChars, "locodepart") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxlocodepart();
Rxdata = true;
}
if (strcmp(receivedChars, "anticlockwiseclear2") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxanticlockwiseclear();
Rxdata = true;
}
if (strcmp(receivedChars, "anticlockwisecaution2") == 0) {
digitalWrite(LOCAL, HIGH);
sigboxanticlockwisecaution();
Rxdata = true;
}
if (strcmp(receivedChars, "pointssetnormal") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, HIGH);
digitalWrite(pointR, LOW);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
}
// added normaltransiton, normaltransitoff, reversetransiton, reversetransitoff to allow flashing when points in transit
// to display in signal box ONLY. 28/11/20.
if (strcmp(receivedChars, "normaltransiton") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, HIGH);
digitalWrite(pointR, LOW);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
Serial1.println("<setstop>"); // added 8/3/21. Now that the points change is in-progress, ensure signals are kept at stop and stop sending commands to set points.
}
if (strcmp(receivedChars, "normaltransitoff") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, LOW);
digitalWrite(pointR, LOW);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
Serial1.println("<setstop>"); // added 8/3/21. Now that the points change is in-progress, ensure signals are kept at stop and stop sending commands to set points.
}
if (strcmp(receivedChars, "reversetransiton") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, LOW);
digitalWrite(pointR, HIGH);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
Serial1.println("<setstop>"); // added 8/3/21. Now that the points change is in-progress, ensure signals are kept at stop and stop sending commands to set points.
}
if (strcmp(receivedChars, "reversetransitoff") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, LOW);
digitalWrite(pointR, LOW);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
Serial1.println("<setstop>"); // added 8/3/21. Now that the points change is in-progress, ensure signals are kept at stop and stop sending commands to set points.
}
//
if (strcmp(receivedChars, "pointssetreverse") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, LOW);
digitalWrite(pointR, HIGH);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
}
if (strcmp(receivedChars, "pointsfailed7") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(pointN, LOW);
digitalWrite(pointR, LOW);
digitalWrite(ptsfailed, HIGH);
sigboxALLRED();
Rxdata = true;
}
if (strcmp(receivedChars, "safetydelay") == 0) {
digitalWrite(LOCAL, HIGH);
Rxdata = true;
}
if (strcmp(receivedChars, "pointsnotfailed") == 0) {
digitalWrite(LOCAL, HIGH);
digitalWrite(ptsfailed, LOW);
Rxdata = true;
}
}
delay (15);
}
// ############################
void locotrackocc(){
locotrackcircuitval = 1000; // added 8/11/21
locotrackcircuitval = analogRead(locotrackcct); // read input
int tccount = 0;
if (locotrackcircuitval < 400) {
tccount = tccount +1;
delay (30); // contact debounce time
locotrackcircuitval = analogRead(locotrackcct); // read input
if (locotrackcircuitval < 400) {
delay (30); // second 50mS - could be legit activiation
locotrackcircuitval = analogRead(locotrackcct); // read input
tccount = tccount +1; //add another block to counter
if (locotrackcircuitval < 400) {
delay (30); // second 50mS - could be legit activiation
tccount = tccount +1; //add another block to counter
}
}
}
if (tccount == 3) { // at least 90mS of occupancy - must be occupied
LOCOOCCUPIED();
tccount = 0;
}
if (locotrackcircuitval > 400) {
LOCOUNOCCUPIED();
}
}