/*
Arduino Nano - old bootloader
Robert Parnell.
27/5/22
Wascoe Siding - signal module
V1 - create basic structure
V2 - 10/6/22. Simulated on-line and tested OK. To check on real hardware.
Signal 1 has 2x turnout indicators and track circuit.
Signal 2 does not have a separate track circuit (shared), no separate turnout indicators.
board outputs:
S1red Signal 1 - red
S1yel Signal 1 - yellow
S1grn Signal 1 - green
S1toL Signal 1 - turnout L
S1toR Signal 1 - turnout R
TC1 Panel mimic - track circuit 1
TC2 Panel mimic - track circuit 2 - XXXX not required, to be removed. Make this emergency display.
S2red Signal 2 - red
S2yel Signal 2 - yellow
S2grn Signal 2 - green
board inputs:
track circuit 1
emergency stop
signal box proceed - signal 1
signal box proceed - signal 2 (if either input is inactive, then signal is at stop)
next signal ahead status (stop or proceed)
turnout L (from lever) OR signal box proceed in other direction
turnout R - from lever
turnout 3 - from lever
*/
//outputs:
int S1red = 2;// D2 etc
int S1yel = 3;
int S1grn = 4;
int S1toL = 5;
int S1toR = 6;
int EMERGind = 7;
int TC1 = 8;
int TC2 = 9; // note - there is only one track circuit input, this isn't required
int S2red = 10;
int S2yel = 11;
int S2grn = 12;
//inputs:
int trackcircuit1 = A0;
int emergencystop = A1;
int signal1proceed = A2;
int signal2proceed = A3;
int signal1aheadstatus = A4;
int turnoutL = A5;
int turnoutR = A6;
int signal2aheadstatus = A7;
// input values:
int trackcct1Val = 1000;
int emergStopVal = 1000;
int signal1Val = 1000;
int signal2Val = 1000;
int signal1aheadVal = 1000;
int signal2aheadVal = 1000;
int turnoutLVal = 1000;
int turnoutRVal = 1000;
int testtime = 100; // milliseconds for test lamp sequence
// for setting signal to "caution" after the block has become unoccupied - if signal is set to full clear
int blockwasoccupied = false; //
int blockisoccupied = false; //
unsigned long startMillis; // for starting countdown after blockwas occupied
unsigned long sigatStopMillis; // for 2 second debounce of track circuit
unsigned long cautiontimer = 8000; // time period for countdown (effectively less 2secs due to debounce timer)
unsigned long currentMillis; // what will be the current value to compare countdown to
void setup() {
pinMode(S1red, OUTPUT);
pinMode(S1yel, OUTPUT);
pinMode(S1grn, OUTPUT);
pinMode(S2red, OUTPUT);
pinMode(S2yel, OUTPUT);
pinMode(S2grn, OUTPUT);
pinMode(S1toL, OUTPUT);
pinMode(S1toR, OUTPUT);
pinMode(EMERGind, OUTPUT);
pinMode(TC1, OUTPUT);
pinMode(TC2, OUTPUT);
pinMode(trackcircuit1, INPUT);
pinMode(emergencystop, INPUT);
pinMode(signal1proceed, INPUT);
pinMode(signal2proceed, INPUT);
pinMode(signal1aheadstatus, INPUT);
pinMode(turnoutL, INPUT);
pinMode(turnoutR, INPUT);
pinMode(signal2aheadstatus, INPUT);
startuptest();
Serial.begin(115200); // Any baud rate should work
Serial.println("Hello Arduino\n");
}
void loop() {
// read input values
// display appropriate signal
// go back and do it again!
readinputvalues();
displaysignals();
delay(200);
}
void readinputvalues(){
trackcct1Val = analogRead(trackcircuit1); // track circuit 1 status
if (trackcct1Val <=500) {
blockisoccupied = true; //
blockwasoccupied = true;
sigatStopMillis = millis();
}
else {
currentMillis=millis();
if (currentMillis-sigatStopMillis>=2000) blockisoccupied = false;
if (currentMillis-sigatStopMillis>=cautiontimer) blockwasoccupied = false;
}
emergStopVal = analogRead(emergencystop); // emergency stop status
signal1Val = analogRead(signal1proceed); // signaller signal switch
signal2Val = analogRead(signal2proceed); // signaller signal switch
signal1aheadVal = analogRead(signal1aheadstatus); // the signal status in advance of this signal
signal2aheadVal = analogRead(signal2aheadstatus); // the signal status in advance of this signal
turnoutLVal = analogRead(turnoutL); // the turnout lever status for Left turnout
turnoutRVal = analogRead(turnoutR); // the turnout lever status for Right turnout
}
void displaysignals(){
// check emergency stop
// check track circuit status
// check signal switches
// if cleared, check signal ahead and timer
// also determine if turnout or straight route is set
// if nothing else affected, display clear
if (emergStopVal<=500){
displaySTOP();
digitalWrite(EMERGind,HIGH);
Serial.println("Emergency stop activated");
}
else{
digitalWrite(EMERGind,LOW);
if (blockisoccupied == true){
displaySTOP();
digitalWrite(TC1,HIGH); // track circuit mimic ON
}
else{
// block is not occupied
digitalWrite(TC1,LOW); // track circuit mimic OFF
// ****************** SIGNAL 1 ****************
if (signal1Val>=500){
Serial.println("signal 1 is at stop");
// signal is set to stop
digitalWrite(S1red,HIGH); // on
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}
else{
Serial.println("Signal 1 is not at stop");
if (signal1Val<=500){
// signal is set to proceed
if (turnoutLVal<=500){
Serial.println("L turnout");
//display turnout aspect to the left
digitalWrite(S1red,HIGH); // on
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,LOW); // off
digitalWrite(S1toL,HIGH); // on
digitalWrite(S1toR,LOW); // off
}
if (turnoutRVal<=500){
Serial.println("R turnout");
// insert - display turnout aspect to the right
digitalWrite(S1red,HIGH); // on
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,HIGH); // on
}
if ((turnoutLVal>=500) && (turnoutRVal>=500)){
if ((blockwasoccupied == true) || (signal1aheadVal<=500)){
Serial.println("Caution");
// display caution aspect
digitalWrite(S1red,LOW); // off
digitalWrite(S1yel,HIGH); // on
digitalWrite(S1grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}
else {
// display clear
Serial.println("Clear");
if ((blockwasoccupied == false) & (signal1aheadVal>=500)){
digitalWrite(S1red,LOW); // off
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,HIGH); // on
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}
}
}
}
}
// ****************** SIGNAL 2 *******************
if (signal2Val>=500){
Serial.println("Signal 2 is at stop");
digitalWrite(S2red,HIGH); // on
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,LOW); // off
}
else{
Serial.println("Signal is not at stop");
if (signal2Val<=500){
// signal 2 is set to proceed
// signal 2 may not have any turnouts. Left in - can be removed later. 10/6/22
if (turnoutLVal<=500){
Serial.println("L turnout");
//display turnout aspect to the left
digitalWrite(S2red,HIGH); // on
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,LOW); // off
digitalWrite(S1toL,HIGH); // on
digitalWrite(S1toR,LOW); // off
}
if (turnoutRVal<=500){
Serial.println("R turnout");
// insert - display turnout aspect to the right
digitalWrite(S2red,HIGH); // on
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,HIGH); // on
}
if ((turnoutLVal>=500) && (turnoutRVal>=500)){
if ((blockwasoccupied == true) || (signal2aheadVal<=500)){
Serial.println("Caution2");
// display caution aspect
digitalWrite(S2red,LOW); // off
digitalWrite(S2yel,HIGH); // on
digitalWrite(S2grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}
else {
// display clear
Serial.println("Clear 2");
if ((blockwasoccupied == false) & (signal2aheadVal>=500)){
digitalWrite(S2red,LOW); // off
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,HIGH); // on
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}
}
}
}
}
}
}
}
void startuptest(){
// cycle throgh and test all outputs for a short time
digitalWrite(S1red,HIGH); // on
delay (testtime);
digitalWrite(S1red,LOW); // off
digitalWrite(S1yel,HIGH); // on
delay (testtime);
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,HIGH); // on
delay (testtime);
digitalWrite(S1grn,LOW); // off
digitalWrite(S2red,HIGH); // on
delay (testtime);
digitalWrite(S2red,LOW); // off
digitalWrite(S2yel,HIGH); // on
delay (testtime);
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,HIGH); // on
delay (testtime);
digitalWrite(S2grn,LOW); // off
digitalWrite(S1toL,HIGH); // on
delay (testtime);
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,HIGH); // on
delay (testtime);
digitalWrite(S1toR,LOW); // off
digitalWrite(EMERGind,HIGH); // on
delay (testtime);
digitalWrite(EMERGind,LOW); // off
digitalWrite(TC1,HIGH); // on
delay (testtime);
digitalWrite(TC1,LOW); // off
digitalWrite(TC2,HIGH); // on
delay (testtime);
digitalWrite(TC2,LOW); // off
}
void displaySTOP(){
digitalWrite(S1red,HIGH); // on
digitalWrite(S1yel,LOW); // off
digitalWrite(S1grn,LOW); // off
digitalWrite(S2red,HIGH); // on
digitalWrite(S2yel,LOW); // off
digitalWrite(S2grn,LOW); // off
digitalWrite(S1toL,LOW); // off
digitalWrite(S1toR,LOW); // off
}