/*
Date Last Test undertaken : 27/09/2013
Sketch Modification Undertaken: Major Upgrade to include London End Fiddle Yard Sequence
*****************************************************************************************
CURRENTLY WORKING ON DIVIDING RULES INTO EACH PANEL
FINAL ACTION MUST BE TO RE-ASSIGN I/O PINS TO SEQUENTIAL ORDER
*****************************************************************************************
Test Results: LONDON END MAIN DOWN PANEL TESTED ON SLOW TRAINS ONLY
RULES 1 TO 6 CORRECT ON LONDON END MAIN DOWN PANEL
Next Action: Major Upgrade to include London End Fiddle Yard Sequence
Following Action : Modify input/output pins to align sequential
Eridge Operator Sequence Panel - This Sketch is used to confirm next step and test prior to saving to Final Sketch
- This Sketch will deal only with DOWN LINE Operations ONLY
The aim is to use MO Pushbutton Switches and LEDs to communicate between each operator the current sequence of events during a running session
***** DOWN MAIN SEQUENCE CONTROL I/O FUNCTIONS *****
** LONDON END FIDDLE YARD SEQUENCE CONTROL PANEL **
buttonA1 - London End Fiddle Yard Down "Train Ready Dispatch" (Button A)
buttonA2 - London End Fiddle Yard Fast Down "Fast Service Ready Dispatch" (Button D)
ledA1 - Amber Solid - "Train Ready Dispatch" (LED A)
ledA2 - Green Solid - "Train Accepted" (LED B1)
ledA3 - Red Flashing - "Ready Next Service" (LED C1)
ledA4 - Amber Solid - "Fast Service Ready Dispatch" (LED D)
ledA5 - Green Solid - "Route Set" (LED E1)
ledA6 - Green Array - "Down Fast Accepted" (LED F2)
** LONDON END MAIN SEQUENCE CONTROL PANEL **
buttonB1 - London End Main Down "Train Accepted" (Button B)
buttonB2 - London End Main Down "Ready Next Service" (Button C)
buttonB3 - London End Main Fast Down "Fast Route Set" (Button E)
ledB1 - Amber Flashing - "Train Awaiting Acceptance" (LED A1)
ledB2 - Green Solid - "Accept Down Train" (LED B)
ledB3 - Red Solid - "Ready Next Service" (LED C)
ledB4 - Amber Flashing - "Fast Service Ready Dispatch" (LED D1)
ledB5 - Green Solid - "Route Set" (LED E)
ledB6 - Green Array - "Down Fast Accepted" (LED F1)
** COUNTRY END MAIN SEQUENCE CONTROL PANEL **
buttonC1 - Country End Main Control Down " Train Ready Dispatch"
ledC1 - Amber Solid - "Train Ready Dispatch"
ledC2 - Green Solid - "Down Train Accepted"
ledC3 - Red Flashing - "Ready Next Service"
ledC4 - Green Array - "Next Train Fast Service"
** COUNTRY END FIDDLE YARD SEQUENCE CONTROL PANEL **
buttonD1 - Country End Fiddle Yard Down - "Train Awaiting Acceptance"
buttonD2 - Country End Fiddle Yard Down - "Train Accepted"
buttonD3 - Country End Fiddle Yard Down - "Ready Next Service"
buttonD4 - Country End Fiddle Yard Down " Accept Down Fast" (Button F)
ledD1 - Amber Flashing - "Train Awaiting Acceptance"
ledD2 - Green Solid - "Train Accepted"
ledD3 - Red Solid - "Ready Next Service"
ledD4 - Amber Flashing - "Accept Down Fast" (LED E2)
ledD5 - Green Array - "Down Fast Accepted" (LED F)
*/
// **** CODE STARTS HERE ****
const long DBTIME = 25; // number of ms allowed to eliminate key bounce
const long FLASH_TIME = 250; // duration of on/off times for flashing LEDs
bool debounce(bool state, bool val, long time, long dbTime, bool& lastVal, long& lastTime) {
// We will only register a change of state if the input value has not
// changed for a certain time
bool newState;
newState = state; // by default the new state is the old state
if (lastVal != val) { // if the input value has changed
lastTime = time; // set the last time it changed to "now"
lastVal = val; // and retain the current input value
} else { // otherwise (input value has NOT changed)
if ((time - lastTime) >= dbTime) { // has it remained stable long enough
newState = val; // change the state
}
}
return newState; // This is the new state
}
bool simpleDebounce(int inPin, bool& state, bool& lastVal, long& lastTime) {
// A debounce routine with a simpler interface.
long time = millis(); // time in milliseconds
bool val = digitalRead(inPin); // current pin value
long dbTime = DBTIME; // the debounce interval
state = debounce(state, val, time, dbTime, lastVal, lastTime); // debounce the pin
return state; // return state
}
// **** INPUTS ON DOWN LINE SEQUENCE CONTROL PANELS ****
// ** LONDON END FIDDLE YARD DOWN SEQUENCE PANEL **
// buttonA1 - London End Fiddle Yard Down "Train Ready Dispatch" (ButtonA)
const int buttonA1 = 7;
bool lastButtonA1;
bool currentButtonA1;
long lastButtonA1Time;
// buttonA2 - London End Fiddle Yard "Fast Train Ready Dispatch" (ButtonD)
const int buttonA2 = 0;
bool lastButtonA2;
bool currentButtonA2;
long lastButtonA2Time;
// ** LONDON END MAIN DOWN SEQUENCE PANEL **
// buttonB1 - London End Main Control Down "Train Accepted" (ButtonB)
const int buttonB1 = 8;
bool lastButtonB1;
bool currentButtonB1;
long lastButtonB1Time;
// buttonB2 - London End Main Control Down "Ready Next Service" (ButtonC)
const int buttonB2 = 9;
bool lastButtonB2;
bool currentButtonB2;
long lastButtonB2Time;
// buttonB3 - London End Main control Down "Route Set" (ButtonE)
const int buttonB3 = 0;
bool lastButtonB3;
bool currentButtonB3;
long lastButtonB3Time;
// ** COUNTRY END MAIN DOWN SEQUENCE PANEL **
// buttonC1 - Country End Main Control Down " Train Ready Dispatch"
const int buttonC1 = 0;
bool lastButtonC1;
bool currentButtonC1;
long lastButtonC1Time;
// ** COUNTRY END FIDDLE YARD DOWN SEQUENCE CONTROL PANEL **
//buttonD1 - Country End Fiddle Yard Down - "Train Awaiting Acceptance"
const int buttonD1 = 0;
bool lastButtonD1;
bool currentButtonD1;
long lastButtonD1Time;
//buttonD2 - Country End Fiddle Yard Down - "Train Accepted"
const int buttonD2 = 0;
bool lastButtonD2;
bool currentButtonD2;
long lastButtonD2Time;
//buttonD3 - Country End Fiddle Yard Down - "Ready Next Service"
const int buttonD3 = 0;
bool lastButtonD3;
bool currentButtonD3;
long lastButtonD3Time;
//buttonD4 - Country End Fiddle Yard Down " Accept Down Fast"
const int buttonD4 = 0;
bool lastButtonD4;
bool currentButtonD4;
long lastButtonD4Time;
// **** OUTPUTS ON DOWN LINE SEQUENCE CONTROL PANEL****
// ** LONDON END FIDDLE YARD SEQUENCE CONTROL PANEL **
//ledA1 - Amber Solid - "Train Ready Dispatch"
const int ledA1 = 2;
bool ledOnA1 = false;
//ledA2 - Green Solid - "Train Accepted"
const int ledA2 = 3;
bool ledOnA2 = false;
//ledA3 - Red Flashing - "Ready Next Service"
const int ledA3 = 4;
bool ledOnA3 = false;
bool ledA3FlashState = false;
long ledA3LastFlashTime = -(FLASH_TIME);
//ledA4 - Amber Solid - "Fast Service Ready Dispatch"
const int ledA4 = 0;
bool ledOnA4 = false;
//ledA5 - Green Solid - "Route Set"
const int ledA5 = 0;
bool ledOnA5 = false;
//ledA6 - Green Array - "Down Fast Accepted"
const int ledA6 = 0;
bool ledOnA6 = false;
bool ledA6FlashState = false;
long ledA6LastFlashTime = -(FLASH_TIME);
// **LONDON END MAIN SEQUENCE CONTROL PANEL **
//ledB1 - Amber Flashing - "Train Awaiting Acceptance"
const int ledB1 = 10;
bool ledOnB1 = false;
bool ledB1FlashState = false;
long ledB1LastFlashTime = -(FLASH_TIME);
//ledB2 - Green Solid - "Accept Down Train"
const int ledB2 = 11;
bool ledOnB2 = false;
//ledB3 - Red Solid - "Ready Next Service"
const int ledB3 = 12;
bool ledOnB3 = false;
//ledB4 - Amber Flashing - "Fast Service Ready Dispatch"
const int ledB4 =1;
bool ledOnB4 = false;
bool ledB4FlashState = false;
long ledB4LastFlashTime = -(FLASH_TIME);
//ledB5 - Green Solid - "Route Set"
const int ledB5 =1;
bool ledOnB5 = false;
//ledB6 - Green Array - "Down Fast Accepted"
const int ledB6 =1;
bool ledOnB6 = false;
bool ledB6FlashState = false;
long ledB6LastFlashTime = -(FLASH_TIME);
// ** COUNTRY END MAIN SEQUENCE CONTROL PANEL **
//ledC1 - Amber Solid - "Train Ready Dispatch"
const int ledC1 = 1;
bool ledOnC1 = false;
//ledC2 - Green Solid - "Down Train Accepted"
const int ledC2 = 1;
bool ledOnC2 = false;
//ledC3 - Red Flashing - "Ready Next Service"
const int ledC3 = 1;
bool ledOnC3 = false;
bool ledC3FlashState = false;
long ledC3LastFlashTime = -(FLASH_TIME);
//ledC4 - Green Array - "Next Train Fast Service"
const int ledC4 = 1;
bool ledOnC4 = false;
bool ledC4FlashState = false;
long ledC4LastFlashTime = -(FLASH_TIME);
// ** COUNTRY END FIDDLE YARD SEQUENCE CONTROL PANEL **
//ledD1 - Amber Flashing - "Train Awaiting Acceptance"
const int ledD1 = 1;
bool ledOnD1 = false;
bool ledD1FlashState = false;
long ledD1LastFlashTime = -(FLASH_TIME);
//ledD2 - Green Solid - "Train Accepted"
const int ledD2 = 1;
bool ledOnD2 = false;
//ledD3 - Red Solid - "Ready Next Service"
const int ledD3 = 1;
bool ledOnD3 = false;
//ledD4 - Green Flashing - "Route Set"
const int ledD4 = 1;
bool ledOnD4 = false;
bool ledD4FlashState = false;
long ledD4LastFlashTime = -(FLASH_TIME);
//ledD5 - Green Array - "Down Fast Accepted"
const int ledD5 = 1;
bool ledOnD5 = false;
bool ledD5FlashState = false;
long ledD5LastFlashTime = -(FLASH_TIME);
void writeLEDStates() { // WRITES THE CURRENT STATES TO THE LEDs
// ** LONDON END FIDDLE YARD SEQUENCE CONTROL PANEL **
// ** Flashing ledA3 **
long time = millis(); // get the time
if (ledOnA3) { // are we flashing?
if (time >= (ledA3LastFlashTime + FLASH_TIME)) { // time to chang LED state?
ledA3FlashState = !ledA3FlashState; // change LED state
ledA3LastFlashTime = time; // and set the time
digitalWrite(ledA3, ledA3FlashState); // Change LED state
}
} else { // not flashing?
digitalWrite(ledA3, false); // turn LED off
// ** Flashing ledA6 ** (LED ARRAY Needs Writing)
if (ledOnA6) {
if (time >= (ledA6LastFlashTime + FLASH_TIME)) {
ledA6FlashState = !ledA6FlashState;
ledA6LastFlashTime = time;
digitalWrite(ledA6, ledA6FlashState);
}
} else {
digitalWrite(ledA6, false);
}
// **SOLID**
digitalWrite(ledA1, ledOnA1);
digitalWrite(ledA2, ledOnA2);
digitalWrite(ledA4, ledOnA4);
digitalWrite(ledA5, ledOnA4);
// ** LONDON END MAIN SEQUENCE CONTROL PANEL **
// ** Flashing ledB1 **
if (ledOnB1) { // are we flashing?
if (time >= (ledB1LastFlashTime + FLASH_TIME)) { // time to chang LED state?
ledB1FlashState = !ledB1FlashState; // change LED state
ledB1LastFlashTime = time; // and set the time
digitalWrite(ledB1, ledB1FlashState); // Change LED state
}
} else { // not flashing?
digitalWrite(ledB1, false); // turn LED off
}
// **special code for flashing ledB4 **
if (ledOnB4) {
if (time >= (ledB4LastFlashTime + FLASH_TIME)) {
ledB4FlashState = !ledB4FlashState;
ledB4LastFlashTime = time;
digitalWrite(ledB4, ledB4FlashState);
}
} else {
digitalWrite(ledB4, false);
}
// ** Flashing ledB6 ** (LED ARRAY Needs Writing)
if (ledOnB6) {
if (time >= (ledB6LastFlashTime + FLASH_TIME)) {
ledB6FlashState = !ledB6FlashState;
ledB6LastFlashTime = time;
digitalWrite(ledB6, ledB6FlashState);
}
} else {
digitalWrite(ledB6, false);
}
// **SOLID**
digitalWrite(ledB2, ledOnB2);
digitalWrite(ledB3, ledOnB3);
digitalWrite(ledB5, ledOnB5);
}
// ** COUNTRY END MAIN SEQUENCE CONTROL PANEL **
// ** Flashing ledC3**
if (ledOnC3) { // are we flashing?
if (time >= (ledC3LastFlashTime + FLASH_TIME)) { // time to chang LED state?
ledC3FlashState = !ledC3FlashState; // change LED state
ledC3LastFlashTime = time; // and set the time
digitalWrite(ledC3, ledC3FlashState); // Change LED state
}
} else { // not flashing?
digitalWrite(ledC3, false); // turn LED off
}
// **SOLID**
digitalWrite(ledC1, ledOnC1);
digitalWrite(ledC2, ledOnC2);
// ** COUNTRY END FIDDLE YARD SEQUENCE CONTROL PANEL **
// ** Flashing ledD1 **
if (ledOnD1) { // are we flashing?
if (time >= (ledD1LastFlashTime + FLASH_TIME)) { // time to chang LED state?
ledD1FlashState = !ledD1FlashState; // change LED state
ledD1LastFlashTime = time; // and set the time
digitalWrite(ledD1, ledD1FlashState); // Change LED state
}
} else { // not flashing?
digitalWrite(ledD1, false); // turn LED off
}
// **special code for flashing ledD4 **
if (ledOnD4) {
if (time >= (ledD4LastFlashTime + FLASH_TIME)) {
ledD4FlashState = !ledD4FlashState;
ledD4LastFlashTime = time;
digitalWrite(ledD4, ledD4FlashState);
}
} else {
digitalWrite(ledD4, false);
}
// ** Flashing ledD5 ** (LED ARRAY Needs Writing)
if (ledOnD5) {
if (time >= (ledD5LastFlashTime + FLASH_TIME)) {
ledD5FlashState = !ledD5FlashState;
ledD5LastFlashTime = time;
digitalWrite(ledD5, ledD5FlashState);
}
} else {
digitalWrite(ledD5, false);
}
// **SOLID**
digitalWrite(ledD2, ledOnD2);
digitalWrite(ledD3, ledOnD3);
}
void setup()
{
// initialize pins
pinMode(buttonA1, INPUT);
pinMode(buttonA2, INPUT);
pinMode(buttonB1, INPUT);
pinMode(buttonB2, INPUT);
pinMode(buttonB3, INPUT);
pinMode(buttonC1, INPUT);
pinMode(buttonD1, INPUT);
pinMode(buttonD2, INPUT);
pinMode(buttonD3, INPUT);
pinMode(buttonD4, INPUT);
pinMode(ledA1, OUTPUT);
pinMode(ledA2, OUTPUT);
pinMode(ledA3, OUTPUT);
pinMode(ledA4, OUTPUT);
pinMode(ledA5, OUTPUT);
pinMode(ledA6, OUTPUT);
pinMode(ledB1, OUTPUT);
pinMode(ledB2, OUTPUT);
pinMode(ledB3, OUTPUT);
pinMode(ledB4, OUTPUT);
pinMode(ledB5, OUTPUT);
pinMode(ledB6, OUTPUT);
pinMode(ledC1, OUTPUT);
pinMode(ledC2, OUTPUT);
pinMode(ledC3, OUTPUT);
pinMode(ledC4, OUTPUT);
pinMode(ledD1, OUTPUT);
pinMode(ledD2, OUTPUT);
pinMode(ledD3, OUTPUT);
pinMode(ledD4, OUTPUT);
pinMode(ledD5, OUTPUT);
// set output states
writeLEDStates();
// get the initial state of buttons
currentButtonA1 = lastButtonA1 = digitalRead(buttonA1);
lastButtonA1Time = millis();
currentButtonA2 = lastButtonA2 = digitalRead(buttonA2);
lastButtonA2Time = millis();
currentButtonB1 = lastButtonB1 = digitalRead(buttonB1);
lastButtonB1Time = millis();
currentButtonB2 = lastButtonB2 = digitalRead(buttonB2);
lastButtonB2Time = millis();
currentButtonB3 = lastButtonB3 = digitalRead(buttonB3);
lastButtonB3Time = millis();
currentButtonC1 = lastButtonC1 = digitalRead(buttonC1);
lastButtonC1Time = millis();
currentButtonD1 = lastButtonD1 = digitalRead(buttonD1);
lastButtonD1Time = millis();
currentButtonD2 = lastButtonD2 = digitalRead(buttonD2);
lastButtonD2Time = millis();
currentButtonD3 = lastButtonD3 = digitalRead(buttonD3);
lastButtonD3Time = millis();
currentButtonD4 = lastButtonD4 = digitalRead(buttonD4);
lastButtonD4Time = millis();
}
void readSwitchStates() {
// read the current button states
simpleDebounce(buttonA1, currentButtonA1, lastButtonA1, lastButtonA1Time);
simpleDebounce(buttonA2, currentButtonA2, lastButtonA2, lastButtonA2Time);
simpleDebounce(buttonB1, currentButtonB1, lastButtonB1, lastButtonB1Time);
simpleDebounce(buttonB2, currentButtonB2, lastButtonB2, lastButtonB2Time);
simpleDebounce(buttonB3, currentButtonB3, lastButtonB3, lastButtonB3Time);
simpleDebounce(buttonC1, currentButtonC1, lastButtonC1, lastButtonC1Time);
simpleDebounce(buttonD1, currentButtonD1, lastButtonD1, lastButtonD1Time);
simpleDebounce(buttonD2, currentButtonD2, lastButtonD2, lastButtonD2Time);
simpleDebounce(buttonD3, currentButtonD3, lastButtonD3, lastButtonD3Time);
simpleDebounce(buttonD4, currentButtonD4, lastButtonD4, lastButtonD4Time);
}
bool pressEdge(bool& state, bool lastVal) {
// detects the leading edge of a button press.
if ((!state) && lastVal) { // button pressed, but state not yet set
state = true; // set the state without waiting for debouncing
return true; // return a valid edge
} else {
return false; // it's not a press edge.
}
}
void buttonLogic() {
/*
**** RULES FOR LONDON END SEQUENCE CONTROL PANELS *****
1) Pressing a button when its LED is off causes the LED to turn on
2) Cancel LED A1 when LED B is illuminated
3) Cancel LED B when LED C is illuminated
4) Cancel LED C when LED A is illuminated
5) Sequence Must Start with ButtonA
6) Sequence Must Be Button A, ButtonB, then ButtonC. Ensures Correct Sequence is followed (prevents inadvertant button push illuminating led out of sequence)
*/
// Gather Button Data for London End Sequence
bool btnA1Edge = pressEdge(currentButtonA1, lastButtonA1);
bool btnA2Edge = pressEdge(currentButtonA2, lastButtonA2);
bool btnB1Edge = pressEdge(currentButtonB1, lastButtonB1);
bool btnB2Edge = pressEdge(currentButtonB2, lastButtonB2);
bool btnB3Edge = pressEdge(currentButtonB3, lastButtonB3);
bool btnC1Edge = pressEdge(currentButtonC1, lastButtonC1);
bool btnD1Edge = pressEdge(currentButtonD1, lastButtonD1);
bool btnD2Edge = pressEdge(currentButtonD2, lastButtonD2);
bool btnD3Edge = pressEdge(currentButtonD3, lastButtonD3);
bool btnD4Edge = pressEdge(currentButtonD4, lastButtonD4);
// ** LONDON END FIDDLE YARD SEQUENCE CONTROL PANEL RULES **
// ** LONDON END MAIN SEQUENCE CONTROL PANEL RULES **
// ** COUNTRY END MAIN SEQUENCE CONTROL PANEL RULES **
// ** COUNTRY END FIDDLE YARD SEQUENCE CONTROL PANEL RULES **
if ((btnA1Edge) && !ledOnB2) { // Rule 1, Rule 6 for LED A
ledOnA1 = true;
ledOnB1 = true;
ledOnA2 = false; // Rule 4
ledOnB2 - false;
}
if ((btnB1Edge) && !ledOnB2 && ledOnA1) { // Rule 1,Rule 5 Rule 6 for LED B
ledOnA2 = true;
ledOnB2 = true;
ledOnA1 = false; // Rule 2
ledOnB1 = false;
}
if ((btnB2Edge) && !ledOnA1 && ledOnB2) { // Rule 1, Rule 5 Rule 6 for LED C
ledOnA3 = true;
ledOnB3 = true;
ledOnA2 = false;
ledOnB2 = false;
/* FOR INFO: ledA1 and ledB1 are selected On by btnA1Edge
ledA1 and ledB1 are selected Off by btnB1Edge
ledA2 and ledB2 are selected On by btnB1Edge
ledA2 and ledB2 are selected Off by btnB2Edge
ledA3 and LedB3 are selected On by btnB2Edge
ledA3 and LedB3 are selected Off by btnA1Edge
*/
}
}
void loop() {
while (true) {
// get input states
readSwitchStates();
// do the button logic
buttonLogic();
// set output states
writeLEDStates();
}
}