Read The Arduino Inventor's Guide Online
Authors: Unknown
Take out your breadboard and wire up a single LED and a button, as shown in
Figures 4-9
and
4-10
. You’ll use this prototype to test your code before building the final Reaction Timer.
FIGURE 4-9:
Wiring diagram for the Reaction Timer circuit
FIGURE 4-10:
Final prototype circuit of the Reaction Timer with a single button and a single LED
As you connect this circuit, note the two different resistance values: 330 Ω for the LED and 10 kΩ for the push button. (See “
Resistors and Bands
” on page
308
for details on how to determine the value of a resistor from its color bands.) The resistor on the LED
is a current-limiting resistor and should be tied to ground, while the resistor on the push button is a pull-up resistor connecting pin 3 to 5 V. But your circuit can’t do anything without the code, so let’s look at that now.
As your sketches and circuits become more complex, you’ll find it helpful to organize your thoughts by listing each action you want the Arduino to take, in the order you want it to happen. Some programmers refer to a list like this as
pseudocode
. Here’s our pseudocode for the Reaction Timer:
1. Wait a random amount of time before turning on the LED (to prevent predicting/gaming the Reaction Timer).
2. Turn on the LED.
3. Record the starting time.
4. Start a timer and wait for a button press.
5. When the button is pressed, calculate the reaction time as the timer value minus the starting time.
6. Report the time back.
Pretty simple, right? Let’s open up Arduino and look at the sketch.
Open a new sketch and type the initialization and the
setup()
code shown in
Listing 4-1
.
LISTING 4-1:
setup()
and initialization code for the Reaction Timer
➊
unsigned int
waitTime;
//random wait time before
//turning on LED
unsigned int
startTime;
//zero reference time
unsigned int
reactTime;
//calculated reaction time
void
setup
()
{
➋
Serial
.
begin
(9600);
//sets up serial
//communication
pinMode
(13, OUTPUT);
//sets pin 13 as an OUTPUT for the
//stimulus LED
➌
pinMode
(3, INPUT);
//sets pin 3 as an INPUT for the
//button
}
NOTE
The
unsigned int
data type can hold values from 0 to 65,535 (2
16
– 1).
First, the namespace defines three
unsigned int
variables
➊
to store the
waitTime
,
startTime
, and
reactTime
values.
Next comes the
setup()
function, which has a new instruction:
Serial.begin(9600)
➋
. Make sure to capitalize
Serial
and leave no spaces between
Serial
, the period, and
begin
. This instruction is a little different from previous commands because it has a period that divides the
object
and the
method
. An
object
is a concept used in computer programming that is similar to a special type of variable that can have different functions or actions. Here
Serial
is the name of the object we’re using. The functions that an object can perform are called
methods
. The
begin()
method initializes or begins
serial communication
between your Arduino and your computer, which allows the Arduino to send and receive data through the USB cable. For this command, the number in the parentheses,
9600
, sets the communication rate to 9,600 bits per second (or
baud
). The Arduino will use serial communication to report your reaction time back to your computer. The
Serial
object has many other methods, which we’ll introduce throughout this book, to handle data between the computer and the Arduino.
Finally, you’ll set up your pins. This project uses a single LED on pin 13 to indicate when to press the button, so you once again use pin 13 as an
OUTPUT
using the
pinMode()
function. Then set pin 3 with the
pinMode()
function
➌
using the
INPUT
keyword. You use
INPUT
here because Arduino needs to be able to detect button presses, not output to the button.
Now let’s write the
loop()
part of the sketch. Enter the code in
Listing 4-2
after your
setup()
function.
LISTING 4-2:
The
loop()
function for the Reaction Timer
void
loop
()
{
//prints the challenge instructions
➊
Serial
.
println
(
"When the LED turns on, push the button!"
);
Serial
.
println
(
"Now, watch the LED. Ready?"
);
➋
waitTime =
random
(2000, 4000);
//random wait time
//from 2000 to 4000 ms
➌
delay
(waitTime);
//delay random wait time
//turn on the LED!
digitalWrite
(13,
HIGH
);
startTime =
➍
millis
();
//set zero time reference
//loop to wait until button is pressed
➎
while
(
digitalRead
(3) ==
HIGH
)
{
}
➏
reactTime =
millis
() - startTime;
//calculation of
//reaction time
digitalWrite
(13,
LOW
);
//turn off LED!
//display information to Serial Monitor
➐
Serial
.
print
(
"Nice job! Your reaction time was "
);
➑
Serial
.
print
(reactTime);
➒
Serial
.
println
(
" milliseconds"
);
delay
(1000);
//short delay before starting again
}
First, this code uses the
Serial.println()
method
➊
to show a message prompt explaining how to play the game. The
println()
method sends text to the computer and adds a newline character to move the cursor down one line. When this method is called, any text between quotation marks (
" "
) is displayed on the Arduino IDE’s Serial Monitor. The Serial Monitor is like a simple chat window, or
terminal
, that allows you to send and receive data between the Arduino and your computer. You can open the Serial Monitor by clicking the magnifying glass button in the top-right corner of the Arduino IDE (shown in
Figure 4-11
), by clicking Tools
▸
Serial Monitor, or by using the hotkey
CTRL
-
SHIFT
-M.
FIGURE 4-11:
Opening the Serial Monitor through the Arduino IDE
We’ll look at the Serial Monitor in just a moment.
To make the Reaction Timer less predictable, the sketch calls the
random()
function
➋
to generate a random
waitTime
. The
random()
function takes a minimum value and a maximum value as arguments and returns a
pseudorandom number
(a number that appears to be random but isn’t; this is explained in more detail in “
Try It Out: Make
waitTime
More Random
” on page
109
). In this example, the
waitTime
variable is set to a “random” number between 2,000 and 4,000 and is passed to
delay()
➌
before the LED turns on. This prevents you and your friends from predicting when to press the button.
When the LED turns on, a call to the
millis()
function
➍
captures the starting time. The
millis()
function checks the Arduino’s internal timer and returns the number of milliseconds since the Arduino was turned on or reset. The
millis()
function is handy for any Arduino project that involves timing.
After fetching the start time, the sketch uses a
while()
loop
➎
to wait for a button press. In Arduino, as in many other programming languages, a
while()
loop runs the code inside its curly brackets as long as the expression between its parentheses is
true
. In this case, the expression is
digitalRead
(3) ==
HIGH
The
digitalRead()
command reads the voltage on the pin specified between the parentheses and returns a value of
HIGH
or
LOW
depending on if it sees 5 V or GND. This call checks the voltage on pin 3. Remember that pull-up resistor on the push button? The button’s normal state is open, and the pin defaults to
HIGH
until you press the button to close the circuit. When you press the button, pin 3 connects to ground, and the state becomes
LOW
. The double equal sign (
==
) checks equality. (See “
Logical Comparison Operators
” on page
106
.)
As long as the button isn’t pressed, the expression is
true
, and the
while()
loop should repeat, preventing the sketch from executing any code after. Notice, however, that there’s no actual code inside the loop. This is referred to as a
holding
or
blocking loop
, and rather than executing any code itself, it just prevents other code from executing. When the button is pressed, the expression becomes
false
, and the sketch proceeds.