Arduino Ebook Notes
Arduino Ebook Notes
Audience
This tutorial is intended for enthusiastic students or hobbyists. With Arduino, one
can get to know the basics of micro-controllers and sensors very quickly and can
start building prototype with very little investment.
Prerequisites
Before you start proceeding with this tutorial, we assume that you are already
familiar with the basics of C and C++. If you are not well aware of these
concepts, then we will suggest you go through our short tutorials on C and C+
+. A basic understanding of microcontrollers and electronics is also expected.
v
Contents
1 Getting Started 1
1.1 What is a Microcontroller?....................................................1
1.2 Install the Software..............................................................3
1.3 The Integrated Development Environment (IDE).................5
1.4 Our first circuit.....................................................................7
1.5 Updated Circuit....................................................................9
1.6 Our First Program................................................................9
1.7 Comments...........................................................................12
1.8 Gotchas...............................................................................13
1.9 Exercises.............................................................................14
3 Input 33
3.1 Pushbuttons........................................................................33
3.2 Potentiometers....................................................................41
3.3 RGB LEDs...........................................................................46
Contents
3.4 Exercises............................................................................. 49
4 Sound 51
4.1 Our Circuit..........................................................................51
vi 4.2 Simple note.........................................................................52
4.3 Music.................................................................................. 53
4.4 Music with functions...........................................................55
4.5 Exercises............................................................................. 58
7 Sensors Galore 91
7.1 Introduction........................................................................91
7.2 Photo Cell (Light Sensor)....................................................91
7.3 Tilt Sensor...........................................................................93
7.4 Reed Switch (Magnetic Field Detector)..............................95
7.5 Piezo Element (Vibration sensor).......................................96
7.6 Exercises............................................................................. 98
10
Next Steps 113
viii
. . . .
C.3 Chapter 3 Solutions . . . . . . . . . . . . . . . . . . . . . . .135
. . . .
C.4 Chapter 4 Solutions . . . . . . . . . . . . . . . . . . . . . . .140
. . . .
C.5 Chapter 5 Solutions . . . . . . . . . . . . . . . . . . . . . . .144
. . . .
C.6 Chapter 6 Solutions . . . . . . . . . . . . . . . . . . . . . . .149
. . . .
C.7 Chapter 7 Solutions . . . . . . . . . . . . . . . . . . . . . . .156
. . . .
C.8 Chapter 8 Solutions . . . . . . . . . . . . . . . . . . . . . . .160
. . . .
vi
Listings
2.1 blink_if/blink_if.pde.............................................................17
2.2 blink_else/blink_else.pde.....................................................20
2.3 blink_while/blink_while.pde................................................21
2.4 blink_for/blink_for.pde........................................................25
2.5 lightPattern1/lightPattern1.pde..........................................28
2.6 lightPattern1b/lightPattern1b.pde......................................29
3.1 button1/button1.pde...........................................................35
3.2 button2/button2.pde...........................................................39
3.3 Constrain............................................................................ 40
3.4 pot1/pot1.pde......................................................................42
3.5 pot2/pot2.pde......................................................................44
3.6 pot3/pot3.pde......................................................................44
3.7 rgb_3pot/rgb_3pot.pde........................................................48
4.1 sound_simple/sound_simple.pde.........................................52
4.2 sound_2/sound_2.pde..........................................................54
4.3 sound_3/sound_3.pde..........................................................56
4.4 sound_array/sound_array.pde.............................................57
5.1 blink_if_serial/blink_if_serial.pde.........................................59
5.2 temp_serial/temp_serial.pde...............................................63
5.3 lcd1/lcd1.pde.......................................................................69
5.4 temp_lcd/temp_lcd.pde.......................................................71
x
Listings
6.1 temp_lcd_graphic/temp_lcd_graphic.pde.............................79
6.2 temp_lcd_graphic_chart/temp_lcd_graphic_chart.pde..........83
7.1 photocell/photocell.pde........................................................92
7.2 tiltsensor/tiltsensor.pde.......................................................94
7.3 reed1/reed1.pde...................................................................95
7.4 knock1/knock1.pde..............................................................97
8.1 servo1/servo1.pde..............................................................100
8.2 joystick/joystick.pde...........................................................102
8.3 pantilt/pantilt.pde...............................................................104
8.4 rubberBandGun/rubberBandGun.pde.................................108
x
Chapter 1
Getting Started
The purpose of this book is to get you started on the road to creating
things using micro-controllers. We will discuss only enough
electronics for you to make the circuits, and only enough
programming for you to get started. The focus will be on your
making things. It is my hope that as you go through this book you
will be flooded with ideas of things that you can make. So let’s get
going...
The first question we’ll start with is:
Wikipedia1 says:
1
1
Chapter 1 Getting
Started
For this book, we will be using the Arduino Uno board. This
combines a micro-controller along with all of the extras to make it
easy for you to build and debug your projects.
2
1.2 Install the Software
3
Chapter 1 Getting
Started
4. Look under Ports (COM & LPT). You should see an open port
named "Arduino UNO (COMxx)".
5. Right click on the "Arduino UNO (COMxx)" port and choose
the "Update Driver Software" option.
6. Next, choose the "Browse my computer for Driver software" option.
7. Finally, navigate to and select the Uno’s driver file, named
"ArduinoUNO.inf", located in the "Drivers" folder of the Arduino
Software download (not the "FTDI USB Drivers" sub-directory).
8. Windows will finish up the driver installation from there.
9. Double-click the Arduino application.
10. Open the LED blink example sketch: File > Examples > 1.Basics >
Blink
11. Select Arduino Uno under the Tools > Board menu.
12. Select your serial port (if you don’t know which one,
disconnect the UNO and the entry that disappears is the right
one.)
13. Click the Upload button.
14. After the message “Done uploading” appears, you should see
the “L” LED blinking once a second. (The “L” LED is on the
Arduino directly behind the USB port.)
4
1.3 The Integrated Development Environment (IDE)
1. Open the LED blink example sketch: File > Examples > 1.Basics > Blink
3. Select your serial port (if you don’t know which one,
disconnect the UNO and the entry that disappears is the right
one.)
You use the Arduino IDE on your computer (picture following) to create,
open, and change sketches (Arduino calls programs “sketches”. We
will use the two words interchangeably in this book.). Sketches
define what the board will do. You can either use the buttons along
the top of the IDE or the menu items.
5
Chapter 1 Getting
Started
• Create new Sketch - This opens a new window to create a new sketch.
• Open Existing Sketch - This loads a sketch from a file on your
computer.
6
1.4 Our first circuit
• Save Sketch - This saves the changes to the sketch you are working on.
• Upload to Board - This compiles and then transmits over the
USB cable to your board.
• Serial Monitor - We will discuss this in section 5.1.
• Tab Button - This lets you create multiple files in your sketch.
This is for more advanced programming than we will do in
this class.
• Sketch Editor - This is where you write or edit sketches
• Text Console - This shows you what the IDE is currently doing
and is also where error messages display if you make a
mistake in typing your program. (often called a syntax error)
• Line Number - This shows you what line number your cursor
is on. It is useful since the compiler gives error messages with
a line number
7
Chapter 1 Getting
Started
BACKWARDS, IT WILL NOT WORK. (But it won’t be damaged, either. Don’t
worry.)
8
1.5 Updated Circuit
9
Chapter 1 Getting
Started
2
3
4
5 void loop()
6
7
10
1.6 Our First Program
starting with the letter k. You don’t have to do this, but it makes it
easier when you look through your code to know what is a constant.
3 void setup()
4 {
5 pinMode(kPinLed, OUTPUT);
6
}
11
Chapter 1 Getting
Started
1.7 Comments
So far our programs have been only for the computer. But it turns
out that you can put things in them that are only for the human
readers. You can (and should) add comments to the program which
the computer ignores and are for human readers only. This
language supports two forms of comments:
1. The block comment style. It starts with a /* and continues
until a */ is encountered. This can cross multiple lines.
Below are three examples.
/* This is a comment */
/* So is this */
/* And
* this
* as
* well */
12
1.8 Gotchas
9 /* Pin Definitions */
10 const int kPinLed = 13;
11
12 /*
13 Function Name: setup
Purpose: Run once when the system powers up.
14
15 */
void setup()
16
17
pinMode(kPinLed, OUTPUT);
18
19
20
21 /*
Function name: loop
22
Purpose: Runs over and over again, as long as the Arduino ←›
23
‹→ has power
*/
24
void loop()
25
26 digitalWrite(kPinLed, HIGH);
27 delay(500);
28 digitalWrite(kPinLed, LOW);
29 delay(500);
30
31
1.8 Gotchas
13
Chapter 1 Getting
Started
• The programming language is case sensitive. In other words,
myVar is different than MyVar
• Whitespace (spaces, tabs, blank lines) is all collapsed to the
equivalent of a single space. It is for the human reader only.
• Blocks of code are encapsulated with curly braces ’{’ and ’}’
• Every open parenthesis ’(’ must have a matching close parenthesis
’)’
• There are no commas in numbers. So you must say 1000 and NOT
1,000.
• Each program statement needs to end with a semicolon ’;’. In
general, this means that each line of your program will have a
semicolon. Excep- tions are:
– Semicolons (like everything) are ignored in comments
– Semicolons are not used after the end curly brace. ’}’
1.9 Exercises
(There are sample solutions in Appendix C. However, you should
struggle with them first and only look there when you are stuck. If
you end up looking there, you should make up another exercise for
yourself. The Challenge exercises do not have sample solutions.)
1. Change the amount of time the LED is off to 1 second.
(Leaving the amount of time the LED is on at ½ second.)
2. Change the pin to which the LED is connected from pin 13 to
pin 2. (Note that both the circuit AND the program must be
changed.)
3. Hook up 8 LEDs to pins 2 through 9 (with resistors, of
course.) Modify the code to turn on each one in order and
then extinguish them in order.
- HINT: hook them up one additional LED at a time and make
sure the new one works before you add the next one.
14
1.9 Exercises
15
Chapter 2
2.1 “Blinky”
In the last chapter, we made a light blink. Now let’s look into ways
to vary the pattern for a single LED. (Later in the chapter we’ll
hook up even more LEDs.) We will use the LED that is built into
our Arduino on pin 13 for the first few sections in this chapter. (It
is labeled “L” on the board and is on the left side behind the USB
connector.)
2.2 IF Statements
So far all of our programs have executed all of the code. Control
structures allow you to change which code is executed and even to
execute code multiple times.
The if statement is the first control structure. Here is an example of a
pro- gram using it:
Listing 2.1: blink_if/blink_if.pde
1 const int kPinLed = 13;
2
3 void setup()
4
5 pinMode(kPinLed, OUTPUT);
6
7
8 int delayTime = 1000;
17
Chapter 2 Making Light
Patterns
9
10 void loop()
11 {
12 delayTime = delayTime - 100;
13 if(delayTime <= 0){ // If e delay time is zero or ←›
‹→ less, reset it.
14 delayTime = 1000;
15 }
16 digitalWrite(kPinLed, HIGH);
17 delay(delayTime);
18 digitalWrite(kPinLed, LOW);
19 delay(delayTime);
20 }
18
2.2 IF Statements
Operator2 Meaning
= assignment operator
+ addition operator
- subtraction operator
* multiplication operator
/ division operator - be aware that if you are using
integers only
the whole part is kept. It is NOT
rounded. For example:
5 / 2 == 2
% modulo operator - This gives the remainder. For
example:
5 % 2 == 1
Next, we’ll look at line 13-15:
13 if(delayTime <= 0){ // If the delay time is zero or ←›
14
‹→ less, reset it.
15
delayTime = 1000;
}
The purpose of this section is to make sure the light always
blinks. Since we are subtracting 100 from delayTime, we want to
keep it from becoming 0 or negative.
There are a number of comparison operators that we can use:
Operator Meaning
== is equal to
!= is not equal to
< is less than
> is greater than
<= is less than or equal to
>= is greater than or equal to
In this case, we could have just tested for if(delayTime == 0)
but since being negative is bad as well, we checked for it. In
general, this is a good practice. (Imagine if we wanted to subtract
300 from delayTime instead of 100.)
As you have probably figured out, if the delayTime is less than or
equal to 0 then the delay time is set back to 1000.
2I am not mentioning all of the operators here, just the more common ones. A full
list is in Appendix A.
19
Chapter 2 Making Light
Patterns
16 digitalWrite(kPinLed, HIGH);
17 delay(delayTime);
18 digitalWrite(kPinLed, LOW);
19
delay(delayTime);
The remaining section turns the LED on and off. However,
instead of using a fixed number, we use a variable so that we can
change the delay time as the program runs. Pretty neat, huh?
20
2.4 WHILE statements
22
21
Chapter 2 Making Light
Patterns
18
19 while(delayTime < 1000){ // while delayTime is less than ←›
‹→ 1000
20
delayTime = delayTime + 100; // do this first so we don←›
‹→ ’t have a loop with delayTime = 0
21
digitalWrite(kPinLed, HIGH);
22 delay(delayTime);
23 digitalWrite(kPinLed, LOW);
24 delay(delayTime);
25 }
26 }
22
2.5 What is truth(true)?
sign= is an assignment (ie, it sets the variable to the value), and a double equals
== is a test to see if they are the same.
For example, imagine if we wanted a light to blink in a speeding
up pattern and then repeat but accidentally used a single equals
instead of a double equals. We might have some code like this:
int delayTime = 1000;
void loop()
{
if(delayTime = 0){ // BAD!!! should be ==
delayTime = 1000;
}
digitalWrite(kPinLed, HIGH);
delay(delayTime);
digitalWrite(kPinLed, LOW);
delay(delayTime);
delayTime = delayTime - 100;
}
This will assign 0 to delayTime. The if statement will then
check to see if 0 is true. It isn’t (remember 0 is the definition of
false.) So it doesn’t exe- cute the delayTime = 1000, but every
time through the loop() function delayTime will be 0. This isn’t
what we wanted to have happen at all!!
For another example, imagine that we wanted the blinking to get
less rapid and then reset but accidentally used a single equals
instead of a double equals.
int delayTime = 100;
void loop()
{
if(delayTime = 1000){ // BAD!!! should be ==
delayTime = 100;
}
digitalWrite(kPinLed, HIGH);
delay(delayTime);
digitalWrite(kPinLed, LOW);
delay(delayTime);
delayTime = delayTime + 100;
}
23
Chapter 2 Making Light
Patterns
In this case, it will assign 100 to delayTime. The if statement will
then check to see if 100 is true. It is (remember everything that isn’t
0 is true). So ev-ery time it will assign 1000 to delayTime and the
blink rate will never change. Oops. These bugs can be difficult to
track down so if you get something un- usual look to make sure you
didn’t make this mistake.
2.6 Combinations
Sometimes you want to test for more than one thing. For example,
you may want to test if a variable is between two numbers. While
you can use multiple if statements, it is often more convenient
and readable to use logical combi- nations. There are three ways
that you can combine logical conditions.
Operator Example Meaning
&& (A < 10) && (B > 5) logical AND (return TRUE if
con- dition A AND condition B
are true,
otherwise return FALSE.)
|| (A < 10) || (B > 5) logical OR (return TRUE if
condi-
tion A OR condition B is true,
oth- erwise return FALSE.)
! !(A < 10) logical NOT (return TRUE if
con-
dition A is false, otherwise
return FALSE.)
Something that isn’t obvious is that you can use the NOT
operator as a toggle for a variable that is intended to be either true
or false (or LOW or HIGH). For example:
int ledState = LOW;
void loop()
24
2.7 FOR statements
25
Chapter 2 Making Light
Patterns
Operator Meaning Example
++ increment x++ means the same as x = x + 1
-- decrement x-- means the same as x = x - 1
The for statement has three sub-statements within it. It is
composed like the following:
for (statement1;condition;statement2){
// statements
}
Statement1 happens first and exactly once. Each time through
the loop, the condition is tested; if it’s true, the code within the
curly braces and then the statement2 is executed. When the
condition is false, it goes to the code after the statement block.
26
2.8 Our New Circuit
2. Connect +5V from the Arduino to the bottom row of the next
to right column. (This isn’t actually necessary, but it is a good
habit to always hook up the power and ground columns.)
3. LED1
a) Connect the resistor with one end in h2 and the other end
on the far right column (ground).
b) Connect an LED cathode (shorter leg) to f2. (This makes
it connect to the resistor through the breadboard.)
c) Connect same LED anode (longer leg) to f3.
d) Connect j3 to pin 2 on the Arduino.
4. LED2
a) Connect another resistor with one end in h5 and the
other end on the far right column (ground).
b) Connect another LED cathode (shorter leg) to f5.
c) Connect same LED anode (longer leg) to f6.
d) Connect j6 to pin 3 on the Arduino.
5. LED3
a) Connect another resistor with one end in h8 and the
other end on the far right column (ground).
b) Connect another LED cathode (shorter leg) to f8.
c) Connect same LED anode (longer leg) to f9.
d) Connect j9 to pin 4 on the Arduino.
6. LED4
a) Connect another resistor with one end in h11 and the
other end on the far right column (ground).
b) Connect another LED cathode (shorter leg) to f11.
27
Chapter 2 Making Light
Patterns
c) Connect same LED anode (longer leg) to f12.
d) Connect j12 to pin 5 on the Arduino.
Now, lets try a program that will let us make sure that all of our
hardware is made correctly. It is often wise to write a small piece
of software to test and make sure your hardware is correct rather
than try your full software on the brand new hardware.
This code sets up LEDs on pins 2-5 and then cycles through
turning each LED on and then off.
Listing 2.5: lightPattern1/lightPattern1.pde
1 const int kPinLed1 = 2;
2 const int kPinLed2 = 3;
3 const int kPinLed3 = 4;
4 const int kPinLed4 = 5;
5
6 void setup()
7 {
8 pinMode(kPinLed1, OUTPUT);
9 pinMode(kPinLed2, OUTPUT);
10 pinMode(kPinLed3, OUTPUT);
11 pinMode(kPinLed4, OUTPUT);
12 }
13
14 void loop()
15 {
16 // turn on each of the LEDs in order
17 digitalWrite(kPinLed1, HIGH);
18 delay(100);
19 digitalWrite(kPinLed2, HIGH);
20 delay(100);
21 digitalWrite(kPinLed3, HIGH);
22 delay(100);
23 digitalWrite(kPinLed4, HIGH);
24 delay(100);
25
26 // turn off each of the LEDs in order
27 digitalWrite(kPinLed1, LOW);
28
2.9 Introducing Arrays
28 delay(100);
29 digitalWrite(kPinLed2,
30
LOW); delay(100);
31
digitalWrite(kPinLed3,
32
LOW); delay(100);
33
digitalWrite(kPinLed4,
34
LOW);
While this code works just fine, it isn’t very elegant and it seems
like there is a lot of writing of very similar things and opportunities
for mistakes. Let’s see how we can do a better job.
29
Chapter 2 Making Light
Patterns
18 digitalWrite(kPinLeds[i], LOW);
19 delay(100);
20 }
21 }
Can you figure out what this does? If not, don’t panic. We are
going to go through this code and look at each part.
1
const int k_numLEDs = 4;
First, we define how many elements are going to be in our array.
We use this later to make sure that we don’t try to read (or write)
past the end of our array. (Arduino does not stop you from doing
this which can cause all sorts of strange problems.)
2
const int kPinLeds[k_numLEDs] = {2,3,4,5}; // LEDs connected←›
‹→ to pins 2-5
Second, we define the array. You’ll notice that we have the
number of “ele- ments” in the array in brackets. We could have
used the actual number, but it is much better to use a constant. We
assign the values to the array here. The values are inside of curly
braces and are separated by commas.
Arrays are zero-indexed, which can be confusing. That means the
first ele- ment in the array k_LEDPins is k_LEDPins[0]. The last
element in the array is k_LEDPins[3]. (0-3 is 4 elements.)
4
void setup()
5
6
{
7
for(int i = 0; i < k_numLEDs; i++)
8 { pinMode(kPinLeds[i], OUTPUT);
9 }
}
Here we use a for loop to go through each of the elements in our
array and
set them as OUTPUT. To access each element in the array,
we use square brackets with the index inside. 4
4Some of you may be wondering if we could have just used pins 2-5 without
using an array. Yes, we could have. But you don’t want to. If in a later circuit
you decide to use pins that aren’t next to each other the array method works,
and the other one doesn’t.
30
2.10 Exercises
2.10 Exercises
1. Modify the blink_for program in Section 2.7 to light the LED
up 10 times in a row instead of 4.
2. Make a program (sketch) that lights up a single LED five
times in a row for one second on and off, and then five times
in a row for ½ of a second on and off.
3. Make a program using arrays that lights up the LEDs from top
to bottom and then goes backwards so only one LED is on at
any time. (This is often called a “Cylon”5 or a “Larson”6 light.)
4. Make a program that lights up the LEDs in any pattern that you like.
31
Chapter 3
Input
Until now, we have only used the Arduino to control other things. It
is time for us to start sensing the real world! After we do this, then
our Arduino will be able to make decisions of what to do based off
of input from the outside world.
In this chapter we will start with a simple circuit and continue to
add pieces to it.
3.1 Pushbuttons
What
is a pushbutton? Pushing a button causes wires under the
button to be connected, allowing current to flow. (called closed)
When the button isn’t pressed, no current can flow because the
wires aren’t touching (called open) .1
1This is true for the most common type of pushbutton called “normally open”
(often abbre- viated NO). There is a less common type called “normally closed”
(abbreviated NC) that is closed (connected) when not pushed and open when
pushed.
33
Chapter 3 Input
3.1.1.1 Circuit
3. Put the pushbutton legs in e5, e7, f5, and f7. (If they won’t fit
in these squares, turn the switch 90º (¼ of a turn) and try
again.)
34
The push buttons have four legs. When the button is pressed it
connects the two
legs on the right side together. (It also connects
the two on the left, but we aren’t using those now.)2
3.1.1.2 Programming
Let us start with some sample code and see if you can guess what it does.
Listing 3.1: button1/button1.pde
const int kPinButton1 = 2;
1
void setup()
4
5
6 pinMode(kPinButton1, INPUT);
7 digitalWrite(kPinButton1, HIGH); // turn on pull-up ←›
‹→ resistor
8
pinMode(kPinLed, OUTPUT);
9
10
11
12
void loop()
13 if(digitalRead(kPinButton1) == LOW){
14 digitalWrite(kPinLed, HIGH);
15 }
16 else{
17 digitalWrite(kPinLed, LOW);
18 }
19
35
7 digitalWrite(kPinButton1, HIGH); // turn on pull-up ←›
‹→ resistor
8
pinMode(kPinLed, OUTPUT);
9
36
11 void loop()
12 {
13 if(digitalRead(kPinButton1) == LOW)
14
{ digitalWrite(kPinLed, HIGH);
15
16
}
17
else{
18
digitalWrite(kPinLed, LOW);
19 }
}
If the button is pressed, then the pin will be connected to ground
(which we will see as LOW). If it isn’t pressed, the pull-up resistor
will have it internally connected to +5V (which we will see as
HIGH.)
Since we want the LED to light when the button is pressed, we write HIGH
out when the value read from the pin connected to the
button is LOW. A few intermediate exercises:
1. Try this program and make sure it works. (If it doesn’t, rotate
the button 90 degrees and try again.)
2. Change it so the LED is normally on and pressing the button turns it off
37
2. Take advantage of the fact that people can only see things
that happen up to a certain speed, and turn the LED on and
off faster than we can see. The more time that the LED is on
in a given period of time, the “brighter” we think it is. The
more time it is off, the “dimmer” we think it is. (This method
supports smoother dimming over a broader range as opposed
to changing resistors.)
It turns out that this method of turning things on and off quickly is
very com- mon, and a standard method has been designed called
Pulse Width Modulation (PWM for short).
The Arduino supports PWM (on certain pins marked with a
tilde(~) on your board - pins 3, 4,5,9,10 and 11) at 500Hz. (500
times a second.) You can give it a value between 0 and 255. 0
means that it is never 5V. 255 means it is always 5V. To do this you
make a call to analogWrite() with the value. The ratio of “ON”
time to total time is called the “duty cycle”. A PWM output that is
ON half the time is said to have a duty cycle of 50%.
Below is an example showing what the pulses look like:
38
You can think of PWM as being on for x
where x is the value you send with
25
analogWrite(). 5
3.1.2.1 Circuit
Enough talking! Let’s make something! First, let us add to our circuit.
(You can test to make sure you have the button put in correctly by
connecting h11 to pin 2 instead of the first button and making sure
it works before you upload a new program to the Arduino.)
3.1.2.2 Programming
Here is a sample program that uses a button to dim the LED and
another button to increase the brightness:
Listing 3.2: button2/button2.pde
1 const int kPinButton1 = 2;
39
2 const int kPinButton2 = 3;
3 const int kPinLed = 9;
4
5
void setup()
6
{
7
8
pinMode(kPinButton1, INPUT);
9
pinMode(kPinButton2, INPUT);
10 pinMode(kPinLed, OUTPUT);
11 digitalWrite(kPinButton1, HIGH); // turn on pullup resistor
12 digitalWrite(kPinButton2, HIGH); // turn on pullup resistor
13 }
14
15 int ledBrightness = 128;
void loop()
16 {
17 if(digitalRead(kPinButton1) == LOW){
18 ledBrightness--;
19 }
20 else if(digitalRead(kPinButton2) == LOW){
21 ledBrightness++;
22 }
23
24 ledBrightness = constrain(ledBrightness, 0, 255);
25 analogWrite(kPinLed, ledBrightness);
26 delay(20);
27 }
40
3.2
Potentiometers
if(value > max)
{ value = max;
return value;
3.2 Potentiometers
We used pushbuttons for digital input in the last section. Now let’s
look at using a potentiometer. (A potentiometer is a resistor whose
value changes smoothly as it is turned. This is used often as an
adjustment “knob” in many electronics.)
41
Chapter 3
Input
3.2.1 Circuit
The potentiometer has three legs. The one in the middle should be
connected to ANALOG IN 0 on the Arduino. One of the sides
should be connected to
+5V and the other to GND. (ground). (If you get these backwards
then your potentiometer will work in the backwards direction of
what you expect.)
Digital means something is either on or off. Analog means it can
have a continuous range of values. The Arduino has some built-in
“analog inputs” that convert the voltage seen on the pin to a
number that we can use in our programs. (They return between 0
and 1023. So, 0V would read as 0 and 5V would read as 1023.)
1. Place the potentiometer (often called “pot” for short) in f13, f14, and
f15.
2. Connect j13 to the next to right most column (+5V).
3. Connect j15 to the right most column (ground).
4. Connect j14 to the A0 pin (Analog In 0) on the Arduino.
3.2.2 Programming
42
3.2
Potentiometers
3
4 void setup()
5
6
pinMode(kPinPot, INPUT);
7
pinMode(kPinLed,
8
9
OUTPUT);
10
11
12 void loop()
13
14 int ledBrightness;
15 int sensorValue = 0;
16
17
sensorValue = analogRead(kPinPot);
18
ledBrightness = map(sensorValue, 0, 1023, 0, 255);
19
analogWrite(kPinLed,
There ledBrightness);
are two things here that are different from anything we
have done before.
43
Chapter 3
Input
now let us do something we can’t do easily without a micro-
controller. This next program changes how quickly the LED blinks
based off of the value read from the potentiometer.
Listing 3.5: pot2/pot2.pde
1 const int kPinPot = A0;
2
const int kPinLed = 9;
3
4
void setup()
5
6
{
7 pinMode(kPinLed, OUTPUT);
8 }
9
10 void loop()
11 {
12 int sensorValue;
13
14
sensorValue = analogRead(kPinPot);
15
16
17
digitalWrite(kPinLed, HIGH);
18 delay(sensorValue);
19 digitalWrite(kPinLed, LOW);
delay(sensorValue);
}
3.2.3 A way to avoid delay()
The program in the last section was pretty neat, but the light has
to go through a full cycle of on and off before it checks the
potentiometer again. So when the delay is long it takes it a long
time to notice that we have changed the potentiometer. With some
tricky programming, we can check the value more often and not
wait until the full delay time was used up. Let’s see an example.
Listing 3.6: pot3/pot3.pde
1 const int kPinPot = A0;
2 const int kPinLed = 9;
3
44
3.2
Potentiometers
4 void setup()
5
6 pinMode(kPinLed, OUTPUT);
7
8
9
long lastTime = 0;
10
11
int ledValue = LOW;
12
13 void loop()
14
15 int sensorValue;
16
17
sensorValue = analogRead(kPinPot);
18
if(millis() > lastTime + sensorValue){
19
if(ledValue == LOW)
20
21
{ ledValue = HIGH;
22
23 else{
24 ledValue = LOW;
25
26 lastTime = millis();
27 digitalWrite(kPinLed, ledValue);
9 long lastTime = 0;
So far we have only used a variable type called int. It turns out
that there are several different types of variables you can have.
Here they are:
45
Chapter 3
Input
Type contains
boolean can contain either true or false
char -128 to 127
unsigned char 0 to 255
byte (same as unsigned char)
int -32,768 to 32,767
unsigned int 0 to 65,535
word (same as unsigned int)
long (or long int) -2,147,483,648 to 2,147,483,647
unsigned long 0 to 4,294,967,295
float -3.4028235E+38 to 3.4028235E+38
double (same as float)
The only thing you need to know about this now is that if you are
trying to store a number that may be too big to fit into an int, you
can use a long (or a long int). (This table is true for Arduino, but
can vary from computer to computer.)
The second new thing is that we are using a new function called
millis(). This returns the number of milliseconds the Arduino has
been running since it started last.5 This function returns a long
since if it returned an int, it wouldn’t be able to count very long.
Can you figure out how long? (Answer: 32.767 seconds)
So instead of using delay(), we keep checking millis() and
when the appropriate number of milliseconds has passed, then we
change the LED. We then store the last time we changed in the
lastTime variable so we can check again at the right time.
46
3.3 RGB LEDs
Introducing our new friend, the RGB LED. An RGB LED is really
three small LEDs next to each other. A Red one, a Green one, and a
Blue one. (Hence, why it is called RGB). It turns out that you can
make any color by mixing these three light colors together.
You use the same PWM method we discussed earlier in the
chapter for each part of the red, the green, and the blue. Let’s
hook it up with three potentiome- ters so we can vary each one and
it should make more sense.
3.3.1 Circuit
47
Chapter 3
Input
7. Connect j23 to the right most column (ground).
8. Connect j22 to the A2 pin on the Arduino.
9. Put the RGB LED (you can tell it because it’s the one with four
legs) in f26, f27, f28, f29 with the cathode (longest leg) in f27.
(this should be the leg second from the top.)
10. Put a resistor from h27 to the far right column (ground).
11. Connect h26 to pin 6 on the Arduino.
12. Connect h28 to pin 10 on the Arduino.
13. Connect h29 to pin 11 on the Arduino.
3.3.2 Programming
Following is a program that will let us control the color of the LED by
turning 3 different potentiometers. One will be read for the value
of Red, one for the value of Green, and one for the value of Blue.
Listing 3.7: rgb_3pot/rgb_3pot.pde
1 const intkPinPot1 A0;
2 const intkPinPot2 A1;
3 const intkPinPot3 A2;
4 const intkPinLed_R 6;
=
5 const intkPinLed_G = 10;
6 const intkPinLed_B = 11;
7
8 void setup()
9
10 pinMode(kPinLed_R, OUTPUT);
11 pinMode(kPinLed_G, OUTPUT);
12 pinMode(kPinLed_B, OUTPUT);
13
14
15 void loop()
16
48
3.4 Exercises
17 int potValue;
18 int ledValue;
19
20
potValue = analogRead(kPinPot1);
21
ledValue = map(potValue, 0, 1023, 0, 255);
22
23
analogWrite(kPinLed_R, ledValue);
24
25 potValue = analogRead(kPinPot2);
26 ledValue = map(potValue, 0, 1023, 0, 255);
27 analogWrite(kPinLed_G, ledValue);
28
29 potValue = analogRead(kPinPot3);
30 ledValue = map(potValue, 0, 1023, 0, 255);
31
analogWrite(kPinLed_B, ledValue);
You may notice that when you turn all of the pots to full on that
instead of white you get red. The reason for this is that the red
LED is stronger than the other two. You can experiment with the
values in the map() function before sending it to the red part of
the LED so that it will be more balanced.
3.4 Exercises
1. Make the two push buttons a “gas” and “brake” button. The
“gas” button should speed up the blinking rate of the LED,
and the “brake” button should slow it down.
2. Change the speed at which the LED blinks based off of the
value of the pot ONLY when the first button is pressed. (In
other words, you can adjust the potentiometer, but it has no
effect until you press the “ON” button)
3. CHALLENGE: Use the two buttons to store a “from” and a
“to” color. When neither button is pressed, the RGB LED
should fade smoothly from one color to the other and back.
4. CHALLENGE: Can you find out how long it is between the last
statement in the loop() function and the first one?
49
Chapter 4
Sound
First, let’s hook up the speaker to pin 9. (The other pin of the speaker simply
goes to ground.)
51
Chapter 4
Sound
52
4.3 Music
53
Chapter 4
Sound
(A strange warning. When the tone() function is running, PWM
(pulse width modulation that we used in section 3.1.2) won’t run on
pin 3 and pin 11.So if you are using a speaker in your sketch, you
might want to avoid using those pins as PWM entirely.) 1 You may
hook a speaker up to any of the pins.
Here is an example to try on your Arduino: (Ok, so it is a simple
C scale and probably not really music.)
54
4.4 Music with
functions
28 delay(500);
29 tone(kPinSpeaker, NOTE_A4, 500);
30 delay(500);
31
tone(kPinSpeaker, NOTE_B4, 500);
32
delay(500);
33
34
tone(kPinSpeaker, NOTE_C5, 500);
35
delay(500);
36
37 noTone(kPinSpeaker);
38
39 delay(2000);
The only thing here you haven’t seen before is #define. #define
is a search and replace command to the computer during
compilation. Any time it finds the first thing (up to a space), it
replaces it with the rest of the line. 2 So in this example, when the
computer finds NOTE_E4, it replaces it with a value of 330. We
won’t talk here about how to determine what the frequency is of
each note. However, there is a file on your USB stick called
pitches.h that has all of the frequencies for all of the notes on a
piano keyboard. This file is also
available from http://www.introtoarduino.com.
55
Chapter 4
Sound
can be used within the function as variables. As an example, we’ll
create a function called ourTone() that will combine the tone()
and delay() lines so that the function won’t return until the note
is done playing.
56
4.4 Music with
functions
34 tone(kPinSpeaker, freq, duration);
35 delay(duration);
36
23
24 void loop()
25
26 for (int i = 0; i < NUM_NOTES; i++) {
27 if (notes[i] == 0) {
28 delay(beats[i] * beat_length); // rest
29
30 else {
57
Chapter 4
Sound
31 ourTone(notes[i], beats[i] * beat_length);
32
33 // pause between notes
34 noTone(kPinSpeaker);
35
delay(beat_length /
36
2);
37
38
39
40
41 void ourTone(int freq, int duration)
42
43 tone(kPinSpeaker, freq, duration);
delay(duration);
In line 1, you’ll see the #include statement. What this does is
take the entire file within the quotes and put it where the #include
statement is. By convention, these are almost always placed at the
top of a program.
4.5 Exercises
1. Make a sketch that plays the first line of “Happy Birthday”
a) C4 (1 beat), C4 (1 beat), D4 (2 beats), C4 (2 beats), F4 (2
beats), E4 (4 beats)
2. Add 2 buttons to the circuit. For a reminder of how to hookup
and pro- gram buttons, see section 3.1. When you press each
button have it play a different tune.
3. Change ourTone() to not use the tone() and noTone()
functions. (HINT: use the technique shown in section 4.2.)
58
Chapter 5
59
Chapter 5 Making a digital
thermometer
3 void setup()
4
5 pinMode(kPinLed,
6
OUTPUT);
7
Serial.begin(9600);
8
9
10
11 int delayTime = 1000;
12
13 void loop()
14
This basically says that we want to use the Serial1 code and to
start it at 9600 baud.2 This number and the one in the serial
monitor (described later) MUST match or you will see gibberish in
the serial monitor. ( 9600 is the default, so it is easiest to use that.)
The second new thing is in lines 17-18.
17 Serial.print("delayTime = ");
18 Serial.println(delayTime);
1Serial means that it is sent one bit after another.
2Baud is how many bits per second are transmitted.
60
5.1 Serial Monitor
The
only difference between Serial.print and Serial.println
is that Serial.println means that the next thing sent out the serial
port after this one will start on the next line. There is a third new
thing you may have noticed.There is something in quotes ( “ ). This
is called a string. In this book we will only use strings as
constants.3
Upload and run it. Hmm, it seems like the LED just blinked and
nothing else new happened (except now we see the TX light blink
on the board. That is because we don’t have the Serial Monitor
window up.
61
Chapter 5 Making a digital
thermometer
program to that to minimize our needing to change settings.) If you
have the baud set differently, you will see garbage instead of what
you expect.
Before going any further, make sure that when you run your
program you see the lines “delayTime = “ with the value of
delayTime on the Serial Monitor.
62
5.2 Measuring the
temperature
2. Connect the next to right column to +5V.
3. Put pin 1 of the TMP36 in f1. (The curved part of the
temperature sensor should face the left edge of the
breadboard. If you get this backwards, it will heat up and can
burn you.)
4. Connect j1 to the far right column (GND).
5. Connect j3 to the next to right column (+5V).
6. Connect j2 to A0 on the Arduino.
Now here is the code that will read the temperature sensor and send
the values to the serial monitor on the computer. Again, we will
show the entire code first and then go through the new sections
afterwards.
Listing 5.2: temp_serial/temp_serial.pde
1 const int kPinTemp = A0;
2
3 void setup()
4
5 Serial.begin(9600);
6
7
8 void loop()
9
10 float temperatureC = getTemperatureC();
11
12 Serial.print(temperatureC);
13 Serial.println(" degrees C");
14
15 // now convert to Fahrenheit
16 float temperatureF = convertToF(temperatureC);
17
18 Serial.print(temperatureF);
19 Serial.println(" degrees F");
20
21 delay(500);
22
63
Chapter 5 Making a digital
thermometer
23
24 float getTemperatureC()
25
26
int reading = analogRead(kPinTemp);
27
28
29
float voltage = (reading * 5.0) / 1024;
30
// convert from 10 mv per degree with 500mV offset
31 // to degrees ((voltage - 500mV) * 100)
32 return (voltage - 0.5) * 100;
33
34
35 float convertToF(float temperatureC)
36
37 return (temperatureC * 9.0 / 5.0) + 32.0;
So we’ll start near the very beginning of loop.
10 float temperatureC = getTemperatureC();
You will notice that we use the float variable type. This variable
type is the only one that allows you to store anything other than
integer numbers (number with no decimal or fractional part.)
Floats are only accurate to about 6-7 digits. This is important only
because you can end up with rounding er- rors when using them.
So when doing comparisons, make sure that you are checking to
see if they are “close” instead of equal. We call our own function
getTemperatureC().
24 float getTemperatureC()
25 {
26 int reading = analogRead(kPinTemp);
27
28
29
float voltage = (reading * 5.0) / 1024;
30
// convert from 10 mv per degree with 500mV offset
31
// to degrees ((voltage - 500mV) * 100)
32
return (voltage - 0.5) * 100;
}
The getTemperatureC function does the math necessary to
convert from the data the sensor gives into the Celsius
temperature. Since our analogIn()
64
5.2 Measuring the
temperature
can return a value between 0 and 1023, we can calculate the
voltage by multi- plying our reading by 5.0 and dividing it by 1024.
The sensor that we are using sends 500mV at 0 Celsius (so that
you can read negative temperatures.) It then goes up 10mV per
degree C. For example, here is what the sensor will return for
some different temperatures.
Temperature Voltage from sensor
Celsius
-10 400mV
0 500mV
10 600mV
20 700mV
30 800mV
40 900mV
50 1000mV
This is the first function we have written that returns a value.
(Remember, all of the other functions have been of type void
meaning they don’t return a value.) You will see that to return the
value you simply put return followed by the value to return.
(Instead of a value, you can put a calculation like we have done
here.) Returning a value means that when you call a function it
hasan “answer” that you can assign to a variable.
We send that to the Serial Monitor and then we convert to
Fahrenheit4 by calling convertToF().
This function takes the temperature in Celsius and converts it to
Fahrenheit. Converting from Fahrenheit to Celsius is the formula:
Fahrenheit = 9 (Celsius)+ 5
32
4Only 2 countries in the world STILL use Fahrenheit as the main temperature
scale. The US and Belize.
65
Chapter 5 Making a digital
thermometer
5.3 Hooking up the LCD
You may have noticed that we have the LCD connected to a small
PCB (printed circuit board) with another chip on it. That is because
the LCD works at 3.3V and we are running the Arduino at 5V. The
chip on the PCB does the voltage conversion for us so we won’t
damage the LCD.
There are 8 pins on the board. Here is a list of the pins and what they do:
66
5.3 Hooking up the LCD
Pin Description
GND This connects to Ground on the Arduino
3.3V Connect to the 3.3V power on the Arduino. This is power
for the LCD. VERY important that this is connected to
3.3V and NOT 5V or you could damage the LCD.
CLK The serial clock5
DIN This is where the serial6 data is sent
D/C This lets the LCD know whether what is being sent to it is
a com-
mand or data
CS This is the Chip Select.7 For this book, we will always tie it
to GND
RST This resets the controller on the LCD.
LED Controls the backlight. We can connect it to +5V to be
always on, or
GND to be always off, or to a pin to be able to turn it on or
off. 8
Now let’s hook up the circuit.
1. Place the LCD + PCB into the breadboard where the pins that are labeled
5The purpose of the serial clock is it lets the controller know when to look at DN
for the next bit
6serial means it is sent one bit at a time
7When this is low then the chip is listening to D/C, DIN, CLK, and RST) This can
either be tied to Ground (which will make it always listen) or used so that the
pins can also be used for other purposes.
8Yes, we can even use PWM like we have earlier to have different brightness
67
Chapter 5 Making a digital
thermometer
on the purple PCB are in a4-a11.
11. Connect c11 (LED) to the next to right column (+5V). This
means that the backlight will always be on.
While we could write all of the code to talk to the LCD, we are
going to use some functions in a library. A library is a collection of
code that can be used by multiple programs. This allows us to
simply call functions that make it much easier to communicate with
the LCD. If you are interested in how the LCD works, you can look
inside the library but explaining that code is outside of the scope of
this book.
9This means that the LCD will always be listening on its pins.
68
5.4 Talking to the LCD
Like we have many times already, we will start with the whole
program and then go through and discuss new parts.
69
Chapter 5 Making a digital
thermometer
21
So, the first thing you will notice that is new is in line 1.
1 #include <PCD8544.h>
The #include tells the computer to take the file mentioned and
when it is “compiling” the program to replace the #include
statement with the contents of that file. An #include can either
have the angle brackets which means tolook in the library
directory or it can have quotes which means to look in the same
directory that the sketch is in.
The next few lines are our pin definitions. Then we create a
variable of a new type.
8
PCD8544 lcd(kPin_CLK, kPin_DIN, kPin_DC, kPin_RESET);
In this statement we are defining a variable named lcd of type
PCD854410 and telling the computer which pins are connected on
the Arduino.
To define the variable we tell it what pin clk, din, dc, and reset
are attached to.
10
void setup()
11
{
12
13
lcd.init();
14
lcd.setCursor(0,0);
15 lcd.print("Hello, World!");
}
In line 12, we call lcd.init() which will initialize the lcd. After
this has returned, we can use the lcd.
In line 13, we set the cursor to the upper left of the screen.
(There are 84 “columns” and 6 “lines” in this display. Just like in
arrays, it starts at 0 instead of 1.)
In line 14, we print a message. This is very similar to how we
sent messages over serial earlier in this chapter except we use
lcd.print instead of serial.print.
10PCD8544 is the name of the LCD controller we are using. How to create new
types of variables is outside the scope of this book but is a feature supported by
the language.
70
5.5 Bringing it all together
17 void loop()
18 {
19 lcd.setCursor(0,1);
20
lcd.print(millis());
21
}
This is the code that is called over and over again.
In line 19, we set the cursor to the 0th column (far left), and
the 1st row. (Remember that it starts at 0 so this is really the 2nd
row.)
In line 20, we see a shortcut. We have used millis() before in section 3.2.3.
We could have done this with 2 lines of code like:
long numMillis = millis();
lcd.print(numMillis);
However, in this case since we didn’t need the value of the
number of mil- liseconds for anything else, we just sent the result
of the millis() function directly to lcd.print().
71
Chapter 5 Making a digital
thermometer
13
14
lcd.init();
15 lcd.setCursor(10,0);
16 } lcd.print("Temperature:");
17
18 void loop()
19 {
20 float temperatureC = getTemperatureC();
21 // now convert to Fahrenheit
22 float temperatureF = convertToF(temperatureC);
23
24 lcd.setCursor(21,1);
25 lcd.print(temperatureC);
26 lcd.print(" C");
27 lcd.setCursor(21,2);
28 lcd.print(temperatureF);
29 lcd.print(" F");
30 delay(100);
31 }
32
33 float getTemperatureC()
34 {
35 int reading = analogRead(kPin_Temp);
36
The only thing new and interesting in this program is that we used the
setCursor()
function to put the text mostly centered on the screen.
72
5.6Exercises
5.6 Exercises
1. Change the program so it displays the voltage returned from
the sensor as well as the temperature in Celsius and
Fahrenheit.
2. Change the program so it displays the temperature in
Fahrenheit as well as the maximum and minimum
temperatures it has seen.
3. CHALLENGE: Modify the program in exercise 2 to also show
how long ago (in seconds) the minimum and maximum
temperature were seen.
73
Chapter 6
75
Chapter 6 Graphics (Pictures) on our LCD
1
10 = 1 x 2
100 = 2 x 2 (4)
1000 = 2 x 2 x 2 (8)
1 0000 = 2 x 2 x 2 x 2 (16)
and so
on.2
So when a computer sees 1101, we know that this
is really: (1 x 8) + (1 x 4) + (0 x 2) + (1 x 1) or 13
(in base 10)
It turns out that you can enter binary values in your code by
starting them with a 0b.
int value = 0b1101;
Now, it turns out that this would be a lot of typing for numbers.
Imagine 200: (1 x 128) + (1 x 64) + (0 x 32) + (0 x 16) + (1 x 8) +
(0 x 4) + (0x 2) + (0x 1)
int value = 0b11001000;
76
C8
(12 * 16) + (8 * 1)
192+8
200
We can put this in our code by starting with 0x to let the
compiler know we are entering hexadecimal. (This is one of the
few occurrences where you can use either lower or upper case
letters and it doesn’t make a difference.)
int value = 0xC8;
Note that there is absolutely no difference to the computer whether you say:
int value = 200;
int value = 0b11001000;
int value = 0xC8;
Since we send data to the LCD one column at a time, this would be:
0b00000001, 0b000000010, 0b00000100, 0b00001000, 0b00010000,
0b00100000,
0b01000000, 0b10000000. (Or since programmers typically use base 16 in
3Yes, you could type in 0b0 or 0x0. I am trying to show the value of all 8 pixels here.
77
their programs instead of base 2, it would look like: 0x01, 0x02,
0x04, 0x08, 0x10, 0x20, 0x40, 0x80). Notice the order. The top
pixel in each column is represented as 1, next is 2, next is 4, and so
on.
You could use this method and some graph paper and figure out
exactly what to send. This would be difficult and would take a while
(and would be easy to make a mistake.)
Luckily, there is an easier and better way.
A friend of mine (Jordan Liggitt) graciously wrote a program that
will run on any modern browser and generate the code you need in
your program. Bring up your web browser, and either open the file
8544.html on your USB key or
http://www.introtoarduino.com/utils/pcd8544.html
Here is what it will look like when you first bring it up:
You can change the image width to any number up to the width
of the dis- play. But the image height can only be done in sets of 8.
To turn a pixel “on” (dark) just click on the square. You can right-
click to turn a pixel back “off”. Here we use it to make a graphic
that looks like a thermometer to put on the display:
78
6.2 Using
graphics
After you have drawn it, you can select the text in the output box
and copy it (using Ctrl-C on a PC or Cmd-C on a mac) and then
paste it into your Arduino program (using Ctrl-V on a PC or Cmd-V
on a mac.) - If you make a mistake you can also copy it out of your
program and paste it into the “output” box and the program will let
you start there. If you have any problems, reload the web page and
try again.
Let’s use the same circuit and program from section 5.5and just
add some graphics to pretty it up.
The entire program is shown first, and then we will go through
the new por- tions.
79
Chapter 6 Graphics (Pictures) on
our LCD
7 const int kPin_Temp = A0;
8
9 PCD8544 lcd(kPin_CLK, kPin_DIN, kPin_DC, kPin_RESET);
10
11 // A bitmap graphic (5x1) of a degree symbol
12 const int DEGREE_WIDTH = 5;
13 const int DEGREE_HEIGHT = 1;
14 const byte degreesBitmap[1 * 5] = {
15 0x00, 0x07, 0x05, 0x07, 0x00 };
16
17 // A bitmap graphic (10x2) of a thermometer...
18 const int THERMO_WIDTH = 10;
19 const int THERMO_HEIGHT = 2;
20 const byte thermometerBitmap[2 * 10] =
21 {
22 0x00, 0x00, 0x48, 0xfe, 0x01, 0xfe, 0x00, 0x02, 0x05, 0x02,
23 0x00, 0x00, 0x62, 0xff, 0xfe, 0xff, 0x60, 0x00, 0x00, 0x00←›
‹→ };
24
25 const int LCD_WIDTH = 84;
26 const int LCD_HEIGHT = 6;
27
28 void setup()
29 {
30 lcd.init();
31 lcd.setCursor(10,0);
32 lcd.print("Temperature:");
33 lcd.setCursor((LCD_WIDTH-THERMO_WIDTH) / 2, 3);
34 lcd.drawBitmap(thermometerBitmap, THERMO_WIDTH, ←›
‹→ THERMO_HEIGHT);
35 }
36
37 void loop()
38 {
39 float temperatureC = getTemperatureC();
40 // now convert to Fahrenheit
41 float temperatureF = convertToF(temperatureC);
42
43 lcd.setCursor(21,1);
80
6.2 Using
graphics
44 lcd.print(temperatureF);
45 lcd.drawBitmap(degreesBitmap, DEGREE_WIDTH,
46 DEGREE_HEIGHT); lcd.print(" F");
47
lcd.setCursor(21, 2);
48
lcd.print(temperatureC);
49
50
lcd.drawBitmap(degreesBitmap, DEGREE_WIDTH,
51
DEGREE_HEIGHT); lcd.print(" C");
52
53 delay(500);
54 }
55
56
float getTemperatureC()
57
{
58
59
int reading = analogRead(kPin_Temp);
60
61 float voltage = (reading * 5.0) / 1024;
62 // convert from 10 mv per degree with 500mV offset
63 // to degrees ((voltage - 500mV) * 100)
64 return (voltage - 0.5) * 100;
65 }
66
67 float convertToF(float temperatureC)
68 }
{
return (temperatureC * 9.0 / 5.0) + 32.0;
Most of this code is the same as in section 5.5. But let’s go through the new
portions.
11 // A bitmap graphic (5x1) of a degree symbol
12 const int DEGREE_WIDTH = 5;
13 const int DEGREE_HEIGHT = 1;
14
const byte degreesBitmap[1 * 5] = {
This defines a small graphic (5 pixels wide by 1 “line” (8 pixels)
high) that we are going to use as a degree symbol.
17 // A bitmap graphic (10x2) of a thermometer...
18 const int THERMO_WIDTH = 10;
19 const int THERMO_HEIGHT = 2;
81
Chapter 6 Graphics (Pictures) on
our LCD
20 const byte thermometerBitmap[2 * 10] =
21
22 0x00, 0x00, 0x48, 0xfe, 0x01, 0xfe, 0x00, 0x02, 0x05, 0x02,
23
0x00, 0x00, 0x62, 0xff, 0xfe, 0xff, 0x60, 0x00, 0x00, 0x00←›
‹→ };
This defines a graphic of a thermometer. (10 pixels wide by 2
“lines” (remem- ber each line is 8 pixels, so it is 16 pixels high))
25
const int LCD_WIDTH = 84;
26
const int LCD_HEIGHT = 6;
Here we define the width and height of the LCD. We are going to
use this later to calculate where to place something so it is
centered.
lcd.setCursor((LCD_WIDTH-THERMO_WIDTH) / 2, 3);
33 lcd.drawBitmap(thermometerBitmap, THERMO_WIDTH, ←›
34
‹→ THERMO_HEIGHT);
This simply draws the small degree bitmap. (This happens again
in line 49 but we aren’t showing it because it is exactly the same.)
82
6.3 Making a
Chart
will go through the new portions afterwards. (We are going to
remove the Celsius temperature to have room for the graph.)
83
Chapter 6 Graphics (Pictures) on
our LCD
33 lcd.setCursor(10,0);
34 lcd.print("Temperature:");
35
lcd.setCursor(0, LCD_HEIGHT - THERMO_HEIGHT);
36 lcd.drawBitmap(thermometerBitmap, THERMO_WIDTH, ←›
‹→ THERMO_HEIGHT);
37 }
38
84
6.3 Making a
Chart
70 // to degrees ((voltage - 500mV) * 100)
71 return (voltage - 0.5) * 100;
72 }
73
74 float convertToF(float temperatureC)
75 {
76 return (temperatureC * 9.0 / 5.0) + 32.0;
77 }
78
79 const byte dataBitmap[] =
80 {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
81
85
Chapter 6 Graphics (Pictures) on
our LCD
86
6.3 Making a
Chart
change the spacing, it only has to be done one place. We then set
the cursor so that the next thing we send to the LCD will be at this
location.
int dataHeight = map(temperatureF, MIN_TEMP, MAX_TEMP, 0, ←›
55
‹→ GRAPH_HEIGHT * 8);
56
57
drawColumn(dataHeight);
58 drawColumn(0); // marker to see current chart position
59 xChart++;
The first thing we do is make sure our value is not larger than it
should be. This should never occur, but if it does we will write past
the end of our array which is really bad and difficult to debug so it
is worth it to check.
//1. clear all pixels in graphBitmap
92
93
for(i = 0; i < GRAPH_HEIGHT; i++){
94
graphBitmap[i] = 0x00;
95 }
87
Chapter 6 Graphics (Pictures) on
our LCD
99 while(value >= 8){
100 graphBitmap[GRAPH_HEIGHT - 1 - i] = 0xFF;
101 value -= 8;
102 i++;
103 }
104 if(i != GRAPH_HEIGHT){
105 graphBitmap[GRAPH_HEIGHT - 1 - i] = dataBitmap[value];
106 }
This piece is tricky and you will probably need to run several
examples through it to convince yourself that it works.
Let’s do one together and then you can do as many as it takes
for you to understand it. How about if value == 20.
99: is value >= 8 - Yes, 20 is greater than 8.
100: graphBitmap[GRAPH_HEIGHT - 1 - i] = 0xFF // all turned on
since GRAPH_HEIGHT is 5 and i is 0, then this will set
graphBitmap[4]
to 0xFF
101: value -= 8. Now value = 12.
102: i++. (i is now 1)
99: is value >= 8. Yes, 12 is greater than 8.
100: graphBitmap[GRAPH_HEIGHT - 1 - i (1)] = 0xFF
since GRAPH_HEIGHT is 5 and i is 1, then this will set graphBitmap[3]
to 0xFF
101: value -= 8. Now value = 4.
102: i++ (i is now 2)
99: is value >=8. No, 4 is not greater than 8
104: if(i != GRAPH_HEIGHT) (it isn’t, i = 2, GRAPH_HEIGHT = 5)
105: graphBitmap[GRAPH_HEIGHT - 1 - i (2)] = dataBitmap[value
(4)]
since GRAPH_HEIGHT is 5 and i is 2, then this will set graphBitmap[2]
to the value of dataBitmap[4] which is 0xF0.
So at the end, our graphBitmap will look like :
0x00, 0x00, 0xF0, 0xFF, 0xFF
(or in binary: 0b00000000, 0b00000000, 0b11110000, 0b11111111,
0b11111111)
88
6.4 Exercises
6.4 Exercises
1. Change the circuit and the program to have a button
connected, and when the button is pressed the graph starts
over.
2. Change the circuit and the program so there is a button that
lets you change between Celsius and Farenheit.
3. SUPER CHALLENGE: Change the program to change the
scale of the graph to have an auto-scale. (ie, At any time the
graph has at the bot- tom the minimum temp observed, and
the top is the maximum temp observed. Remove the
thermometer graphic and show the scale of the graph on the
LCD.)
89
Chapter 7
Sensors Galore
7.1 Introduction
The purpose of this chapter is to give you a taste of the wide
variety of different types of sensors that you can hook up to a
micro-controller. For this chapter, we will have four inexpensive
sensors. They will detect light, tilt, magnetic field, and vibrations.
91
Chapter 7 Sensors
Galore
3. Connect a 10kX (brown, black, orange) resistor on the far right and i2.
4. Connect one end of the photo cell in the next to right and the
other end in j2.
5. Connect h2 to A0 on the Arduino.
The photo cell we are using acts like a potentiometer that has lower
resistance the more light it sees. This is not a high precision
instrument that measures exactly how much light there is. But it
can be used to know whether a light is on in a room. You could
also put it inside a drawer and know when it is opened.
Here is some sample code:
Listing 7.1: photocell/photocell.pde
1 const int kPin_Photocell = A0;
2
3 void setup()
4
5 Serial.begin(9600);
6
7
8 void loop()
9
10 int value = analogRead(kPin_Photocell);
11
12 Serial.print("Analog Reading = ");
13 Serial.print(value);
14 if(value < 200){
15 Serial.println(" - Dark");
16 }else if(value < 400){
17 Serial.println(" - Dim");
18
19 else if(value < 600){
20 Serial.println(" - Light");
21
22 else if(value < 800){
23 Serial.println(" - Bright");
92
7.3 Tilt Sensor
24
25 else{
26 Serial.println(" - Very Bright");
27
28 delay(1000);
29
93
Chapter 7 Sensors
Galore
A tilt sensor is a switch that can determine when it is tilted. It works
by having a metal ball inside and when it is tilted the ball is over
the two contacts, so electricity can flow through the ball.
(This code uses the LED next to “L”. If you want to hook up an
LED and connect it to pin 13, you can.)
You’ll notice that we use the pull-up resistor just like we did with
the push- buttons in section 3.1, so LOW means that it isn’t tilted. and
HIGH means that it is.
94
7.4 Reed Switch (Magnetic Field Detector)
95
Chapter 7 Sensors
Galore
6 pinMode(kPinReedSwitch, INPUT);
7 digitalWrite(kPinReedSwitch, HIGH); // turn on pullup ←›
‹→ resistor
8 pinMode(kPinLed, OUTPUT);
9
10
11 void loop()
12
13 if(digitalRead(kPinReedSwitch) == LOW){
14 digitalWrite(kPinLed, HIGH);
15
16 else{
17 digitalWrite(kPinLed, LOW);
18
19
96
7.5 Piezo Element (Vibration sensor)
void setup()
8 {
9 pinMode(kPinLed, OUTPUT); // declare the ledPin as as ←›
‹→ OUTPUT
10 }
11
12 void loop()
13 {
14 int val = analogRead(kPinSensor);
15
21
The threshold is just to make sure it was a real knock, and not
some other vibration from the room. You can adjust this value to
see what works best for
97
Chapter 7 Sensors
Galore
you. A5 was just selected on the Arduino because I was originally
using this in part of a larger project. You can use any of the analog
inputs (as long as your circuit and program match)
7.6 Exercises
1. Hook up a photo cell and an LED. Have the LED shine
brighter (using PWM) when there is more light and dimmer
when there is less light.
2. Hook up a Tilt Sensor and the speaker. Have activating of the
tilt sensor make an alarm go off.
3. Use the reed switch and the magnet to make a sound when
the magnet is close.
4. Hook up the piezo element and use it to play a tune after someone
knocks.
a) HUGE CHALLENGE: Light an LED after someone knocks
a correct pattern (say 3 in a row followed by silence.)
98
Chapter 8
99
Chapter 8 Making a rubber
band gun
3. Put the potentiometer in f1, f2, f3.
4. Connect j1 to the next to right column (+5V).
5. Connect j3 to the far right column (GND).
6. Connect j2 to A0 on the Arduino.
7. Connect the red wire of the servo to +5V (next to right column).
8. Connect the black wire of the servo to GND (far right column).
9. Connect the white wire of the servo to pin 9 on the Arduino.
This program lets you turn the potentiometer and the servo rotates as
you turn it.
Listing 8.1: servo1/servo1.pde
1 #include
2
3
<Servo.h> Servo
4
5
6
servo1;
7
8 const int kPinPot = A0;
9 const int kPinServo1 = 9;
10
11 void setup()
12 {
13
servo1.attach(kPinServo1);
14
}
15
16
17
void loop()
18 {
19 int val = analogRead(kPinPot);
val = map(val, 0, 1023, 0, 180);
There are only two things in here that are new. One is attaching
servo1.write(val);
the servo (telling it what pin it is on.) The second is sending it a
delay(15);
value (0 to 180) for the angle.
100
8.2 Joystick
8.2 Joystick
We have a thumb joystick that we will use. It is made up of 2
potentiometers (one for the x-axis and one for the y-axis) and a
switch (for when the button is pressed).
101
Chapter 8 Making a rubber
band gun
Listing 8.2: joystick/joystick.pde
1 const int kPinJoystickX = A5;
2 const int kPinJoystickY = A4;
3 const int kPinJoystickFire = 2;
4
5 const int JOYX_LEFT = 300;
6 const int JOYX_RIGHT = 700;
7 const int JOYY_UP = 700;
8 const int JOYY_DOWN = 300;
9
10 void setup()
11 {
12 pinMode(kPinJoystickFire, INPUT);
13 digitalWrite(kPinJoystickFire, HIGH); // turn on pull-up ←›
‹→ resistor
14 Serial.begin(9600);
15 }
16
17 void loop()
18 {
19 int xVal = analogRead(kPinJoystickX);
20 int yVal = analogRead(kPinJoystickY);
21
22 Serial.print("x = ");
23 Serial.print(xVal);
24 Serial.print(" y = ");
25 Serial.print(yVal);
26 Serial.print(’ ’);
27
28 if(xVal < JOYX_LEFT){
29 Serial.print(’L’);
30 }
31 else if(xVal > JOYX_RIGHT){
32 Serial.print(’R’);
33 }
34 if(yVal < JOYY_DOWN){
35 Serial.print(’D’);
36 }
102
8.3 Pan/Tilt
bracket
37 else if(yVal > JOYY_UP){
38 Serial.print(’U’);
39 }
40 if(digitalRead(kPinJoystickFire) == LOW){
41 Serial.print("+F");
42 }
43 Serial.println();
44
45 delay(100); // Keep from overwhelming serial
46 }
Since the readings from the joystick are within a range of 0 to
1023, we break the range down into sections. We call less than 300
LEFT (or UP), greater than 700 RIGHT (or DOWN), and just let
everything in the middle count as CEN- TER.
The +F is to show that the joystick has been pressed down.
(HINT: If you don’t take apart the circuit in the last section, you can start
with step 9.)
103
Chapter 8 Making a rubber
band gun
1. Connect the far right column to GND on the Arduino.
2. Connect the next to right column to +5V on the Arduino.
3. Put the Joystick breakout board in d1-d5.
4. Connect a1 on breadboard to the next to right column (+5V).
5. Connect a2 on breadboard to A5 on the Arduino.
6. Connect a3 on breadboard to A4 on the Arduino.
7. Connect a4 on breadboard to pin 2 on the Arduino.
8. Connect a5 on breadboard to the far right column (GND).
9. Connect the black wire of the servo on bottom (the pan servo)
to the far right column (GND)
10. Connect the red wire of the servo on bottom (the pan servo)
to the next to right column (+5V)
11. Connect the white wire of the servo on bottom (the pan servo)
to pin 9 on the Arduino.
12. Connect the black wire of the servo in the middle (the tilt
servo) to the far right column (GND)
13. Connect the red wire of the servo in the middle (the tilt servo)
to the next to right column (+5V)
14. Connect the white wire of the servo in the middle (the tilt
servo) to pin 10 on the Arduino.
104
8.3 Pan/Tilt
bracket
5 const int kPinJoystickFire = 2;
6 const int kPinServoPan = 9;
7 const int kPinServoTilt = 10;
8
9 const int JOYX_LEFT = 300;
10 const int JOYX_RIGHT = 700;
11 const int JOYY_UP = 700;
12 const int JOYY_DOWN = 300;
13
14 Servo panServo;
15 Servo tiltServo;
16
17 int panAngle = 0;
18 int tiltAngle = 90;
19
20 void setup()
21 {
22 panServo.attach(kPinServoPan);
23 tiltServo.attach(kPinServoTilt);
24 }
25
26 void loop()
27 {
28 int xVal = analogRead(kPinJoystickX);
29 int yVal = analogRead(kPinJoystickY);
30
31 if(xVal < JOYX_LEFT){
32 panAngle--;
33 }
34 else if(xVal > JOYX_RIGHT){
35 panAngle++;
36 }
37 if(yVal < JOYY_DOWN){
38 tiltAngle--;
39 }
40 else if(yVal > JOYY_UP){
41 tiltAngle++;
42 }
43 tiltAngle = constrain(tiltAngle, 0, 180);
105
Chapter 8 Making a rubber
band gun
44 panAngle = constrain(panAngle, 0, 180);
45
46 panServo.write(panAngle);
47 tiltServo.write(tiltAngle);
48 delay(20); // wait for the servos to get there
49
(HINT: If you don’t take apart the circuit in the last section, you
can start with step 15)
1. Connect the far right column to GND on the Arduino.
2. Connect the next to right column to +5V on the Arduino.
3. Put the Joystick breakout board in d1-d5.
106
8.4 Adding a firing
mechanism
4. Connect a1 on breadboard to the next to right column (+5V).
9. Connect the black wire of the servo on bottom (the pan servo)
to the far right column (GND).
10. Connect the red wire of the servo on bottom (the pan servo)
to the next to right column (+5V).
11. Connect the white wire of the servo on bottom (the pan servo)
to pin 9 on the Arduino.
12. Connect the black wire of the servo in the middle (the tilt
servo) to the far right column (GND).
13. Connect the red wire of the servo in the middle (the tilt servo)
to the next to right column (+5V).
14. Connect the white wire of the servo in the middle (the tilt
servo) to pin 10 on the Arduino.
15. Connect the black wire of the servo on the top (the fire servo)
to the far right column (GND).
16. Connect the red wire of the servo on the top (the fire servo) to
the next to right column (+5V).
17. Connect the white wire of the servo on the top (the fire servo)
to pin 11 on the Arduino.
107
Chapter 8 Making a rubber
band gun
Listing 8.4: rubberBandGun/rubberBandGun.pde
1 #include <Servo.h>
2
3 const int kPinJoystickX = A5;
4 const int kPinJoystickY = A4;
5 const int kPinJoystickFire = 2;
6 const int kPinServoPan = 9;
7 const int kPinServoTilt = 10;
8 const int kPinServoFire = 11;
9
10 const int JOYX_LEFT = 300;
11 const int JOYX_RIGHT = 700;
12 const int JOYY_UP = 700;
13 const int JOYY_DOWN = 300;
14
15 Servo panServo;
16 Servo tiltServo;
17 Servo fireServo;
18
19 int panAngle = 90;
20 int tiltAngle = 90;
21 int fireAngle = 0;
22
23 void setup()
24 {
25 pinMode(kPinJoystickFire, INPUT);
26 digitalWrite(kPinJoystickFire, HIGH); // turn on pull-up ←›
‹→ resistor
27 fireServo.attach(kPinServoFire);
28 fireServo.write(0);
29 delay(500);
30 fireServo.detach();
31 panServo.attach(kPinServoPan);
32 tiltServo.attach(kPinServoTilt);
33 }
34
35 void loop()
36 {
108
8.4 Adding a firing
mechanism
37 int xVal = analogRead(kPinJoystickX);
38 int yVal = analogRead(kPinJoystickY);
39
40 if(xVal < JOYX_LEFT){
41 panAngle--;
42 }
43 else if(xVal > JOYX_RIGHT){
44 panAngle++;
45 }
46 if(yVal < JOYY_DOWN){
47 tiltAngle--;
48 }
49 else if(yVal > JOYY_UP){
50 tiltAngle++;
51 }
52 tiltAngle = constrain(tiltAngle, 0, 180);
53 panAngle = constrain(panAngle, 0, 180);
54
55 panServo.write(panAngle);
56 tiltServo.write(tiltAngle);
57 delay(20); // wait for the servos to get there
58
59 if(digitalRead(kPinJoystickFire) == LOW){
60 fireServo.attach(kPinServoFire);
61 fireServo.write(180);
62
delay(500);
63
fireServo.write(0);
64
65
delay(500);
66
fireServo.detach();
while(digitalRead(kPinJoystickFire) == LOW){
67 // wait for it not to be low anymore
68 }
69 }
70 }
The reason why we attach and detach the firing servo is that we
don’t move it very often and we don’t want to send it commands
continuously when we won’t use it very often. This is for power
reasons.
109
Chapter 8 Making a rubber
band gun
The fireServo.write(180) is the line that actually fires the rubber band.
Then it goes back to 0 so we can load the next rubber band on it.
8.5 Exercises
1. Hook up the joystick and 5 LEDs. One that shows when the
joystick is pressed up, one for down, one for left, one for
right, and one for fire.
2. Make a servo do a slow sweep from 0 to 180 and then back again.
3. CHALLENGE: After firing a rubber band, play a victory tune!
110
Chapter 9
Make your own project!
Now it is time to unleash your creativity. Hopefully as we have gone
through these sections, you have started to think of other things
that would be neat to make. One of the great things about micro-
controllers is how many things you can make.
It is now time for you to make your own project. Below is a
sample list of projects that you can make with the parts that are in
your kit. Make something off this list or something you have
thought of. Just make something!!
• A stopwatch (uses the LCD, push buttons)
• A count down timer (uses the LCD, push buttons, speaker)
• An alarm clock (Challenging, as you have to do all of the
programming to allow the setting of the time) - (uses the LCD,
push buttons, speaker)
• An alarm when the temperature goes out of a set range
• Let someone knock using the knock sensor and have the
controller play it back (as either sound or lights)
• Make a dial that shows the temperature (use a servo and the
temperature sensor)
• Make a dial that shows the amount of light (use a servo and
the light sensor)
• Change tone playing on speaker based off of amount of light,
or temper- ature
111
Chapter 9 Make your own project!
• Alarm going off when reed switch opens (to let you know
when someone has opened a door)
• Data logger - time and temp, light - either on serial or LCD. As
a bonus, allow scrolling using either the joystick or
pushbuttons
• Morse code - one button dots, one button dashes. Saving/recording
• Enter message using joystick onto LCD, and then playback on
speaker with morse code when a button is pressed
• Traffic light simulation - include push buttons for car sensors
• A metronome (uses the speaker, LCD and pushbuttons (or a
potentiome- ter))
• If you have great ideas, please give them to me and I’ll add
them to future versions of the book!!
112
Chapter 10
Next Steps
If you enjoyed this book, then there is lots more you can learn. I
would rec- ommend looking at a few websites for inspiration.
(Make sure you have your parent’s permission and be careful of
anyone that asks for contact information online.)
• http://www.arduino.cc
• http://www.sparkfun.com
• http://www.adafruit.com
• http://www.makezine.com
I would also recommend the book Arduino Cookbook by Michael
Margolis. Here are a few ideas of more complicated projects that I
have seen made with an Arduino.
• A box that will only open when it is at a certain location in the
world (It connects a GPS to the Arduino. Search on “Reverse
Geo-cache” to see examples.)
• An alarm clock that rolls away from you when it goes off
• An alarm clock that you set by tilting back and forth
• A Thermostat
• A controller for a 3D printer
113
Chapter 10 Next Steps
• Robots
• A module that goes in a model rocket and keeps track of the
acceleration so it can be charted upon recovery
• A full weather station (wind speed, rain amounts, humidity,
temperature, barometer, etc.)
• and much, much more!!
I hope you have enjoyed this introduction. What you can create is
limited only by your creativity (and budget!) Areas for future study
would be interfacing with more types of sensors, more
sophisticated programming, more powerful micro-controllers, and
much much more!
This is the end of this book, but only the beginning of your
journey! Please let me know what you have made as I will be
excited to see your creations! You can contact me at:
[email protected]
114
Appendix A
Arduino Reference
In fact, if you look online you’ll notice that I used the same
structure to split things up as they do online. The online reference
is really good with examples for each one.
1It puts a #include before the beginning, scans the file for functions and puts
the prototypes at the top of the file, and then includes a main() function at the
bottom that calls setup() and loop()
115
Appendix A Arduino Reference
A.1 Structure
117
Operator Meaning
= assignment operator
+ addition operator
- subtraction operator
* multiplication operator
/ division - be aware that if you are using integers only
the whole
part is kept. It is NOT rounded. For example: 5 / 2 ==
2
% modulo - This gives the remainder. For example: 5 % 2
== 1
Operator Meaning
== is equal to
!= is not equal to
< is less than
> is greater than
<= is less than or equal to
>= is greater than or equal to
117
! !(A < 10) logical NOT (return TRUE if
con- dition A is false,
otherwise return TRUE)
118
A.1.6 Pointer Access Operators
Pointers are very powerful but can also be fraught with danger. The
easiest way to understand pointers is to know that to the computer,
all data has a memory address. (where it lives in memory) An
explanation of pointers is outside the scope of this book, but I am
including the operators here for completeness.
We have not talked about bitwise operators in this book. These are
included only for completeness.
119
A.1
Structure
A.1.8 Compound Operators
119
Appendix A Arduino
Reference
A.2 Variables
A.2.1 Constants
121
A.3
Functions
A.2.3 Conversion
Name Brief Description
char() converts to the char type
byte() converts to the byte type
int() converts to the int type
word() converts to the word type
long() converts to the long type
float() converts to the float type
A.2.5 Utilities
sizeof() - returns the size ofa variable in bytes
A.3 Functions
A.3.4 Time
123
A.3
Functions
A.3.5 Math
Name Brief Description
min() returns the minimum of two values
max() returns the maximum of two values
abs() returns the absolute value
constrain() See section 3.2.2 for details
map() See section 3.1.2.2 for details
pow() calculates the value of a number raised to a power
sqrt() calculates the value of the square root of a number
A.3.6 Trigonometry
123
Appendix A Arduino
Reference
A.3.9 External Interrupts
A.3.10 Interrupts
A.3.11 Communication
Serial Class - used partially in section 5.1. Full list of functions are:
Name Brief Description
Serial.begin() set the data rate
Serial.end() disables serial communication
Serial.available() Gets number of bytes available for
reading (al-
ready in the receive buffer which holds
128 bytes)
Serial.read() read incoming serial data (and removes
from
buffer)
Serial.peek() returns the next byte of serial data
without re-
moving from buffer
Serial.flush() removes all data in receive buffer
Serial.print() prints data to the serial port as human-
readable
ASCII text
Serial.println() prints data to the serial port as human-
124
A.3
readable Functions
A.3.5 Math ASCII text followed by a newline
Serial.write() sends data byte to the serial port
125
A.4 PCD8544 (LCD Controller) Library
126
A few notes on init(). There are four different ways you can use it:
1. The way we have used it throughout this book.
lcd.init(kPIN_CLK, kPin_DIN, kPin_DC, kPin_RESET);
4. Having CS (chip select) under program control, but not the backlight.
lcd.init(kPin_CLK, kPin_DIN, kPin_DC, kPin_RESET, -1, kPin_CS);
127
Appendix A Arduino
Reference
Appendix B
Parts in Kit
128
Appendix B Parts in Kit
128
B.8 First used in Chapter 8
129
Appendix C
131
Appendix C Sample Solutions to Selected Exercises
2
3 void setup()
4
5
pinMode(kPinLed, OUTPUT);
6
7
8
9
void loop()
10
11 digitalWrite(kPinLed,
12 HIGH); delay(500);
13 digitalWrite(kPinLed, LOW);
14 delay(1000);
10 void setup()
11 {
12 pinMode(kPinLed1, OUTPUT);
13 pinMode(kPinLed2, OUTPUT);
14 pinMode(kPinLed3, OUTPUT);
15 pinMode(kPinLed4, OUTPUT);
16 pinMode(kPinLed5, OUTPUT);
17 pinMode(kPinLed6, OUTPUT);
18 pinMode(kPinLed7, OUTPUT);
19 pinMode(kPinLed8, OUTPUT);
20 }
21
22 void loop()
23 {
132
24
25
// turn on the LEDs
26 digitalWrite(kPinLed1, HIGH);
27 delay(500);
28 digitalWrite(kPinLed2, HIGH);
29 delay(500);
30 digitalWrite(kPinLed3, HIGH);
31
delay(500);
32
digitalWrite(kPinLed4, HIGH);
33
delay(500);
34
35
digitalWrite(kPinLed5, HIGH);
36
delay(500);
37 digitalWrite(kPinLed6, HIGH);
38 delay(500);
39 digitalWrite(kPinLed7, HIGH);
40 delay(500);
41 digitalWrite(kPinLed8, HIGH);
42 delay(500);
43
// Now turn them off
44
digitalWrite(kPinLed1,
45
LOW); delay(500);
46
digitalWrite(kPinLed2,
47
48
LOW); delay(500);
49
digitalWrite(kPinLed3,
50 LOW); delay(500);
51 digitalWrite(kPinLed4,
52 LOW); delay(500);
53 digitalWrite(kPinLed5,
54 LOW); delay(500);
55 digitalWrite(kPinLed6,
56 LOW); delay(500);
57 digitalWrite(kPinLed7,
LOW); delay(500);
58 } digitalWrite(kPinLed8,
LOW);
delay(1000); // wait 1 second with them all off before ←›
‹→ starting again
133
C.2 Chapter 2 Solutions
void loop()
9 {
10 for(int i = 0; i < 5; i++){
11 digitalWrite(kPinLed, HIGH);
12 delay(1000);
13 digitalWrite(kPinLed, LOW);
14 delay(1000);
15 }
134
C.3 Chapter 3
Solutions
16 for(int i = 0; i < 5; i++){
17 digitalWrite(kPinLed, HIGH);
18 delay(500);
19 digitalWrite(kPinLed, LOW);
20 delay(500);
21 }
22 }
135
Appendix C Sample Solutions to Selected
Exercises
Listing C.7: solutions/Chap3_1/Chap3_1.pde
1 const int kPinButtonGas = 2;
2
const int kPinButtonBrake = 3;
3
const int kPinLed = 9;
4
5
6
void setup()
7
{
8 pinMode(kPinButtonGas, INPUT);
9 pinMode(kPinButtonBrake, INPUT);
10 pinMode(kPinLed, OUTPUT);
digitalWrite(kPinButtonGas, HIGH); // turn on pullup ←›
11 ‹→ resistor
digitalWrite(kPinButtonBrake, HIGH); // turn on pullup ←›
12
13
‹→ resistor
14
}
15
16
int delayTime = 500;
17 long lastTime = 0;
18 int ledState = LOW;
19 void loop()
20 {
21 if(digitalRead(kPinButtonGas) == LOW)
22 { delayTime = delayTime--;
23
}
24
else if(digitalRead(kPinButtonBrake) == LOW)
25
{ delayTime = delayTime++;
26
27 }
28 delayTime = constrain(delayTime, 10, 5000);
29 if((lastTime + delayTime) < millis())
30 { ledState = !ledState;
31 digitalWrite(kPinLed, ledState);
32 lastTime = millis();
}
Listing C.8: solutions/Chap3_2/Chap3_2.pde
delay(10);
1
}
const int kPinPot = A0;
136
C.3 Chapter 3
Solutions
2 const int kPinButton = 2;
3 const int kPinLed = 9;
4
5 void setup()
6
7 pinMode(kPinLed, OUTPUT);
8 pinMode(kPinButton, INPUT);
9 digitalWrite(kPinButton, HIGH); // enable pull-up resistor
10
11
12 long int lastTime = 0;
13 int ledValue = LOW;
14 int sensorValue;
15
16 void loop()
17
18 if(digitalRead(kPinButton) == LOW){
19 sensorValue = analogRead(kPinPot);
20
21 if(millis() > lastTime + sensorValue){
22 if(ledValue == LOW){
23 ledValue = HIGH;
24
25 else{
26 ledValue = LOW;
27
28 lastTime = millis();
29 digitalWrite(kPinLed, ledValue);
30
31
137
Appendix C Sample Solutions to Selected
Exercises
7 const int kPinBtnTo = 2;
8 const int kPinBtnFrom = 3;
9
10 void setup()
11 {
12 pinMode(kPinLed_R, OUTPUT);
13 pinMode(kPinLed_G, OUTPUT);
14 pinMode(kPinLed_B, OUTPUT);
15 pinMode(kPinBtnTo, INPUT);
16 pinMode(kPinBtnFrom, INPUT);
17 digitalWrite(kPinBtnTo, HIGH); // enable pull-up resistor
18 digitalWrite(kPinBtnFrom, HIGH); // enable pull-up resistor
19 }
20
21 int fromRed = 0;
22 int fromGreen = 0;
23 int fromBlue = 0;
24 int toRed = 255;
25 int toGreen = 255;
26 int toBlue = 255;
27
28 int currStep = 0;
29 int change = 1;
30
31 void loop()
32 {
33 int pot1Value;
34 int pot2Value;
35 int pot3Value;
36
37 pot1Value = analogRead(kPinPot1);
38 pot2Value = analogRead(kPinPot2);
39 pot3Value = analogRead(kPinPot3);
40
41 if(digitalRead(kPinBtnFrom) == LOW){
42 fromRed = map(pot1Value, 0, 1023, 0, 255);
43 analogWrite(kPinLed_R, fromRed);
44
45 fromGreen = map(pot2Value, 0, 1023, 0, 255);
138
C.3 Chapter 3
Solutions
46 analogWrite(kPinLed_R, fromGreen);
47
48
fromBlue = map(pot3Value, 0, 1023, 0, 255);
49
analogWrite(kPinLed_R, fromBlue);
50 }
139
Appendix C Sample Solutions to Selected
Exercises
C.4 Chapter 4 Solutions
140
C.4 Chapter 4
Solutions
36 tone(speakerPin, freq, duration);
37 delay(duration);
38 noTone(speakerPin);
39
13 };
14
15 const int beats_tune1[NUM_NOTES_TUNE1] = {
16 1, 1, 2, 2, 2, 4, 4 };
17
18 #define NUM_NOTES_TUNE2 15
19
26 };
27
28 const int beats_tune2[NUM_NOTES_TUNE2] = {
29 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
30
141
Appendix C Sample Solutions to Selected
Exercises
31 const int tempo = 300;
32
33 void setup()
34 {
35 pinMode(k_speakerPin, OUTPUT);
36 pinMode(k_btn1Pin, INPUT);
37 pinMode(k_btn2Pin, INPUT);
38 digitalWrite(k_btn1Pin, HIGH); // turn on pull-up resistor
39 digitalWrite(k_btn2Pin, HIGH); // turn on pull-up resistor
40 }
41
42 void loop()
43 {
44 if(digitalRead(k_btn1Pin) == LOW){
45 playTune1();
46 }
47 if(digitalRead(k_btn2Pin) == LOW){
48 playTune2();
49 }
50 }
51
52 void playTune1()
53 {
54 for (int i = 0; i < NUM_NOTES_TUNE1; i++) {
55 if (notes_tune1[i] == 0) {
56 delay(beats_tune1[i] * tempo); // rest
57 }
58 else {
59 ourTone(notes_tune1[i], beats_tune1[i] * tempo);
60 }
61 // pause between notes
62 delay(tempo / 2);
63 }
64 }
65
66 void playTune2()
67 {
68 for (int i = 0; i < NUM_NOTES_TUNE2; i++) {
69 if (notes_tune2[i] == 0) {
142
C.4 Chapter 4
Solutions
70 delay(beats_tune2[i] * tempo); // rest
71
72 else {
73 ourTone(notes_tune2[i], beats_tune2[i] * tempo);
74
75
// pause between notes
76
delay(tempo / 2);
77
78
79
80
81 void ourTone(int freq, int duration)
82
83 tone(k_speakerPin, freq, duration);
84 delay(duration);
85
noTone(k_speakerPin);
143
Appendix C Sample Solutions to Selected
Exercises
21 void loop() {
22 for (int i = 0; i < NUM_NOTES; i++) {
23 if (notes[i] == 0)
24
{ delay(beats[i] * tempo); //
25
26
rest
27
}
28
else {
29 ourTone(notes[i], beats[i] * tempo);
30 }
31 // pause between notes
32 delay(tempo / 2);
33 }
34 }
35
36
void ourTone(int freq, int duration)
{
37
38 long timeDelay = (1000000 / (2 * freq)); // calculate num ←›
39 ‹→ of microsec to delay
40 long endTime = millis() + duration;
41 // will have a bug with rollover time
42 while(millis() < endTime)
43 { digitalWrite(k_speakerPin,
44 HIGH);
45
delayMicroseconds(timeDelay);
digitalWrite(k_speakerPin, LOW);
delayMicroseconds(timeDelay);
}
C.5 Chapter 5 Solutions
144
C.5 Chapter 5
Solutions
7 const int kPin_Temp = A0;
8
ET);
9 PCD8544 lcd(kPin_CLK, kPin_DIN, kPin_DC, kPin_RES
10
11 void setup()
12 {
13 lcd.init();
14 lcd.setCursor(10,0);
15 lcd.print("Temperature:");
16 }
17
18 void loop()
19 {
20 float voltage = getVoltage();
21 float temperatureC = getTemperatureC(voltage);
22 // now convert to Fahrenheit
23 float temperatureF = convertToF(temperatureC);
24
25 lcd.setCursor(21,1);
26 lcd.print(temperatureC);
27 lcd.print(" C ");
28 lcd.setCursor(21,2);
29 lcd.print(temperatureF);
30 lcd.print(" F");
31 lcd.setCursor(21,3);
32 lcd.print(voltage);
33 lcd.print(" V");
34 delay(100);
35 }
36
37 float getVoltage()
38 {
39 int reading = analogRead(kPin_Temp);
40
41 return (reading * 5.0) / 1024;
42 }
43
44 float getTemperatureC(float voltage)
45 {
145
Appendix C Sample Solutions to Selected
Exercises
46 // convert from 10 mv per degree with 500mV offset
47 // to degrees ((voltage - 500mV) * 100)
48 return (voltage - 0.5) * 100;
49
50
51 float convertToF(float temperatureC)
52
53 return (temperatureC * 9.0 / 5.0) + 32.0;
54
146
C.5 Chapter 5
Solutions
28 maxTemp = temperatureF;
29
30
if(temperatureF < minTemp)
31
{ minTemp = temperatureF;
32
33
}
34
35
lcd.setCursor(16,1);
36 lcd.print(temperatureF);
37 lcd.print(" F");
38 lcd.setCursor(16, 2);
39 lcd.print(maxTemp);
40 lcd.print(" F max");
41
lcd.setCursor(16, 3);
42
lcd.print(minTemp);
43
44
lcd.print(" F min");
} delay(100);
45
46 float getTemperatureC()
47 {
48 int reading = analogRead(kPin_Temp);
49
147
Appendix C Sample Solutions to Selected
Exercises
5 const int kPin_DC = 7;
6 const int kPin_RESET = 8;
7 const int kPin_Temp = A0;
8
9 PCD8544 lcd(kPin_CLK, kPin_DIN, kPin_DC, kPin_RESET);
10
11 void setup()
12 {
13 lcd.init();
14 lcd.setCursor(10,0);
15 lcd.print("Temperature:");
16 }
17
18 float maxTemp = -200; // smaller than we can ever see
19 long maxTime;
20 float minTemp = 200; // larger than we can ever see
21 long minTime;
22
23 void loop()
24 {
25 float temperatureC = getTemperatureC();
26 // now convert to Fahrenheit
27 float temperatureF = convertToF(temperatureC);
28
29 if(temperatureF > maxTemp){
30 maxTemp = temperatureF;
31 maxTime = millis();
32 }
33 if(temperatureF < minTemp){
34 minTemp = temperatureF;
35 minTime = millis();
36 }
37
38 lcd.setCursor(21,1);
39 lcd.print(temperatureF);
40 lcd.print(" F");
41 lcd.setCursor(0, 2);
42 lcd.print(maxTemp);
43 lcd.print(" F max");
148
C.6 Chapter 6
Solutions
44 lcd.setCursor(0,3);
45 lcd.print((millis() - maxTime) / 1000);
46 lcd.print(" secs ago");
47 lcd.setCursor(0, 4);
48 lcd.print(minTemp);
49 lcd.print(" F min");
50 lcd.setCursor(0,5);
51 lcd.print((millis() - minTime) / 1000);
52 lcd.print(" secs ago");
53
54 delay(100);
55 }
56
57 float getTemperatureC()
58 {
59 int reading = analogRead(kPin_Temp);
60
61 float voltage = (reading * 5.0) / 1024;
62 // convert from 10 mv per degree with 500mV offset
63 // to degrees ((voltage - 500mV) * 100)
64 return (voltage - 0.5) * 100;
65 }
66
67 float convertToF(float temperatureC)
68 {
69 return (temperatureC * 9.0 / 5.0) + 32.0;
70 }
149
Appendix C Sample Solutions to Selected
Exercises
6 const int kPin_DC = 7;
7 const int kPin_RESET = 8;
8 const int kPin_Temp = A0;
9
10 PCD8544 lcd(kPin_SCLK, kPin_SDIN, kPin_DC, kPin_RESET);
11
12 // A bitmap graphic (5x1) of a degree symbol
13 const int DEGREE_WIDTH = 5;
14 const int DEGREE_HEIGHT = 1;
15 const byte degreesBitmap[] = { 0x00, 0x07, 0x05, 0x07, 0x00 ←›
‹→ };
16
17 // A bitmap graphic (10x2) of a thermometer...
18 const int THERMO_WIDTH = 10;
19 const int THERMO_HEIGHT = 2;
20 const byte thermometerBitmap[] =
21 { 0x00, 0x00, 0x48, 0xfe, 0x01, 0xfe, 0x00, 0x02, 0x05, 0x02,
22 0x00, 0x00, 0x62, 0xff, 0xfe, 0xff, 0x60, 0x00, 0x00, 0x00←›
‹→ };
23
24 const int LCD_WIDTH = 84;
25 const int LCD_HEIGHT = 6;
26 const int GRAPH_HEIGHT = 5;
27
28 const int MIN_TEMP = 50;
29 const int MAX_TEMP = 100;
30
31 void setup()
32 {
33 pinMode(kPin_Btn, INPUT);
34 digitalWrite(kPin_Btn, HIGH); // turn on pull-up resistor
35 lcd.init();
36 lcd.setCursor(10,0);
37 lcd.print("Temperature:");
38 lcd.setCursor(0, LCD_HEIGHT - THERMO_HEIGHT);
39 lcd.drawBitmap(thermometerBitmap, THERMO_WIDTH, ←›
‹→ THERMO_HEIGHT);
40 }
41
150
C.6 Chapter 6
Solutions
42 int xChart = LCD_WIDTH;
43
44 void loop()
45 {
46 float temperatureC = getTemperatureC();
47 // now convert to Fahrenheit
48 float temperatureF = convertToF(temperatureC);
49
50 if(digitalRead(kPin_Btn) == LOW){
51 xChart = THERMO_WIDTH + 2;
52 lcd.setCursor(xChart, 2);
53 // clear it
54 while(xChart <= LCD_WIDTH){
55 drawColumn(0);
56 xChart++;
57 }
58 xChart = THERMO_WIDTH + 2;
59 }
60
61 lcd.setCursor(21,1);
62 lcd.print(temperatureF);
63 lcd.drawBitmap(degreesBitmap, DEGREE_WIDTH, DEGREE_HEIGHT);
64 lcd.print(" F");
65 if(xChart >= LCD_WIDTH){
66 xChart = THERMO_WIDTH + 2;
67 }
68 lcd.setCursor(xChart, 2);
69 int dataHeight = map(temperatureF, MIN_TEMP, MAX_TEMP, 0, ←›
‹→ GRAPH_HEIGHT * 8);
70
71 drawColumn(dataHeight);
72 drawColumn(0); // marker to see current chart position
73 xChart++;
74
75 delay(500);
76 }
77
78 float getTemperatureC()
79 {
151
Appendix C Sample Solutions to Selected
Exercises
80 int reading = analogRead(kPin_Temp);
81
82 float voltage = (reading * 5.0) / 1024;
83 // convert from 10 mv per degree with 500mV offset
84 // to degrees ((voltage - 500mV) * 100)
85 return (voltage - 0.5) * 100;
86 }
87
88 float convertToF(float temperatureC)
89 {
90 return (temperatureC * 9.0 / 5.0) + 32.0;
91 }
92
93 const byte dataBitmap[] =
94 {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
95
96 void drawColumn(unsigned int value)
97 {
98 byte graphBitmap[GRAPH_HEIGHT];
99 int i;
100
101 if(value > (GRAPH_HEIGHT * 8)){
102 value = GRAPH_HEIGHT * 8;
103 }
104 // value is number of pixels to draw
105
106 //1. clear all pixels in graphBitmap
107 for(i = 0; i < GRAPH_HEIGHT; i++){
108 graphBitmap[i] = 0x00;
109 }
110
111 //2. Fill all of the ones that should be completely full
112 i = 0;
113 while(value >= 8){
114 graphBitmap[GRAPH_HEIGHT - 1 - i] = 0xFF;
115 value -= 8;
116 i++;
117 }
118 if(i != GRAPH_HEIGHT){
152
C.6 Chapter 6
Solutions
119 graphBitmap[GRAPH_HEIGHT - 1 - i] = dataBitmap[value];
120
121
lcd.drawBitmap(graphBitmap, 1, GRAPH_HEIGHT);
122
153
Appendix C Sample Solutions to Selected
Exercises
31 void setup()
32 {
33 pinMode(kPin_Btn, INPUT);
34 digitalWrite(kPin_Btn, HIGH); // turn on pull-up resistor
35 lcd.init();
36 lcd.setCursor(10,0);
37 lcd.print("Temperature:");
38 lcd.setCursor(0, LCD_HEIGHT - THERMO_HEIGHT);
39 lcd.drawBitmap(thermometerBitmap, THERMO_WIDTH, ←›
‹→ THERMO_HEIGHT);
40 }
41
42 int xChart = LCD_WIDTH;
43 bool displayF = true;
44
45 void loop()
46 {
47 float temperatureC = getTemperatureC();
48 // now convert to Fahrenheit
49 float temperatureF = convertToF(temperatureC);
50
51 if(digitalRead(kPin_Btn) == LOW){
52 displayF = !displayF;
53 while(digitalRead(kPin_Btn) == LOW){
54 }
55 }
56
57 lcd.setCursor(21,1);
58 if(displayF){
59 lcd.print(temperatureF);
60 }
61 else{
62 lcd.print(temperatureC);
63 }
64 lcd.drawBitmap(degreesBitmap, DEGREE_WIDTH, DEGREE_HEIGHT);
65 if(displayF){
66 lcd.print(" F");
67 }
68 else{
154
C.6 Chapter 6
Solutions
69 lcd.print(" C");
70 }
84 float getTemperatureC()
85 {
86 int reading = analogRead(kPin_Temp);
87
88 float voltage = (reading * 5.0) / 1024;
89 // convert from 10 mv per degree with 500mV offset
90 // to degrees ((voltage - 500mV) * 100)
91 return (voltage - 0.5) * 100;
92 }
93
94 float convertToF(float temperatureC)
95 {
96 return (temperatureC * 9.0 / 5.0) + 32.0;
97 }
98
99 const byte dataBitmap[] =
100 {0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE};
101
102 void drawColumn(unsigned int value)
103 {
104 byte graphBitmap[GRAPH_HEIGHT];
105 int i;
106
155
Appendix C Sample Solutions to Selected
Exercises
107 if(value > (GRAPH_HEIGHT * ){
108 8) value = GRAPH_HEIGHT *
109 8;
110 to draw
111 // value is number of pixels
112
phBitmap
113
//1. clear all pixels in i++){
114
gra
115
for(i = 0; i < GRAPH_HEIGHT;
116
117
graphBitmap[i] = 0x00;
118 at should be completely full
119
120 //2. Fill all of the ones
th
- 1 - i] = 0xFF;
i = 0;
while(value >= 8){
graphBitmap[GRAPH_HEIGHT
121 value -= 8;
122 i++;
123 }
124 if(i != GRAPH_HEIGHT){
125 graphBitmap[GRAPH_HEIGHT - 1 - i] = dataBi map[value];
126 }
127 lcd.drawBitmap(graphBitmap, 1, GRAPH_HEIGHT);
128 }
156
C.6 Chapter 6
10
Solutions
157
C.7 Chapter 7
Solutions
11 int value = analogRead(kPin_Photocell);
12 int brightness = map(value, 0, 1023, 0, 255);
13
14 analogWrite(kPin_LED, brightness);
15
Listing C.19:
solutions/Chap7_2/Chap7_2.pde
1 const int kPin_Tilt = 3;
2 const int kPin_LED = 13;
3 const int kPin_Speaker = 9;
4
5 void setup()
6
7 pinMode(kPin_Tilt, INPUT);
8 digitalWrite(kPin_Tilt, HIGH); // turn on built-in pull-up←›
‹→ resistor
9 pinMode(kPin_LED, OUTPUT);
10 pinMode(kPin_Speaker, OUTPUT);
11
12
13 void loop()
14
15 if(digitalRead(kPin_Tilt) == LOW){
16 digitalWrite(kPin_LED, HIGH);
17 soundAlarm();
18
19 else{
20 digitalWrite(kPin_LED, LOW);
21
22
23
24 void soundAlarm()
25
26 for(int freq = 440; freq < 4000; freq = freq * 2){
27 tone(9, 440);
28 delay(10);
29
30 noTone(9);
157
Appendix C Sample Solutions to Selected
Exercises
31
158
C.7 Chapter 7
Solutions
9 const int notes[NUM_NOTES] = // a 0 represents a rest
10 {
11 NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4,
12 NOTE_A4, NOTE_A4, NOTE_G4, NOTE_F4,
13 NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4,
14 NOTE_D4, NOTE_C4, 0
15 };
16
17 const int beats[NUM_NOTES] = {
18 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
19 const int tempo = 300;
20
21 void setup()
22 {
23 pinMode(k_speakerPin, OUTPUT);
24 }
25
26 void loop()
27 {
28 if (analogRead(k_sensorPin) >= k_threshold) {
29 playTune();
30 }
31 }
32
33 void playTune()
34 {
35 for (int i = 0; i < NUM_NOTES; i++) {
36 if (notes[i] == 0) {
37 delay(beats[i] * tempo); // rest
38 }
39 else {
40 ourTone(notes[i], beats[i] * tempo);
41 }
42 // pause between notes
43 delay(tempo / 2);
44 }
45 }
46
47
159
Appendix C Sample Solutions to Selected
Exercises
48
49 void ourTone(int freq, int duration)
50
51
tone(k_speakerPin, freq, duration);
52
delay(duration);
53
54
noTone(k_speakerPin);
160
C.8 Chapter 8
Solutions
25 }
26
27 void loop()
28 {
29 int xVal = analogRead(k_JoystickX_Pin);
30 int yVal = analogRead(k_JoystickY_Pin);
31
32 int left = false;
33 int right = false;
34 int up = false;
35 int down = false;
36 int fire = false;
37
38 if(xVal < JOYX_LEFT){
39 left = true;
40 }
41 else if(xVal > JOYX_RIGHT){
42 right = true;
43 }
44 if(yVal < JOYY_DOWN){
45 down = true;
46 }
47 else if(yVal > JOYY_UP){
48 up = true;
49 }
50 if(digitalRead(k_Joystick_Fire) == LOW){
51 fire = true;
52 }
53 digitalWrite(k_ledUP_Pin, up);
54 digitalWrite(k_ledDOWN_Pin, down);
55 digitalWrite(k_ledLEFT_Pin, left);
56 digitalWrite(k_ledRIGHT_Pin, right);
57 digitalWrite(k_ledFIRE_Pin, fire);
58 }
161
Appendix C Sample Solutions to Selected
Exercises
3 const int k_Servo_Pin = 9;
4
5 Servo servo;
6
7
8
void setup()
9
10
servo.attach(k_Servo_Pin);
11
12
13 void loop()
14
15 for(int i = 0; i < 180; i++){
16
servo.write(i);
17
delay(20);
18
19
20
for(int i = 180; i > 0; i--){
21 servo.write(i);
22 delay(20);
}
}
162