/*
Four Basic Switch Processing Routines For Newbies

- Simple Toggle Switch
- Single Pole Double Throw Toggle Switch
- Simple Pushbutton Switch
- Push On/Push Off Pushbutton Switch

This sketch employs Jim's INPUTPINS() user function from his "Link2fs Multi Radio Panel project" found at
http://www.jimspage.co.nz/intro.htm

As always, thank you Jim for Link2FS and the sample sketches.

Switch input is a human interface procedure, not terribly fast by processor standards, a toggle switch can be scanned every 60 milliseconds without missing an input. Pushbuttons may require scans every 50 milliseconds or less. Reduce the value in "delayTimer = millis() + 50;" if you find that light (very short) button presses are being missed.-

I have used a verbose method to set up the input/output pins. It is convenient to catalog all pin information in one place. Use the physical pin numbers in the pinMode() function and show pin alias names, purpose of the pin, sample output in a comment for each pin. Assign the physical pin number to a constant variable (alias name) in the global declaration section. Some day the use of a sketch or last revision may exceed your attention span or memory.

Keep void loop() as short as possible. Putting all code in loop() is ok for development and testing, otherwise separate code into user functions() and call from void loop() in sequence or when conditions for use exist.


Simple Toggle Switch - 'on' and 'off' positions are maintained, pretty simple, do something if the pin input changes from one voltage to another. There is no output if the voltage does not change from one scan to another.

Momentary Toggle Switch or Simple Toggle Switch used as a pushbutton. If there is output for both 'on' and 'off positions, use the Simple Toggle Switch code. 'Jog' or increment/decrement functions may not have 'off' code. Use Simple Pushbutton code. Sometimes there is only a toggle switch on the workbench, use code appropriate to the job and return the switch toggle to the 'off' position after use.

Single Pole Double Throw Toggle Switch, may use the same code for both input pins, multiple variety of switches, both 'on' positions maintained, 'off' position may or may not be maintained, one or both 'on' positions may be momentary. And the code may not require output when the switch returns to, or passes through, the 'off' position from one or both 'on' positions. That code is not included in this sketch. For each input pin, do something if voltage changes from high to low and optionally from low to high. There is no output if the voltage does not change from one scan to another.

Simple Pushbutton OR A Rotary Switch connected to multiple input pins. Again pretty simple, do something if the pin input changes from HIGH to LOW. There is no output if the voltage changes from LOW to HIGH, or the voltage does not change from one scan to another. Can be used for rotary switches where the current position over rides prior output.

Push On/Push Off Pushbutton, do something if the pin input changes from HIGH to LOW. There is no output if the voltage changes from LOW to HIGH, or the voltage does not change from one scan to another. A boolean variable - exclusive to each switch - keeps track of the current state of the switch - on or off - and issues output accordingly


INPUTPINS() An excellent user function() for beginners learning about nested routines and loops. Watch for changes to the last five lines of the sketch when copying and pasting code to the sketch. A misplaced closing curly brace will really spoil your day.

Each input pin has a corresponding flag in the pin register 'stringoldstate'. This flag is used to tell whether the voltage at each input pin has changed. When the last scan of a pin was LOW, the corresponding character in the string is changed to '0'. A scan of a HIGH pin produces a '1'. I used 20 characters, one for each digital pin including the TX and RX pins and digital equivalent of the analog pins. However, the scan can start with digital pin 2 as in the sketch and the first cycle in the for() loop function is numerical 0. To match these two values subtract 2 from the pinNo variable in the line "oldpinStateSTR = String(stringoldstate.charAt(pinNo -2)); " and no further offset is required in the function. 'stringoldstate' is updated every pass through the function() in the second last line.

SOOOOOOOOOOOOOOO

Connect one post of each switch to ground (centre pin for SPDT switch) and other post or posts to a programmed digital pin. Change wiring on toggle switches when output is reversed.

CREATE A LOOP to scan every digital input pin of interest.
WITHIN THE LOOP()
- Read each designated digital in turn.
- Read the corresponding flag in 'stringoldstate'.
- Compare a stringified pin input to the flag.
AND IF THE TWO VALUES DIFFER:
- No matter which pinNo scan fails
- look at all possible code for any match to the pinNo. One will execute.
WHETHER THE TWO VALUES DIFFER OR NOT:
- The current loop is completed
- But before leaving the current loop ADD the current stringified value of pinNo to the end of 'stringnewstate'
START ANOTHER LOOP USING THE NEXT PIN NUMBER
OR
WHEN ALL LOOPS HAVE FINISHED
- Transfer the contents of the string 'stringnewstate' (one character for each pin) to the pin register 'stringoldstate'
void INPUTPINS() is now complete RETURN to void loop().

NOTE: Digital pin 13 cannot be used as an input with the 'blink' led circuit intact. The input pin voltage never rises high enough to trigger a HIGH level response. Include pin 13 in the pin 'for loop' for continuity into digital pins 14 to 19, but do not write 'test and respond' code for pin 13. You can remove the 'blink' led or the take up resistor from the board to fix this. Arduino ATMEGA 328 boards use pin 13 for default SPI communication. The 'blink' led may be the only physical indicator of SPI activity.

BushPilotWannabe
March 2018
*/

