Hopefully, you’ve gotten skilled with blinking an LED. That may sound simple, but you’ve learned how to
That is no small feat.
We also learned about input and output devices. Output devices are things that perform an action liking blinking an LED light, and input devices are things that sense things about the world, like sensing that someone pressed a push button. When we combine both input and output devices in a single circuit, that circuit becomes truly interactive.
Most of those examples, rely on a basic pushbutton which is what we will experiment with here.
Pushbuttons were invented over 100 years ago. One of their first uses was in pocket flashlights by the EverReady company
These look old and dirty because, well, they are old, and they were used. In 1905 these would have been the equivalent of getting an iPhone 12. (I have no clue if that is true but it sounds true!). And if you are completely fascinated by the history of the pushbutton check out Rachel Plotnick’s book Power Button: A history of pleasure, panic, and the politics of pushing, which focuses on the history of the pushbutton from 1880 to 1925
Now back to our current topic. In this circuit, we are going to combine the LED, which is used in almost everything, with a pushbutton, which is also used in everything and our computer code will use an if statement, which, as you can predict, is used in almost all computer programs.
The way a push button works with the Arduino Uno is that when the button is pushed, the voltage goes LOW. Your board reads this and reacts accordingly. When the button is not pushed it will read HIGH (there is a longer explanation that we will ignore). The Uno can read that the button is HIGH and will react appropriately.
You will need the following parts:
4x Jumper Wires
The button we used is called a momentary switch. As long as you press on the button it will read LOW, and as soon as you release the button it will read HIGH. So the switch is on as long as you press it and it turns off as soon as you release it. Most push buttons in the modern world are momentary switches. The other type of push button is called latching. In latching push buttons when you press a button and release it the button stays pushed in and activated and turns off when you press it again.
We are going to add the push button to the same LED circuit from the first experiment following the Fritzing diagram below.
The shorter leg of the LED should be connected to the resistor and then ground.
Buttons have an orientation that is correct. The legs of the button protrude out of two sides of the button, while the other two side are bare. The sides with the legs should be on either side of the valley on the breadboard. Buttons have a tendency to fall out of the breadboard holes. To get a secure connect, you can use your finger nail tips to securely seat the button on the breadboard.
In our first experiment when we connected an LED to a pin on the Arduino Uno, in our setup code we declared:
pinMode(redLed, OUTPUT);
What do you think the pinMode will be for a button?
If you think INPUT you would be 100% correct …. except there is a wrinkle. For buttons we will use a special kind of input called INPUT_PULLUP
pinMode(button, INPUT_PULLUP)
That line of code will go into our setup()
With LEDs to turn them on and off we used digitalWrite
. What do you think we will use to see if a button is pressed?
If you think digitalRead
again, you would be 100% correct.
digitalRead(pushButton);
It’s a good idea to sketch out what we want to do in English before we code (or use your favorite language - 私たちがやりたいことをスケッチするのは良い考えです)
And what better place to do it then your lab notebook:
Now we have a pretty good idea of what we want to do. And because we are beginners, let’s copy that idea into our code as comments. So we might have
int led = 13;
int pushButton = 3;
void setup() {
pinMode(led, OUTPUT);
pinMode(pushButton, INPUT_PULLUP);
}
void loop() {
// if button is pressed
// turn on the LED
// else
// turn off the led
}
We already know how to write the lines to turn the led on and off so let’s add them in:
...
void loop() {
// if button is pressed
// turn on the LED
digitalWrite(led, HIGH);
// else
// turn off the led
digitalWrite(led, LOW);
}
Ok. The state of the button will be LOW if the button is pressed and HIGH if it is not. We can get the current state of the button using
digitalRead(pushButton)
and we want to check if it is pressed (LOW):
if (digitalRead(pushButton) == LOW)
The complete code for the loop() would then be
...
void loop() {
// if button is pressed
if (digitalRead(pushButton) == LOW){
// turn on the LED
digitalWrite(led, HIGH);
} else {
// else
// turn off the led
digitalWrite(led, LOW);
}
}
the general template for an if statement is
if (somecondition){
statement1
statement2
statement3
} else {
statement4
statement5
}
So if some condition is true the computer executes statements 1, 2, and 3. If it is false it will execute 4 and 5. The braces {} delimit what statements to execute. In our case of the one LED, we execute just a single statement in the if (turning the LED on) and a single statement in the else (turning it off), but we could have as many statements as we need.
Let’s put this all together in our finished code:
int led = 13;
int pushButton = 3;
void setup() {
pinMode(led, OUTPUT);
pinMode(pushButton, INPUT_PULLUP);
}
void loop() {
// if button is pressed
if (digitalRead(pushButton) == LOW){
// turn on the LED
digitalWrite(led, HIGH);
} else {
// else
// turn off the led
digitalWrite(led, LOW);
}
}
Recall that part of bullet 1, work to code, is that all lines within void setup
and void loop
need to be indented. A continuation of this practice is that all lines within an if block and an else block are indented as shown above. Again, if you come back to your code a week from now – or are seeking help now– it is easier to read the version above then this version:
int led = 13;
int pushButton = 3;
void setup() {
pinMode(led, OUTPUT);
pinMode(pushButton, INPUT_PULLUP);}
void loop() {
if (digitalRead(button) == LOW){
digitalWrite(led, HIGH);} else {
digitalWrite(led, LOW);}
}
Copy and paste the indented version of our code into the IDE. Then upload.
When you hold down the push button, those warm fuzzy feelings from the first experiment should happen again, and the LED should shine brightly. The LED will be off when the button is released.
We have already been using digitalWrite to turn on an LED. When we see an expression containing parentheses like
int redLed = 2;
...
digitalWrite(redLed, HIGH);
we call the items within the parentheses arguments. In this digitalWrite example,
HIGH
means we are setting pin 2 to a positive voltage. LOW
means we are setting it to ground.Now let’s look at the argument for digitalRead.
int button = 3;
...
digitalRead(button);
If you look at the hardware you constructed you can see that when you press the button pin 3 is connected to ground (GND
). If we do a digitalRead
while pressing the button we will read LOW
. If we do a digitalRead
while not pressing the button we will read HIGH
.
if
statementsImagine if your friend Clara said I’ll go to the party if Ann goes, else I’ll stay home. Now let me ask you a question. Barring unforeseen circumstances, if we see Ann at the party do we think Clara is there? And a second question. If we know Ann didn’t go, (and again barring unforeseen circumstances) do we think Clara went to the party? I imagine you have zero problems figuring this out.
Let’s now look at the psuedo code we wrote above:
Just looking at this we know, without any formal computer science training, what happens when we press the button.
Congratulations. You have fantastic intuitions about if-else statements. Now let’s look at this part of the loop part of our code:
void loop() {
// if button is pressed
if (digitalRead(button) == LOW){
// turn on the LED
digitalWrite(led, HIGH);
} else {
// else
// turn off the led
digitalWrite(led, LOW);
}
}
The ==
means equal so we can read
if (digitalRead(button) == LOW)
as meaning if the value when we read the button is LOW or even a more English-like description: if the button is pressed then
The braces ({}
) delimited the block of code that should be executed if the if
statement is true. In this case if the button is pressed we only execute one line:
digitalWrite(led, HIGH);
If the button is not pressed we only perform the else
block which turns off the led.
Again, the braces ({}
) delimited the block of code that should be executed if the if
statement is true. Suppose we want to turn on the redLED
and blueLED
and turn off the greenLED
if the button is pressed. In that case we would put all three statements inside the braces {}:
if (digitalRead(button) == LOW){
//we pushed the button
digitalWrite(redLED, HIGH); //so turn on the redLED
digitalWrite(blueLED, HIGH); //so turn on the blueLED
digitalWrite(greenLED, HIGH); //so turn off the greenLED
}
What does the following do?
if (pushButtonState == LOW) {}
digitalWrite(led1, HIGH);
digitalWrite(led2, HIGH);
digitalWrite(led3, HIGH);
}
else
{
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
}
and what about this one:
int wait = 500;
...
if (pushButtonState == LOW) {}
digitalWrite(led, HIGH);
delay(wait);
digitalWrite(led, LOW);
delay(wait);
}
else
{
digitalWrite(led, LOW);
}
In the first case, if we press the button all three leds will be on and when we release the button the leds will be off. In the second example, if we press the button an led will blink.
Programming languages allow us to do the normal comparisons we might have seen in math classes:
expression | name | example | meaning |
---|---|---|---|
== | Equal | age == 21 | is age equal to 21? |
!= | Not Equal | age != 21 | Is the value of age not equal to 21? |
< | Less Than | age < 21 | Is age less than 21? |
> | Greater Than | age > 21 | Is age greater than 21? |
<= | Less Than or Equal to | age <= 21 | Is age less than or equal to 21? |
>= | Greater Than or Equal To | age >= 21 | Is age greater than or equal to 21? |
So, for example, if the variable temperature
represents the current temperature then
if (temperature < 90) {}
digitalWrite(led, HIGH); //so turn on the LED
}
else
{
digitalWrite(led, LOW);
}
would turn on the led if the temperature was less than 90.
Consider the following psuedocode
What happens in the following cases?
Take a moment to figure it out. When you are ready compare your intuitions to mine, highlight (select the region with your laptop trackpad) the following seemingly whitespace to reveal the answer.
Select the region right after this line.
I am hoping you are thinking that the led is turned on for case (3), only when both buttons are pressed. If only one of the buttons is pressed the led does not go on.
The code for this puzzler would be
void loop() {
// if button is pressed
if ((digitalRead(button1) == LOW) &&
(digitalRead(button2) == LOW)){
// turn on the LED
digitalWrite(led, HIGH);
} else {
// else
// turn off the led
digitalWrite(led, LOW);
}
}
As you can see the English and gets translated into computer code as &&
and the expressions that the &&
connects are bounded by parentheses.
Next, consider this version:
and let’s ask the same questions: What happens in the following cases?
Again, the answer can be revealed in the whitespace:
In this case in cases 1, 2, and 3 the led is on, and in case 4 it is off.
The English or is translated into computer code as ||
(we rarely type the vertical bar but it is there on the right of your laptop keyboard).
The code for this example would be
void loop() {
// if button is pressed
if ((digitalRead(button1) == LOW) ||
(digitalRead(button2) == LOW)){
// turn on the LED
digitalWrite(led, HIGH);
} else {
// else
// turn off the led
digitalWrite(led, LOW);
}
}
With these building blocks the Arduino Uno can make complex decisions based on the input it is getting. Consider
void loop() {
if ((digitalRead(button1) == LOW) && (digitalRead(button2) == LOW)){
// turn on the LED
digitalWrite(redLed, HIGH);
digitalWrite(blueLed, LOW);
digitalWrite(greenLed, LOW);
} else if (digitalRead(button1) == LOW) {
digitalWrite(redLed, LOW);
digitalWrite(blueLed, HIGH);
digitalWrite(greenLed, LOW);
} else {
digitalWrite(redLed, LOW);
digitalWrite(blueLed, LOW);
digitalWrite(greenLed, LOW);
}
}
And again, what happens in the following cases?
And the answer is ….
Now if at this point, you are slightly confused, or just don’t care about all this, don’t fear throughout the course we are going to practice so we become a bit more fluent and are able to use Logic Like A Vulcan.
One of the things that makes the Arduino Uno (and any computer) so useful is that it can make complex decisions based on the input it’s getting. For example, you could make a thermostat that turns on a heater if it gets too cold, or a fan if it gets too hot, and it could even water your plants if they get too dry. As we have seen, in order to make such decisions, the programming language provides a set of logic operations that let you build complex “if” statements.
For example suppose we want to turn on an led only if the temperature is between 65 and 75 inclusive and the led should be off otherwise. We can do this using the AND
operator &&
:
if ((temperature >= 65) && (temperature) <=75){
digitalWrite(led, HIGH); //so turn on the LED
}
else
{
digitalWrite(led, LOW);
}
Using these logic operators, you can program your Arduino Uno to make intelligent decisions and take control of the world around it!
Add another LED and another button. Both LEDs should blink 200ms on and 200ms off only when both buttons are pressed. Otherwise both LEDs will be off.
We are going to use the patterns we constructed for experiment one: double tap, slow n fast, and Cylon. Here is the behavior of your circuit:
1: Tutorials are CC BY-SA 4.0. Original page at Sparkfun Inventor’s Kit for Photon. This slight remix by Ron Zacharski.