How to Read a Switch
So far we've covered how to blink an LED on and off and how to flicker an LED using an analogue output value, it's time to start reading and reacting to inputs to the controller. This means adding some additional hardware to read from, but today that can be a simple as a single wire on a prototyping breadboard. One end of the wire is connected to the D1 input and the other end is swapped between the 3V3 pin and the GND pin to create High/Low input signals. The initial code to read this is impressively simple, we're also going to leave some LED code in the demo so that we can easily see what value is being read by the controller.
// Define the input pins | |
const uint8_t btnPin = D1; | |
// Define the output pins | |
const uint8_t ledPin = LED_BUILTIN; | |
uint8_t btnValue; | |
void setup() { | |
pinMode(btnPin, INPUT); // Initialise the btn pin as an input | |
pinMode(ledPin, OUTPUT); // Initialise the LED pin as an output | |
} | |
void loop() { | |
btnValue = digitalRead(btnPin); | |
digitalWrite(ledPin, btnValue); | |
} |
When you load this example you should see that the LED turns on when the wire is connected to GND (remember the LED_BUILTIN is active low) and the LED turns off when the wire is connected to 3V3. This system works but has a downside, the input pin only changes state when the wire is connected to the new pin. When the wire is disconnected and left 'floating' you're unable to tell if the wire has actually been disconnected or not.
A floating voltage like this can be removed/detected by using a pull up resistor. When the wire is disconnected from GND, the pull up resistor brings the voltage immediately up to 3V3 which gives a much more definitive response to the wire being disconnected/button is released. Thankfully most arduino devices have these resistors built into the controller and they can be configured by using 'INPUT_PULLUP' in the pinMode function. The other bonus is that you only need to run two wires to your external switch, the data line and GND.
By changing the pin mode to use the input pullup, in the above example, we can see that the LED turns on when the wire is connected and turns off again as soon as the wire is disconnected. Playing with this arrangement a bit should illustrate our next issue. The wire may not always connect and disconnect smoothly as metal scrapes against metal, this may cause the LED to appear to flicker slightly as the wire is inserted. There may be some 'electrical noise' on the input pin and if we attempt to read the pin during this noise the input may appear to be off when it should be on.EVERY_N_MILLISECONDS(INTERVAL) { | |
btnOldValue = btnCurValue; | |
btnCurValue = digitalRead(btnPin); | |
if (btnOldValue == btnCurValue) { | |
digitalWrite(ledPin, btnCurValue); | |
} | |
} |
void loop() { | |
EVERY_N_MILLISECONDS(INTERVAL) { | |
btnOldValue = btnCurValue; | |
btnCurValue = digitalRead(btnPin); | |
if (btnUp()) { | |
// The button has just been released. Reset the counter | |
btnCount = 0; | |
} else if (!btnCurValue) { | |
// Add to the count for each loop the button is held down | |
// Prevent the counter from overflowing by limiting to 250 | |
if (btnCount < 250) { | |
btnCount++; | |
} | |
} | |
} | |
} | |
bool btnUp() { | |
return !btnOldValue & btnCurValue; | |
} | |
bool btnDown() { | |
return btnOldValue & !btnCurValue; | |
} |