Chapter 3
IN THIS CHAPTER
Reading the status of push buttons
Generating random numbers
Using a potentiometer as input
In this chapter, you learn some additional Arduino programming techniques that will become invaluable in your Arduino projects. Specifically, you learn how to handle input data in the form of push buttons, how to generate random numbers that will make your programs more interesting by adding a degree of randomness, and how to read the value of a potentiometer.
In Chapter 2 of this minibook, you learn how to connect an LED to an Arduino I/O pin and turn the LED on or off by using digitalWrite function in an Arduino program. The digitalWrite function uses the I/O pins as output pins by setting the status of an I/O pin to HIGH or LOW so that external circuitry (such as an LED) can react to the pin’s status.
But what if you want to use an I/O pin as an input instead of an output? In other words, what if you want the Arduino to react to the status of an external circuit instead of the other way around? The easiest way to do that is to connect a push button to an I/O pin. Then, you can add commands to your Arduino program to detect whether the push button is pressed.
There are two ways to connect a push button to a Arduino I/O pin:
Figure 3-1 shows examples of both active-high and active-low push buttons. In the active-high circuit, the I/O pin is connected to ground through resistor R1 when the push button is not pressed. Thus, the voltage at the I/O pin is 0. When the push button is pressed, the I/O pin is connected to through R1, causing the I/O pin to see . As a result, the I/O pin is LOW when the button is not pressed and HIGH when the button is pressed.
In the active-low circuit, the I/O pin is connected to through R1, causing the I/O pin to go HIGH. But when the button is pressed, the current is shorted to ground through R1, causing the voltage at the I/O pin to drop to zero. Thus, the I/O pin is HIGH when the button isn't pressed and LOW when the button is pressed.
Once you’ve connected a switch to an Arduino I/O pin, you need to know how todetermine whether the switch is open or closed from an Arduino program. The easiest way to do that is to first designate the pin as an input pin by calling the pinMode function, and then checking the status of the input pin by calling the digitalRead function. The digitalRead function returns 0 or 1 depending on the current status of the input pin.
For example, you can designate pin 10 as an input pin like this:
pinMode(10, INPUT);
Then, to get the status of the pin, you could call digitalRead like this:
int Pin10Status;
Pin10Status = digitalRead(10);
The digitalRead function returns the current status of pin 10 and stores it in an int variable named Pin1Status. You can then test the status of the pin in an if statement:
if (Pin10Status == 1)
{
// The switch has been pressed!
}
In many cases, you can shorten your code by skipping the need for a variable to store the result of the pinRead function, like this:
if (digitalRead(10))
{
// The switch has been pressed!
}
Notice in the preceding if statement that two consecutive right parentheses are required. The first one closes the list of arguments passed to the digitalRead function; the second one closes the expression in the if statement.
Here’s an example that lights an LED on pin 0 if the user presses the button on pin 10 and turns on the LED when the button is released:
if (digitalRead(10))
{
digitalWrite(0, HIGH);
}
Else
{
digitalWrite(0, LOW);
}
Here, the LED on pin 0 is made HIGH if the button is pressed and LOW if the button isn’t pressed.
Listing 3-1 shows an interesting program that works with an Arduino that has a push button switch connected to pin 10 and LEDs connected to pins 0 and 1. The program flashes the LED connected to pin 0 on and off at quarter-second intervals until the push button switch is depressed. Then, it flashes the LED on pin 1.
LISTING 3-1 The Push Button Program
// The LED Flasher Program with a Push Button
// Doug Lowe
// September 16, 2016
//
// This program flashes one of two LEDs connected to
// pins 0 and 1, depending on whether the push button on
// pin 10 is pressed.
void setup() {
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
pinMode(10, INPUT);
}
void loop() {
if (digitalRead(10) == 1)
{
digitalWrite(0, HIGH);
delay(250);
digitalWrite(0, LOW);
delay(250);
}
else
{
digitalWrite(1, HIGH);
delay(250);
digitalWrite(1, LOW);
delay(250);
}
}
Project 45 shows how to build a simple circuit you can use to test the program in Listing 3-1, and Figure 3-2 shows the completed circuit.
In this project, you connect a breadboard with two LEDs and a push button to an Arduino UNO board.
Insert the resistors.
: J4 to ground
: J8 to ground
: J28 to ground
LED |
Anode |
Cathode |
LED1 |
I6 |
I4 |
LED2 |
I10 |
I8 |
Insert the push button.
The pins should be inserted in E26, F26, E28, and F28 such that the switch opens and closes across rows 26 and 28.
Breadboard |
Digital Pin |
J6 |
0 |
J10 |
1 |
H28 |
10 |
Connect the ground bus to the UNO board ground.
Use a jumper to connect any hole in the ground bus on the breadboard to either of the GND pins on the UNO board.
Connect the positive bus to the UNO board .
Use a jumper to connect any hole in the ground bus on the breadboard to the 5 V pin on the UNO board.
Connect the UNO to the computer.
Use the mini-B USB connector.
Upload the Flashing LED program (see Listing 3-1) to the UNO.
LED2 will flash on an off a quarter-second intervals. If you press the push button, LED1 will flash instead.
Many computer-controlled applications require a degree of randomness to their operation. A classic example is the Indiana Jones ride at Disneyland and Disney World. Every time you go on this ride, the adventure is slightly different. At the start, there are three doors that your vehicle can drive through; the exact door chosen for your ride is determined randomly. Many other details of the ride are randomly varied in an effort to make the adventure slightly different every time you ride it.
You can add a bit of randomness to your own Arduino programs by using the random function. This function returns a random number whose value lies within a range that you specify via a pair of arguments.
The first argument indicates the minimum value you want returned. Somewhat confusingly, the second argument is one greater than the maximum value you want. For example, if you want a value within the range of 1 to 10, you would call the random function like this:
random(1,11);
Listing 3-2 shows a sample program that lights LED1 (pin 0) until the push button on pin 14 is pressed. Then, it switches to LED2 (pin 2) for a random period of time between 1 and 5 seconds. It then switches back to LED1. This program will work with the circuit you built for Project 45.
Note that the program does a bit of math for the delay function. The random function generates a number between 1 and 5, and the delay function multiplies this number by 1,000 to delay the appropriate number of seconds.
LISTING 3-2 The Random Program
// Random Program
// Doug Lowe
// September 16, 2016
//
// This program turns on the LED at pin 1 for a random
// number of seconds between 1 and 5 when the push
// button on pin 10 is pressed. When the push button is
// not pressed, the LED on pin 0 is turned on.
void setup() {
pinMode(0, OUTPUT);
pinMode(10, INPUT);
}
void loop() {
if (digitalInput(10) == 1)
{
digitalWrite(0, LOW);
digitalWrite(1, HIGH);
delay(random(1, 6) * 1000);
digitalWrite(1, LOW);
digitalWrite(0, HIGH);
}
}
Each time you press the push button in this program, the LED on pin 1 lights up for a different length of time, between 1 and 5 seconds.
Thus, the program in Listing 3-2 always generates the same sequence of random delays. In particular, the sequence for the first ten button presses will always be as follows:
This sequence appears fairly random, but every time you reset the program and start over, the sequence will be identical.
You can get around this lack of true randomness by calling the randomSeed function to provide a seed value for the random function. The seed value provides a starting point within the sequence of random numbers generated by the random function. If you use a different seed value each time the program runs, you’ll get a different random sequence each time.
So, how do you use a different seed value? You can do that easily enough by using the millis function, which returns the number of milliseconds that the program has been running. If you call the millis function when the user presses a button, and use its return value to seed the random number calculation, you’ll get a truly random result.
Listing 3-3 shows an improved version of the random program that uses this technique to create a truly random delay. It turns out that only one additional line of code is needed to properly randomize the delay:
randomSeed(millis());
This line reseeds the random number generator each time the button is pressed. Thus, a true random value is generated.
LISTING 3-3 An Improved Version of the Random Program
// Random Program
// Doug Lowe
// September 16, 2016
//
// This program turns on the LED at pin 1 for a random
// number of seconds between 1 and 5 when the push
// button on pin 10 is pressed. When the push button is
// not pressed, the LED on pin 0 is turned on.
void setup() {
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
pinMode(10, INPUT);
}
void loop() {
if (digitalInput(10) == 1)
{
randomSeed(millis());
digitalWrite(0, LOW);
digitalWrite(1, HIGH);
delay(random(1, 6) * 1000);
digitalWrite(1, LOW);
digitalWrite(0, HIGH);
}
}
As you know, a potentiometer (often called a pot) is simply a variable resistor with a knob you can turn to vary the resistance. Pots of various types are often used as input devices for Arduino projects. For example, you might use a simple pot to control the speed of a pair of flashing LEDs: As you turn the pot’s knob, the rate at which the LEDs flash changes.
The Arduino can read the value of a pot directly using any of its six analog input ports. On the Uno board, these ports are located on a six-pin header that’s on the opposite side of the digital ports. Each of these ports converts a voltage level between 0 V and a reference voltage to a integer between 0 and 1023. Although you can change the reference voltage for an analog port, we’ll use the standard reference voltage of .
Figure 3-3 shows how simple it is to connect a potentiometer to an Arduino. Here, the two outside terminals of the potentiometer are connected to ground and , respectively, and the middle terminal is connected to an analog input port.
To read the value of an analog input in an Arduino program, you use the analogRead function. This function accepts the number of the port to be read as an argument and returns a number between 0 and 1023 to indicate the voltage at the input relative to the reference voltage of . Thus, if the voltage is 2.5 V, the analogRead function will return 511.
Listing 3-4 shows a simple program that alternately flashes LEDs connected to pins 0 and 1. The rate at which the LEDs flash is set by a potentiometer on analog pin 0. As you can see, the program simply uses the value returned by the analogRead function as the delay between flashes. Thus, as the user turns the potentiometer’s knob, the flash rate varies between 0 and a tad over one second.
LISTING 3-4 An LED Flashing Program That Uses a Pot
// Variable Rate Flasher
// Doug Lowe
// September 16, 2016
//
// This program flashes a pair of LEDs on pins 0 and 1
// at a rate set by a potentiometer on analog input pin
// 0.
int Rate;
void setup() {
pinMode(0, OUTPUT);
pinMode(1, OUTPUT);
}
void loop() {
Rate = analogRead(0);
digitalWrite(0, LOW);
digitalWrite(1, HIGH);
delay(Rate);
digitalWrite(1, LOW);
digitalWrite(0, HIGH);
delay(Rate);
}
Project 46 shows how to build a circuit that includes a potentiometer so that you can test the code in Listing 3-4. Figure 3-4 shows the completed circuit.
In this project, you connect a breadboard with two flashing LEDs and a potentiometer that controls the rate at which the LEDs flash.
Insert the resistors.
: J8 to ground
: J4 to ground
LED |
Anode |
Cathode |
LED1 |
G10 |
G8 |
LED2 |
G6 |
G4 |
Insert the potentiometer.
The pins should be inserted in F24, F26, and F28.
Breadboard |
Uno Pin |
J10 |
Digital 0 |
J6 |
Digital 1 |
J26 |
Analog 0 |
Connect the ground bus to the UNO board ground.
Use a jumper to connect any hole in the ground bus on the breadboard to either of the GND pins on the UNO board.
Connect the positive bus to the UNO board .
Use a jumper to connect any hole in the ground bus on the breadboard to the 5 V pin on the UNO board.
Connect the UNO to the computer.
Use the mini-B USB connector.
Upload the Variable-Rate Flasher (see Listing 3-4) to the UNO.
The LEDs will alternately flash at a rate determined by the potentiometer. When you turn the knob on the potentiometer, the rate of flashing will increase or decrease.