// Four Basic Switches Sketch
// Copy this to a new Arduino sketch page
// Highlight the following then hit 'Auto Format' in the 'Tools' tab to make the code easier to follow


String stringoldstate = "11111111111111111111"; // input pin level register
long delayTimer;
bool push_OnOff = false; // start push on/push off switch in the off position


void setup()
{
pinMode(2, INPUT); digitalWrite(2, HIGH); // SPST toggle switch -- code "C01" and "C02"
pinMode(3, INPUT); digitalWrite(3, HIGH); // SPDT toggle switch -- "Switch Off", "Switch Down"
pinMode(4, INPUT); digitalWrite(4, HIGH); // SPDT toggle switch -- "Switch Off", "Switch Up"
pinMode(5, INPUT); digitalWrite(5, HIGH); // Simple pushbutton -- "Simple Pushbutton"
pinMode(6, INPUT); digitalWrite(6, HIGH); // Push on/push off -- "Push On", "Push Off"
//pinMode(7, INPUT); digitalWrite(7, HIGH); // Future assignment
//pinMode(8, INPUT); digitalWrite(8, HIGH); // Future assignment
//pinMode(9, INPUT); digitalWrite(9, HIGH); // Future assignment
//pinMode(10, INPUT); digitalWrite(10, HIGH); // Future assignment
//pinMode(11, INPUT); digitalWrite(11, HIGH); // Future assignment
//pinMode(12, INPUT); digitalWrite(12, HIGH); // Future assignment
//pinMode(13, INPUT); digitalWrite(13, HIGH); // Future assignment
//pinMode(14, INPUT); digitalWrite(14, HIGH); // Future assignment -- analog pin 0
//pinMode(15, INPUT); digitalWrite(15, HIGH); // Future assignment -- analog pin 1
//pinMode(16, INPUT); digitalWrite(16, HIGH); // Future assignment -- analog pin 2
//pinMode(17, INPUT); digitalWrite(17, HIGH); // Future assignment -- analog pin 3
//pinMode(18, INPUT); digitalWrite(18, HIGH); // Future assignment -- analog pin 4
//pinMode(19, INPUT); digitalWrite(19, HIGH); // Future assignment -- analog pin 5
// CHANGE the Arduino Serial Monitor baud rate to 115200 (lower right corner of the monitor)
Serial.begin(115200); //
}// end void setup()


void loop() {
if (millis() > delayTimer) {
INPUTPINS();
delayTimer = millis() + 50;
}
}// end void loop()


void INPUTPINS() {
String pinStateSTR;
String oldpinStateSTR;
String stringnewstate = "";
int spdt_position = 0;

for (int pinNo = 2; pinNo <= 12; pinNo++) {
pinStateSTR = String(digitalRead(pinNo));
oldpinStateSTR = String(stringoldstate.charAt(pinNo -2));
if (pinStateSTR != oldpinStateSTR) { // value of pinStatSTR has changed since oldpinStateSTR was stored

//SIMPLE TOGGLE SWITCH
if (pinNo == 2) {
if (pinStateSTR == "0") {
Serial.println("C01");
}
else {
Serial.println("C02");
}
}// close pinNo 2

//SPDT TOGGLE SWITCH
if (pinNo == 3) { // change switch in any way to trigger -- cheap interrupt
spdt_position = (digitalRead(3) * (-1)) + (digitalRead(4) * 1);
switch (spdt_position) {
case -1: {Serial.println("Switch Down");} break; // switch off
case 0: {Serial.println("Switch Off");} break; // switch down
case 1: {Serial.println("Switch Up");} break; // switch up
}// close switch
}// close pinNo 3
if (pinNo == 4) { // change switch in any way to trigger -- cheap interrupt
spdt_position = (digitalRead(3) * (-1)) + (digitalRead(4) * 1);
switch (spdt_position) {
case -1: {Serial.println("Switch Down");} break; // switch off
case 0: {Serial.println("Switch Off");} break; // switch down
case 1: {Serial.println("Switch Up");} break; // switch up
}// close switch
}// close pinNo 4

//SIMPLE PUSHBUTTON
if ((pinNo == 5) && (pinStateSTR == "0")) {Serial.println("Simple Pushbutton");}


//PUSH ON/PUSH OFF PUSHBUTTON
if ((pinNo == 6) && (pinStateSTR == "0")) {
if (push_OnOff == false) { // switch was 'off' turn 'on'
Serial.println("Push On");
push_OnOff = true;
}
else { // switch was 'on' turn 'off'
Serial.println("Push Off");
push_OnOff = false;
}
}// close pinNo 6
}// close look for switch movement
stringnewstate += pinStateSTR;
}// close for loop
stringoldstate = stringnewstate;
}// end of inputpins