Documente Academic
Documente Profesional
Documente Cultură
Microcontrollers
with the Arduino
Version 2.89
This manual is furnished under license and may be used or copied only in accordance with the terms of such license. The
content of this manual is furnished for informational use only, is subject to change without notice, and should not be construed
as a commitment by TechShop Inc. Except as permitted by such license, no part of this publication may be reproduced, stored
in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the
prior written permission of TechShop Inc.
TechShop and the TechShop logo are either registered trademarks or trademarks of TechShop Inc in the United States and/or
other countries. Microsoft and Windows logo are either registered trademarks or trademarks of Microsoft Corporation in the
United States and/or other countries. Apple, Mac and Macintosh are either registered trademarks or trademarks of Apple
Computer, Inc. in the United States and/or other countries. SnagIt is either registered trademarks or trademarks of TechSmith
Corporation in the United States and/or other countries. All other registered trademarks or trademarks are the property of the
respective owners.
These class materials are intended for use in an instructional setting. Successful completion of SBUs are REQUIRED for many
of the products at TechShop, an instructor must sign off on this requirement. It is NOT enough to just read and follow these
materials.
Except for the cover page, the content of this manual is under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0
License. Under this license, you are permitted to copy, distribute, and transmit this work. You are also free to adapt this work
for your usage. To comply with this license you must also provide attribution for the author, you may not use this work for
commercial purposes, and if you alter or share this work then you must distribute this license with the resulting work. For more
information about this license and the full legal code version text, please see this website:
http://creativecommons.org/licenses/by-nc-sa/3.0/
Colophon
These materials were created electronically using Microsoft Word. These materials were originally written by Marshall
Massengill. To view the original version of this material online, please visit Marshalls website here:
http://forum.nc2600.org/~nickfury/arduino_class/
Ron Craig has added a lot of material since the initial version. There is a web page tracking additional resources for the class.
The website is available at http://wiki.techshoprdu.com/index.php?title=Introduction_to_Microcontrollers_with_Arduino
The second thing to notice about the Arduino is all of the pin headers. On the top of the
board there are Digital I/O pins. Digital I/O might seem like something fancy but it just
means that the signals sent and received on those pins must be in the form of 1s or 0s, either
+5 or 0 volts for the Arduino to understand them. Youll also notice that some of the Digital
pins have a PWM label underneath them. PWM will be explained a little later but the basic
idea is that for those specific pins, the Arduino can output a different kind of digital signal
that some special devices can understand and take advantage of. There is also a ground
connection and some serial communication ports on the top headers.
On the bottom headers you will find a couple of power output pins for +5v and +3.3v
power, along with a couple of ground pins. You can also find the Analog pins on the
bottom headers. The analog pins will be used for input to the Arduino from analog devices
like sensors and potentiometers. How they work will be explained a little later.
If you are curious about the specifications for the actual microcontroller then they arent
anything to write home about but they are more than enough for most small projects. The
heart of the Arduino is the little PDIP chip that sits in the middle of the board. It is an
ATmega328. The 328 provides 32KB of flash memory, 2KB of SRAM, and 1024 bytes of
EEPROM. The Arduino operates at a blazing fast 16MHz and it is an 8 bit processor. The
ATmega chips are based around a modified Harvard RISC architecture.
The data sheet for the microcontroller is available online at
http://www.atmel.com/dyn/resources/prod_documents/8271S.pdf
The previous version is the Duemilanove (Italian for 2009). The boards are identical except
for the support chip used to communicate over the USB port.
Now that youre almost asleep, its time to wake up and start programming.
3
Arduino.
9. The tab for the sketch. Multiple tabs for multiple files in a single sketch are possible.
10. The actual coding area of the sketch. This is where you will write your code.
11. Another important piece of the IDE is located at the bottom of the screenthe debug
window. The debug window will provide you with the error messages from
compiling your code.
12. This identifies the board, the chip, and the serial port you have configured.
void setup()
{
}
void loop()
{
}
The setup function above is called exactly once, and then loop is called over and over, doing
nothing.
We will now create our first Arduino program. To begin, open the Arduino program on the
computer. This will bring up a window and a new blank project. This new blank project
doesn't contain anything so we're going to have to add some code to it.
digitalWrite(blinkyPin, LOW);
delay(1000);
The first bit of code to add is your name and some information about the project.
Programmers call this kind of thing a "comment" and it can come in two varieties. The first
is a multi-line comment and it begins with "/*" and ends with "*/". Anything between the
marks is ignored by the compiler and it is purely for human reference. The next type of
comment is a single-line comment and it is the characters "//" followed by the comment.
/* Arduino Hello World Program
Written by Johnny Appleseed
August 12th, 1859
*/
Sometimes, multi-line comments will have asterisk characters before each line in the
comment. This is more for style than anything functional. Technically, comments are not
functional at all but they help to make code readable and understandable. Without them,
coding would be a whole lot harder.
The next part of the program that needs to be written is a variable assignment. This part of
the program isn't strictly necessary but it will make the code more readable and it will
provide some practice. The code is as follows:
int blinkyPin = 13;
That might seem complicated but it isn't. The first word is "int" and it is shorthand for
"integer" and it serves to tell the compiler what kind of variable it needs to reserve space for.
There are other types of variables but they aren't terribly important to us at the moment. The
next word is "blinkyPin" and it is the name of the variable. From this point on, anytime we
want to refer to our variable then we will call it by its name. The third bit is an assignment
operator, the equals sign. Next is the integer value that we are assigning to the variable
"blinkyPin", in this case the value is 13. The last character is a semicolon and it serves to tell
the compiler that the line has ended.
At this point, if you are confused then it might help to avoid thinking of the equals sign as an
equals sign but rather as the word "gets." If you do so then the above can be read as "integer
variable blinkyPin gets thirteen."
Now, because the Arduino is a microcontroller, every sketch you write has two primary
functions. The first is the setup function and it is run exactly once after a reset and when
the board is first powered on. This function typically contains one-time events that serve to
"setup" the Arduino for the remainder of its execution. The setup function is the next
thing that we will program. We will program it using the following code:
void setup()
{
pinMode(blinkyPin, OUTPUT);
}
The first part of the setup function is marked void to set the return type for the function.
In this case, the setup function does not return anything so it is void. In other cases, a
function might return an integer or something else. The next part is the name of the function,
in this case that is setup as this is the setup function. If you were writing your own
function then it can be named almost anything you want to name it. The next part is a set of
parenthesis. If the function requires any arguments, they would be listed here. Because the
setup function does not require any arguments, the parentheses are empty. Next is a set of
curly braces. They serve as the bookends for the function and tell the compiler where the
function begins and ends. Anything inside of the curly braces is inside of the function and
will be executed exactly once when the Arduino is turned on.
8
Inside of the setup function we add the line that will configure the pin for our LED to
blink. The main point of this line is to call a function called pinMode and pass it two
arguments that will configure the pin that is connected to the LED we wish to blink. The first
argument is the variable that we created initiallyit names the pin. The second argument,
which is preceded by a comma to separate the two arguments, indicates whether we will set
the pins value or read from the pin. This variable is called OUTPUT and is a special type of
global variable that the Arduino provides. It will serve to set the pin for output so we can
blink the LED.
void loop()
{
digitalWrite(blinkyPin, HIGH); // sends +5V to pin
delay(1000);
digitalWrite(blinkyPin, LOW);
delay(1000);
The second function is a loop function that will repeat over and over again and again until
the Arduino loses power, or is reset. It returns nothing so its return type is also void and it
takes no arguments so the parentheses dont contain anything.
This code might look complex but it is very simple. The first line is calling the
digitalWrite function with two arguments. The first argument is the variable
blinkyPin (which we set to 13 earlier). The second argument is a constant in the Arduino
language called HIGH. A constant is basically a variable that is immutable, or in other
words, it is a variable that cannot be changed. In reality HIGH is just the integer 1 and we
could even rewrite the line and replace HIGH with 1 to accomplish the same thing but doing
so would make the code harder to read and understand. As it is, the line can be read as "set
the digital blinkyPin to HIGH output". Lastly, there is a single line comment on this line.
This comment serves to tell you exactly what the line is doing. Setting a digital pin to HIGH
sends +5 volts to the pin. LOW sets the pin to ground (0 volts).
The next line is calling the delay function with only one argument. That argument is an
integer value in milliseconds. In this case, the delay function is being called for one
thousand milliseconds, or one second. The delay function does exactly what you probably
think it doesit delays the code execution for a specified amount of time. This line also has
a single line comment.
The third line is very similar to the first. In fact, the only difference is that the third line is
using the constant LOW instead of the constant HIGH. The constant LOW is the integer
value 0 and if you felt inclined, you could replace LOW with 0 and the line would work just
the same. Again, the reason to use the constants is that it makes the code easier to read and
understand. Lastly, this line is also followed by a single line comment explaining what the
line is doing.
The fourth and final line is exactly the same as the second line.
9
Once you have all of these lines then you can save your code and then compile and upload it
to the Arduino board. The onboard LED should begin to blink on for one second and then off
for one second in a continuous and never-ending loop.
Something that you could try at this point is connecting the positive lead of an external LED
to digital pin 13, which is conveniently located right next to the ground pin. The negative
lead of the LED must also be connected to the ground pin. This external LED will then begin
to blink in the same manner as the onboard LED. Dont try this with pins other than 13
there is a special current-limiting resistor connected only to pin 13 that prevents your external
LED from being burned out.
To practice connecting up an LED properly, change the pin to pin 11 and connect one of your
LEDs to pin 11 using the half-size breadboard supplied with your student kit. Dont forget
the current-limiting resistor!
That concludes the first project of this class.
11
How do we use this to sense the world? If you set a pin to INPUT with
pinMode(pinNumber, INPUT), you can then make a call to determine if that pin
has a logical one (+5V) or zero (0V) value attached. If the voltage on the pin is 3 volts or
higher, the digitalRead function returns a 1. If the voltage is 2 volts or lower, the
function returns a 0. If the value is in the middle, youve wired something wrong or have
a poorly-designed circuit.
There is a function to read varying voltage values, but thats an
analogRead(pinNumber), which well use later with analog sensors.
Pull-up Resistors
12
So, what value will you get if the pin is not connected to anything? The answer is that
the value you get will be unreliable. If you intend to read a value (analog or digital) from
a pin, you really need to ensure that the pin is always connected to something.
You might think that the following would work, but they dont. Can you guess why?
In the left drawing, when the button is released, the pin is left floatingit is not
connected to ground nor is it connected to power. A digitalRead(4) might return
zero or one, depending on sunspots or your hand waving near the chip or just poor luck.
One thought might be to connect the other side of the switch to ground (right drawing).
This would be a Very Bad Idea because if the button were to be pressed, you would have
connected Vcc (your voltage source) to ground (GND), creating a short circuit. This
would certainly make the circuit stop working, possibly burn up the wires, and maybe
start a fire!
The solution to this problem is to drive the pin high in such a way that when the button is
released the value will be reliably high, but when the button is pressed, the value goes
low. This is done with what is called a pull-up resistor. A pull-up resistor is a largevalue resistor through which a HIGH voltage value (+5V for Arduino) is supplied to a
pin. The digital sensor is connected in a way that activating it will then drive the pin to a
low value. When the button is pushed 5 Volts will flow through the button to ground
voltage. Because the resistor limits the amount of current that can flow to ground, you
avoid a short circuit and setting things on fire. That scheme looks like this:
When the button is released, the pin will see the +5V that is connected through the pullup resistor. When the button is pressed, the +5V will flow to ground, and the pin will be
13
connected to ground, so the pin value will go to ground voltage as long as the button is
pressed.
This type of setup is used so very frequently that the designers of the ATMega chip
designed a 20K-Ohm pull-up resistor into every digital IO pin. You dont have to build
this circuit, you only need to use a special pinMode value to enable it.
pinMode(4, INPUT_PULLUP);
Once this call is made, the value read will be HIGH unless it is driven low by whatever is
connected to the pin. To disable the pull-up while running, you can make a call to
digitalWrite(4, LOW).
We can combine this new knowledge about digitalRead() and pull-up resistors to create a
program and circuit that can use a push button to light the LED weve already wired up.
14
void setup()
{
pinMode(blinkyPin, OUTPUT); // digital output hooked to LED
// digital input from button is active when LOW because we will
pinMode(buttonPin, INPUT_PULLUP); // enable the pull-up resistor!!
}
void loop()
{
if ( digitalRead(buttonPin) == LOW )
// button pushed
{
digitalWrite(blinkyPin, HIGH);
// LED on
}
else
{
digitalWrite(blinkyPin, LOW);
// LED off
}
}
The sketch starts with a multiline comment with your name and the purpose of the sketch.
const int buttonPin = 2;
const int blinkyPin = 11;
These lines define our pins. They wont change, so we tell the compiler to keep us
honest by making them constants with the keyword const. If we write any code that
tries to change their value, the compiler will mark that code as an error for us.
15
void setup()
{
pinMode(blinkyPin, OUTPUT); // digital output hooked to LED
pinMode(buttonPin, INPUT_PULLUP); // digital input from button (active low)
}
When we set up the pins in our setup function, we need to remember to enable the
pull-up resistor so the value will stay high whenever the button is not pressed.
void loop()
{
if ( digitalRead(buttonPin) == LOW )
// button pushed
{
digitalWrite(blinkyPin, HIGH);
// LED on
}
else
{
digitalWrite(blinkyPin, LOW);
// LED off
}
}
We want our programs loop to read the value of the digital input pin (the button), and
based on the value, switch the LED on or off. The code above turns the LED on while
the button is pressed, and off when the button is released.
Notice that now we need ground and +5V for more things, so we are connecting the
breadboards power and ground rails to the Arduino, then the components to the rails.
16
Figure shows GND and 5V connected to make power rails on breadboard. The
pushbutton switch is connected to digital pin 2 and the ground rail. The LED is
connected as before to digital pin 11.
17
18
19
}
for(value = 255; value >=0; value=value-5) // fade out (from max to min)
{
analogWrite(fadingPin, value);
delay(30);
}
}
The code for this project is very similar to the code from the first project. You could reuse some of the code from the first project but the tutorial is written so that you are
starting from a new file. So, start a new file! Just as before, make a multiline comment at
the beginning of the file describing the program and giving your name.
int value = 0;
int fadingPin = 11;
Here we create a few variables to use later. The first variable (we'll call it "value") is a
spot where we will store our temporary values for this program. Assign a value of 0 to it
for the time being. Also, create a variable called fadingPin and assign it the value of
20
11. This will allow you to connect the positive lead of the fading LED to the digital pin 11
of the Arduino board, and the negative lead to ground.
void setup()
{
pinMode(fadingPin, OUTPUT); // optional for analogWrite, but good practice
}
Technically, you don't need to put anything inside of the setup() function but for the
sake of completeness and proper coding you should add a line for making pin 11 an output
pin.
for(value = 0 ; value <= 255; value=value+5) // fade in (from min to max)
{
analogWrite(fadingPin, value);
delay(30);
}
The first lines to add to the loop function are the ones that will make the LED fade on.
The first line of the above code is a for-loop. For-loops will execute the code within
them until the specified condition is no longer true. That might sound complicated but it
isn't. For-loops have three parameters, the first parameter is an initialization value, the
second is a conditional statement that must be true for the loop to execute, and the third
parameter is incrementing (or decrementing) the variable so that the for -loop doesn't get
stuck in a never-ending loop. Notice that the separators between the parameters are
semicolons, not colons.
The for -loop above, then, causes value to take on the value of 0, then 5, then 10, and
so on up to 255.
Inside the for -loop are two more function calls. The first one is the analogWrite
function and it needs two parameters. The first is the pin that it is controlling and the
second is the value, between 0 and 255, that is assigned to set the duty cycle. The other
function is a delay function and it has already been discussed. Now, that takes care of
fading the LED on.
21
Next we need to fade the LED back off by adding another for-loop after the one we just
created:
for(value = 255; value >=0; value=value-5) // fade out (from max to min)
{
analogWrite(fadingPin, value);
delay(30);
}
The second for-loop is nearly the same as the previous one but instead of incrementing
the last parameter, we are decrementing it. The functions inside of the loop are identical to
the previous one because we are applying the same values. That's it. Upload the code to
your Arduino board and run it. Make sure you have the LED connected correctly. You
should be rewarded with an LED that slowly fades on and off.
For a bonus, comment out the delay(30) in the first loop. What happens? Why?
22
23
24
void setup()
{
pinMode(fadingPin, OUTPUT); // declare the LEDs pin as an OUTPUT
Serial.begin(9600); // start up the serial port at 9600 baud (bits per second)
}
Inside of the setup() function we do two things. The first is to set the mode for the
PWM output pin. The second thing we need to do is initialize the serial communication
protocol. We will be using the serial communication of the Arduino to get useful feedback
information from the Arduino about the state of our analog values. The
Serial.begin() function takes one parameter, in our case that parameter will be the
integer value, 9600, which is significant because it is the speed that the Arduino will
communicate at over the serial connection. Depending on your perspective, 9600 might
seem big or it might seem small, but the Arduino will happily convey the information we
are looking for at that speed.
value = analogRead(potentiometerPin);
value = value >> 2;
Serial.println(value);
Inside the loop() function the first thing we are doing is to read in the value of the
potentiometer. We store that value in the "value" variable we created earlier.
Now, remember how the analog inputs on the Arduino offer 10 bits of precision? Well, we
need to alter our stored value a little to make it fit within the 8 bits we are allowed to
provide to our PWM output. To do this we use what computer science types would call a
"bitwise operation." In this case, we shift each bit two positions to the right with the
following line of code:
value = value >> 2; // 1111111111 (1023) becomes 0011111111 (255)
Basicially, what we just did was chop off the last two figures of our binary value. In other
words, we removed two bits of precision thereby giving us the magical 8-bit number that
we needed for our PWM output to understand.
Theres another way to do this, of course (isnt there always another way?) The Arduino
libraries provide a function called map which returns a value mapped into another
range. The call would be
value = map(value, 0, 1023, 0, 255); // map a value from the range 0-1023 into 0-255
Next, we are going to use our serial connection to send this value back to the computer so
we can actually see it changing on the screen. To do this, we will use the
Serial.println() function that can take a couple of different parameters. In our
particular instance, we are only concerned with giving it our "value" variable as a
parameter. There are several other functions to write information over the serial
connection including Serial.write(), and Serial.print(). We are not
interested in those functions right now, though, but you should be aware of them.
25
analogWrite(fadingPin, value);
delay(10);
Next, we are going to use the analogWrite() function to output a value to our PWM
output pin and the delay() function to slow things down just a little.
Before we upload this code to the Arduino, we need to build the circuit. The circuit you
already have for controlling the LED can be left in place as it is. Instead of controlling the
brightness with hard-coded values in a loop, were simply adding another circuit to get the
desired brightness, and your program will serve to link the two circuits together!
Find the potentiometer (also called a pot or variable resistor) and put that into your
breadboard so that each of the 3 leads is on its own row of the board. You'll want to
connect the potentiometer with the two outer legs connected separately to +5 volts and
ground. The wiper (the middle pin) of the potentiometer is connected to the analog input
pin we specified previously, Pin A2.
That's it. Save it and upload it to your Arduino. Once you have it uploaded to the Arduino
you will be able to open the Serial monitor and see the values of the potentiometer scroll
by and change as you adjust the potentiometer.
Switch the +5 and ground going to the potentiometer. What happens? Why?
For a bonus, try connecting a photoresistor or thermistor between +5V and pin A2 in
place of the potentiometer. How does that work? What values do you see? If you
disconnect pin A2 totally, what values do you see as you wave your hand over the board?
How does the LED react?
That completes this project.
Schematic of tutorial
showing a potentiometer
connected to pin A2 and
an LED connected to pin
11.
26
27
Processing program on the computer. The "byte" type is just an 8 bit number (from 0 to
255). You can assign it the value of 0 for now.
void setup()
{
Serial.begin(9600);
pinMode(fadingPin, OUTPUT);
}
Inside of the setup() function we initialize the serial communication and set the pin
mode of the PWM output pin to be output:
if (Serial.available())
{
}
Next, we move on to the loop() function. Inside of it, we need to create an ifstatement. An if-statement works similarly to a for-loop but instead of executing its
contents for a certain number of iterations, it executes its contents if (and only if) a
specified condition is met. Our if-statement will execute only if data is available on the
serial port.
The if-statement will execute if the value inside of the parenthesis is true. In our code
above, we are taking advantage of something that the Arduino (and most other)
programming language doesit evaluates any non-zero integer value to be true. So it
doesn't matter what the Serial.available() function actually returns because we don't care
as long as the value isn't zero. Luckily for us, the Serial.available() function returns the
number of bytes ready to be read, and that is zero only if the serial connection has no data
available. Pretty neat, huh?
value = Serial.read();
analogWrite(fadingPin, value);
Next, we add some code inside of the if-statement. The code we add reads in the value
from the serial connection and then assigns that value as the duty cycle value of the PWM
signal.
The Serial.read() function is very similar to the Serial.write() function that we used
previously except, as you've probably guessed by now, it doesn't write values to the serial
connection, it reads them from it.
29
30
The first line is creating a new window that has a size of 256 pixels by 150 pixels. The
window will serve as our slider. The second line is defining the port object that we created
earlier and assigning it some basic properties. You will need to change the COM1
portion of this code to be the specific COM port that your Arduino is using. Leave
the 9600 alone, though, as it is the speed that we defined for our serial communication on
the Arduino previously.
Next, we need to add code to the draw() function in our Processing program. First, create
a for-loop that counts from 0 to 256 in increments of one:
for (int i = 0; i < 256; i++) {
}
Inside of the "for" loop, we should add the following to create a gradient and give us
something to look at within our window that we created earlier:
stroke(i);
line(i, 0, i, 150);
At this point, it might seem like we are rushing through this Processing stuff but don't
worry about that because this class is about the Arduino, not Processing. You can just
copy the code for now if you need to.
Lastly, outside of the for-loop but still within the draw() function we will add the
following line to get the location of the mouse from our window and output that
information to the serial port:
port.write(mouseX);
Now, at this point we should verify and then run both the Processing sketch and the
Arduino sketch that we created. If all is working as it should, then as we move the mouse
back and forth across the gradient that our Processing program is running we should see
the LED on the Arduino fade on and off. If you made it this far then give yourself a pat on
the back because you now know that Microcontrollers are no where near as scary as you
might have thought they were.
31
Processing Code:
/* Serial Controlled Fading LED using Processing
Written by Emmanuel Goldstein
Janurary 1st, 1984
*/
import processing.serial.*;
Serial port;
void setup() {
size(256, 150);
port = new Serial(this, "COM1", 9600); // must match your machines COMx
}
void draw() {
for (int i = 0; i < 256; i++) {
stroke(i);
line(i, 0, i, 150);
}
port.write(mouseX);
}
32
Debouncing a button
We asserted in an early lesson that proper detection of simply pressing a button could
actually be harder than it might at first appear. If you type in the following program Ill
prove it.
const int buttonPin = 2;
const int LEDPin = 13;
void setup()
{
pinMode(LEDPin, OUTPUT);
// LED pin is for output
pinMode(buttonPin, INPUT ); // digital input from button
digitalWrite(buttonPin, HIGH); // enable pullup so no press reads a 1
Serial.begin(9600);
// for the serial monitor output
}
int buttonState = HIGH;
int prevState = HIGH;
boolean ledState = true;
int buttonPress = 0;
int dumped = 0;
//
//
//
//
//
void loop()
{
buttonState = digitalRead(buttonPin);
33
{
}
}
void dumpStats() // this function displays the number of button presses
{
Serial.print("Button Presses = ");
Serial.println(buttonPress, DEC);
}
If you run the program and view the serial monitor, it starts blank. Press the button 10
times. Is the code seeing button presses that match your presses? If you press the button
10 times, does it report 10 button presses or more?
Now, remove the leading slashes on the lines that do the debouncing and run the sketch
again. Does it work now? Why?
The loop() function is called very very rapidly. If the button bounces, the program will
interpret each bounce as a button press then a button release, then another press, another
release. Each press and each release is another button state change, and youll often see
several with a single physical button press. The simple way to work around this is to give
the button some time to settle down. The new lines are triggered on a potential button
press. They give the button some time to settle down (50 milliseconds in this case) and
then check the button again to see if it still thinks the button is in the new state.
34
Project Ideas:
0 - Interfacing LCDs - http://www.arduino.cc/playground/Code/LCD
2 - Arduino Projects @ MAKE - http://blog.makezine.com/archive/arduino/
4 - Ardunio @ Instructables - http://www.instructables.com/id/Arduino/
35
36