-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSwitch8_Turnouts.ino
More file actions
159 lines (132 loc) · 4.33 KB
/
Copy pathSwitch8_Turnouts.ino
File metadata and controls
159 lines (132 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
Arduino Sketch to control an NCE Switch-8 from non-momentary rotary toggle switches.
This replaces an NCE Button Board which does not properly deal with non-momentary rotary switches.
This sketch is designed for an Arduino Nano.
https://www.arduino.cc/en/Main/ArduinoBoardNano
Connections to the Switch-8's Button Board terminal:
- Pin 1 (TX1) to "DATA"
- Pin VIN to "+" (6-20 V max, 7-12 V recommended)
- Pin GND to "GND"
Connections to the rotary toggles:
- D2/D3 : Turnout 1 N/R
- D4/D5 : Turnout 2 N/R
- D6/D7 : Turnout 3 N/R
- D8/D9 : Turnout 4 N/R
- D10/D11: Turnout 5 N/R
- A0/A1 : Turnout 6 N/R
- A2/A3 : Turnout 7 N/R
- A4/A5 : Turnout 8 N/R
Note that on the Arduino Nano, RX0/TX1 are linked to the USB chip.
This means one can trivially check the output by using an USB cable
and checking the Arduino IDE's serial console.
*/
// Pin number of the Arduino's onboard LED.
#define LED 13
// Time in milliseconds to wait at startup to let the Switch-8 initialize.
#define DELAY_MS_START 2000
// Time in milliseconds to wait after sending a serial command to let the Switch-8 throw the turnout.
#define DELAY_MS_SWITCH 1000
// Time in milliseconds before scanning next input.
// This crude rate-limiter makes the sketch scan each input roughtly once per second.
#define DELAY_MS_LOOP 10
// Blink the LED for 100 ms.
#define DELAY_MS_BLINK 100
// Time in milliseconds to wait before sending the button-released command to the Switch-8.
#define DELAY_MS_BTN_RELEASE 500
// Number of inputs scanned (8 turnouts, Normal/Release each).
#define MAX_INPUT 16
// When this digital I/O is grounded during setup, output debug statements instead of SW8 commands
#define DEBUG_PIN 12
// Pin numbers of the Digital I/O to scan for the 8 turnouts inputs.
// Each turnout uses 2 inputs: one for Normal and one for Reverse.
const int inputs[MAX_INPUT] = {
2,3, 4,5, 6,7, 8,9, 10,11,
A0,A1, A2,A3, A4,A5
};
// Last known state of each input, either LOW (active) or HIGH.
int states[MAX_INPUT];
boolean isDebug;
// Blinks the onboard LED.
void blink() {
digitalWrite(LED, HIGH);
delay(DELAY_MS_BLINK);
digitalWrite(LED, LOW);
}
void sendByte(byte value) {
Serial.write(value);
Serial.write(0xFF ^ value);
}
void sendSwitch8Command(int index) {
if (isDebug) {
Serial.write("\nActivate ");
String s = String(index);
Serial.write(s.c_str());
} else {
sendByte(0x80 + index);
delay(DELAY_MS_BTN_RELEASE);
sendByte(0x40 + index);
}
}
// Checks an input and sends a command to the Switch-8 if the input
// has changed since last read.
void checkInput(int index) {
int state = digitalRead(inputs[index]);
if (state != states[index]) {
// State has changed.
states[index] = state;
if (isDebug) {
Serial.write("\nChanged ");
String s = String(index);
Serial.write(s.c_str());
Serial.write(" to ");
Serial.write(state ? "HI" : "LO");
}
if (state == LOW) {
// Inputs are active LOW since we use pull-up resistors.
// For any turnout rotary switch, one of the inputs is LOW and the other one is HIGH.
blink();
sendSwitch8Command(index);
delay(DELAY_MS_SWITCH);
}
}
}
void sleepStart() {
for (int i = 0; i < 4; ++i) {
blink();
delay(DELAY_MS_START / 4);
}
}
void setup() {
// Configure the onboard LED pin to a digital output
pinMode(LED, OUTPUT);
// Configure the debug pin enabling its internal pull-up.
pinMode(DEBUG_PIN, INPUT_PULLUP);
for (int i = 0; i < MAX_INPUT; ++i) {
// Configure the inputs, enabling their internal pull-up.
pinMode(inputs[i], INPUT_PULLUP);
// Set each memorized "previous" state to high. Since the states
// are active LOW, this will force the initialization code to send
// the current turnout state to the Switch-8 during setup.
states[i] = HIGH;
}
// Initialize serial port.
Serial.begin(9600, SERIAL_8N1);
// Sleep to give time to the Switch-8 to start
sleepStart();
isDebug = digitalRead(DEBUG_PIN) == LOW;
if (isDebug) {
Serial.write("\nDEBUG MODE\n");
sleepStart();
}
// Checks the inputs and updates the Switch-8 to match the rotary switches.
for (int i = 0; i < MAX_INPUT; ++i) {
blink();
checkInput(i);
}
}
void loop() {
for (int i = 0; i < MAX_INPUT; ++i) {
checkInput(i);
delay(DELAY_MS_LOOP);
}
}