This is an old revision of the document!
[Fritzing or photo of final main circuit for this lesson] Fritzing parts here: https://github.com/digistump/OakCore/issues/38
This lesson will show you how to connect a tactile switch (button) to your Oak and use it to control a sketch. In the examples we will turn a LED on and off by pushing the button.
| Part | Quantity | Identification |
|---|---|---|
| Oak with soldered headers | 1 | |
| Breadboard | 1 | |
| 5mm RGB Common Cathode LED | 1 | |
| 330R Resistor | 1 | Orange-Orange-Red |
| 10K Resistor | 1 | Brown-Black-Orange |
| 12mm Tactile Button | 1 |
[NOTE: You can find an index of the parts in the starter and ultimate kits here: Starter and Ultimate Kit Parts List]
Pull-Down Resistor: In this lesson we will use a Pull-Down resistor to make sure we can reliably detect button presses. If an I/O pin is 'left floating' reading it's value can result in either HIGH or LOW. By attaching a resistor between the I/O pin of the Oak and GND we can ensure that if the button is not pressed, the state is always LOW.
[Fritzing diagram of pull-down vs floating]
Interrupt: A method to attach code (small functions!) to the state change of a pin. The supported triggers are:
It's important to note that an Interrupt actually interrupts what you're doing! So keep your interrupt handlers as simple as possible. Otherwise they might interfere with other time-sensitive operations.
[Fritzing diagram of hooking the Oak to the Button with resistor, the LED and the breadboard] Steps to make these connections, things to watch out for (polarity, resistor codes etc)
The simple mode allows you to check for the current button state and react accordingly. This example assumes Pin 6 for the button and Pin 9 for the LED. You can define these at the top section of your sketch like this:
#DEFINE BUTTON_PIN 6 #DEFINE LED_PIN 9
Because the Oak has to know how the pins will be used, you will have to set the pinMode as follows: This requires the following code in setup():
void setup() {
pinMode(BUTTON_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
}
And to finish the sketch, use the following loop code:
void loop() {
if(digitalRead(BUTTON_PIN) == LOW) {
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(LED_PIN, LOW);
}
}
The code above will check the state of the BUTTON_PIN. If the state is LOW (which means: button pressed) the LED will turn on for as long as the button is pressed. Releasing the tactile switch turns the LED off again.
So getting the button to work isn't that hard, but what if you want to do other stuff in your loop as well? We can use interrupts for that! Start by adding the handle_button method to your sketch:
void handle_button() {
bool btn_state = digitalRead(BUTTON_PIN);
digitalWrite(LED_PIN, btn_state);
}
For readability we first assign the current state to the bool state. If the button is pressed, the pin is perceived as HIGH (or: true). If the button is released, it is perceived as LOW (or: false). Then we set the LED to the current state of the button.
Then, replace line where you set the pin mode for BUTTON_PIN so that it looks like this:
void setup() {
pinMode(LED_PIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handle_button, CHANGE);
}
This assigns the handle_button function to the interrupt signal. Now because we're using the interrupt instead of polling, you can just keep the loop() empty, or do something else with it.
In this lesson you learned how to read a button state using digitalRead and attachInterrupt. Of course it doesn't have to stop at a single button, all digital I/O pins on the Oak can be used to handle interrupts!