0% found this document useful (0 votes)
69 views

Arduino SBS Draft Notes May 2015

The document provides an overview of the Arduino ecosystem and prototyping process. It describes the main components of the Arduino ecosystem including the Arduino board, IDE, core software library, third party libraries, shields, and individual components. It then explains that prototyping is an iterative process of building a prototype, testing it, refining it based on results, and repeating until the desired product is achieved. Finally, it outlines the basic tools needed for Arduino prototyping including a multimeter, breadboards, jump wires, and optional power supply.

Uploaded by

Nguyen Tri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views

Arduino SBS Draft Notes May 2015

The document provides an overview of the Arduino ecosystem and prototyping process. It describes the main components of the Arduino ecosystem including the Arduino board, IDE, core software library, third party libraries, shields, and individual components. It then explains that prototyping is an iterative process of building a prototype, testing it, refining it based on results, and repeating until the desired product is achieved. Finally, it outlines the basic tools needed for Arduino prototyping including a multimeter, breadboards, jump wires, and optional power supply.

Uploaded by

Nguyen Tri
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 303

Sold to

[email protected]
Peter Dalmaris Lecture 2 Arduino Step by Step

Section 1 Lecture 2
The Arduino ecosystem
!
Before setting up the "hello world" demo app of the electronics world (the blinking LED),
let's have a really quick look at the Arduino ecosystem. The members of this ecosystem are
the bits and pieces that come together when you build an Arduino project.

The Arduino ecosystem is made up of these parts:

1. The Arduino board

2. The Arduino IDE

3. The Arduino core software library ("Arduino language")

4. Third party software libraries

5. Shields

6. Components

The Arduino board


In the beginning, way back in 2005, there was only one board. Rumour has it that it was
called the "Arduino" in honour of the place where the idea for an open-source hardware
prototyping platform was conceived. Today there are numerous boards, with a wide range
of capabilities. Processing, input/output, power consumption, size, and price are various
metrics in which modern Arduino boards differ from each other.

The very popular Arduino Uno Rev 3


!Arduino-official boards are made by companies that work in collaboration with the Arduino
team to ensure compatibility. They are the only ones licensed to use the name "Arduino". In
return, makers of official Arduino boards pay a fee to the Arduino project. There are also

1
Peter Dalmaris Lecture 2 Arduino Step by Step

The very small Arduino Micro


!
many clones, derivatives and counterfeit boards that while using the open-sourced Arduino
software and schematics do not contribute to the project financially. They also are not
providing any guarantee of compatibility and quality. I recommend you only purchase an
official Arduino board for both peace of mind and for the nice feeling of contribution to the
project.

The Arduino IDE


The Arduino IDE, or Integrated Development Environment, is the tool you use to create an
Arduino program and upload it to your board. An Arduino program is called a sketch, a
reminder that what you are actually doing is prototyping, which in turn means that anything
you do is subject to trial, testing, and change.

Here is an example of the Arduino IDE.

2
Peter Dalmaris Lecture 2 Arduino Step by Step

The Arduino IDE can be downloaded from the Arduino website and it works on Mac, Linux
and Windows computers. Its only requirement is the Java Runtime Environment (JRE).
Simply download the IDE installer for your computer, and run it. The installer will let you
know if you need to download the JRE. Get it from http://arduino.cc/en/Main/Software.

With the IDE installed, you will be able to type, upload to the board, and debug (ie. fix) your
sketches. You also use the IDE to communicate both ways with the board: to upload your
sketches to the Arduino, and to receive messages from the Arduino.

The Arduino language


When you download the Arduino IDE, you also get the Arduino core library. This library is a
collection of functions or methods that allow you to control the various aspects of your
board's functionality. For example, if you want to read an analogue value from pin 1, you
call the relevant method like this:

analogRead(1);
!
Awesomely simple! If you want to turn an LED light on, that requires "writing" a digital value
1 to a digital pin. Connect the LED through a resistor to digital pin 13 and use this method:

digitalWrite(13, HIGH);
!
Apart from methods like these, meant to interact with the environment, the Arduino core
library gives you many others. There are control structures, arithmetic operators,
mathematics functions and many others. All of them are listed and documented in the
references page of the Arduino project's web site.

I will be explaining the use of many of these methods as we use them throughout this
course.

Third party software libraries


Lot's of people have contributed to the Arduino ecosystem by writing their own libraries
and making them available to others. These third-party libraries often address gaps in
functionality that the Core library perhaps does not offer, or it does not offer well. In other
cases, these libraries offer alternative ways of doing things.

For example, this library allows you to add infra-red remote control capability to your
project. This one implements a web server that can run on your board, which is very useful
for remote sensing or remote control applications.

Shields
Very often, certain hardware components are used so widely that eventually a company
assembles them together on a printed circuit board so that it is easy to plug into an Arduino
board without any wires. These extension boards are known as "shields".

3
Peter Dalmaris Lecture 2 Arduino Step by Step

The Ethernet shield is very common. It makes it very easy to add Ethernet and Internet
communications to your project. You could just buy the WizNet controller, connector and
other parts and create your own Ethernet adaptor, but it would be silly to do that.
Remember that our mission is to build prototypes so that we can implement our ideas, not
to fiddle around with problems already solved well by others!

Another popular shield is the Arduino Motor Shield through which you can control all sorts
of motors, very useful if you want to build a robot, a racing car, or a remote control lawn
mower.

In section 4 we will be playing with the Ethernet shield.

Components
Finally, there are the individual components. These are typically small devices that you plug
into your board by using jumper cables and breadboards.

For example, if you want to take temperature and humidity readings, you could use the
DHT11 sensor.

If you need to measure distance, then you could use an ultrasonic distance sensor.

In sections 2 and 3 of this course we will be experimenting with many useful components.

Conclusion
Ok, that concludes a brief dive into the Arduino ecosystem. Please take a few minutes to
answer a few quiz questions before continuing with Lecture 3 where we examine the
Arduino tools and the prototyping process.

4
Peter Dalmaris Lecture 3 Arduino Step by Step

Section 1 Lecture 3
Tools and the prototyping process
!
In this lecture I will show you the tools and process involved in prototyping with the
Arduino.

There is nothing Arduino-specific about either these tools or process. The Arduino is an
incredibly effective creative tool because it accelerates prototyping dramatically.

The prototyping process


Prototyping is an iterative process whereby each iteration's objective is the refinement of a
prototype.

It looks like this:

!
It all begins with an idea, a problem or a thing that you would like to build. Usually you will
have some prior knowledge of the problem area, or some informed assumptions that can
help you get started. But at the very beginning, you will not have the details or at least
some of the knowledge necessary to help you in actually building whatever you are trying to
build.

So, you go ahead and use what you know to build a prototype, version 1. This prototype
may barely work at all, but it should be doing something that you can test and learn from.
Testing yields information that you can use to adjust your original assumptions. This
adjustment is called refinement.

1
Peter Dalmaris Lecture 3 Arduino Step by Step

Iteration after iteration will yield more and more information and result to more and more
refinements until at some point your prototype, be it version 100 or version 1000, is the
product or solution you aimed for.

Of course, the Arduino is not necessary in the prototyping process. You could do
prototyping using bare-bones electronic components down to the transistor. However with
the Arduino, you can prototype much faster because (1) you will be using general purpose
and already tested components which allow you to focus on your actual objective and (2)
you will be using high-level tools to do so.

Tools
Yet another really nice thing about prototyping with the Arduino is that you only need few
and very basic tools.

Not including the board itself, shields and other components mentioned in Lecture 2, you
can build great projects with just these items:

1. Multimeter (not strictly needed)

2. Solderless Breadboards

3. Jump wires

4. Power supply (not strictly needed)

A multimeter
A multimeter is not required for the majority of the projects you will be building as a
beginner. However having one and getting to know how to use it will help you a lot later on.

Multimeters vary in capabilities and prices, but for


$20 or $30 you can get a really nice digital one that
will show you things like:

1. Voltage AC and DC

2. Resistance

3. Continuity between two parts of a circuit

With these basic capabilities, you will be able to


check that there is voltage differential between two
pins, or that a battery is charged, check the
resistance of a resistor, and confirm that two parts of
a circuit are electrically connected.

This is what a typical digital multimeter looks like.

!
2
Peter Dalmaris Lecture 3 Arduino Step by Step

Solderless Breaboards
A solderless breadboard is a convenient way
to connect components together without a
need to use solder and a soldering iron.

With a breadboard, you will just connect your


components into electrically connected
sockets. When you are done, you can clear the
breadboard and use it for another project.

In a breadboard you get a couple of rows


containing sockets that carry ground and
positive voltages along one or both sides of
the board, and multiple columns containing
sockets that are electrically connected.

Here's a medium-sized breadboard.

If you could x-ray a breadboard, you would


see something like this:

An "x-ray" photo of a breadboard

You can see here how sockets are electrically


connected vertically or horizontally.

And here is a picture of a simple Arduino


project where an LED that is connected to the
Arduino pin 9 (digital out) and ground via a
resistor. Instead of making the connections
directly into the Arduino connectors, which
would result in a messy bungle of wires, I
plugged the LED, resistor and jumper cables
into a mini-breadboard. Much cleaner setup!

!
!
Jumper wires
A jumper wire is a thin cable with pins at either end. Use them to
make connections on a breadboard and on the Arduino headers.
They come in many colours and lengths. One thing to remember:
you don't want to run out of jumper cables during your
prototyping so make sure you have plenty available!

My only "rules" when it comes to jumper cables are these:

3
Peter Dalmaris Lecture 3 Arduino Step by Step

1. Use red for positive voltages

2. Use black for ground

Any other colours can be used to signify the connection of different kind of components or
functions that each one serves. For example, you could use light coloured wires for sensors
and dark for buttons or displays. Up to you.

Power supply
The Arduino can provide power for itself and for the circuit you are building from the USB
cable that is used to connect it to your computer.

However, there are three obvious cases where you will need an external power supply:

1. If you want your sketch and gadget to continue its operation after your computer is
turned off.

2. If your circuit becomes large enough so that the Arduino can't provide enough
power

3. If your computer's USB port can't provide enough power.

Here are three things you can do to deal with such situations:

An external power supply

This provides DC power from an electrical outlet. Anything


rated at 9V to 12V and 250mA or more will work with the
Arduino. Just make sure it outputs DC power, not AC! I got
mine from an old cordless phone.

A breadboard power supply

Very useful if you want to drive devices that need more


power than what the Arduino can provide, such as a motor.
I have one of these which uses the same kind of power
brick as the Arduino and provides both 5V and 3.3V of
selectable output.

A battery pack

If you want to go off-grid, then you need battery power.


You can buy plastic battery cases specifically designed for
the Arduino on ebay, or just find an old broken battery
operated toy and recycle its battery pack. Here's one that
I use. You just need this pack to produce voltage that falls
within the Arduino's operating range.

!
4
Peter Dalmaris Lecture 3 Arduino Step by Step

Ok, with all the logistics out of the way, time to get into our first project: let's go to Lecture 4
and make an LED blink!

5
Peter Dalmaris Lecture 4 Arduino Step by Step

Section 1 Lecture 4
The blinking LED
!
The basics
A Light Emitting Diode is a special kind of a
diode in that it can emit light. Although all
diodes do emit light, in most cases this light is
not bright enough so we can't see it. LEDs
are specially constructed to allow the light
produced to escape outwards so we can see
it instead of just being absorbed by the
semiconductor.

A diode is a polarised device. In a polarised


device, there is a correct way and an incorrect
way of connecting it to your circuit.
Connecting a polarised device to your circuit
incorrectly will, at least, result in your device not working. In some cases the device can
burn out.

This is what an LED device looks like. Notice that there is a short and a long "leg". The
short leg is called "the cathode", often noted with a "k" and should be connected to
the negative ("-") voltage. The longer leg is called "the anode", often noted with an "a"
and should be connected to the positive ("+") voltage. Other devices of note that are
polarised and use similar or same terminology are transistors and certain types of
capacitors.

Symbolically, i.e. in diagrams depicting electronic circuits, an LED is depicted like this:

!
The basic characteristic of a diode is that it is a semiconducting device that allows the flow
of electricity (electrons) only towards one direction. Think of it as the equivalent of a
plumbing valve that allows water to flow only in one direction. Therefore, diodes are used in
situations where we want to restrict the directionality of electricity. Diodes are used

1
Peter Dalmaris Lecture 4 Arduino Step by Step

extensively in applications like the conversion of current from alternating to direct, in radio
transmitters for the modulation of signals, and many others.

The symbol of a diode is almost the same as the one for an LED. The only difference is the
presence of three little arrows which show that light is emitted from an LED:

!
Let's experiment with an LED
With the background and theory behind us, lets implement our first Arduino circuit. The aim
is to become familiar with plugging components into the breadboard, uploading and
running a sketch.

In our first sketch we will simply make an LED


blink on and off.

Here's a diagram of the circuit you need to


build now.

Use a red jumper cable to connect the Arduino


digital socket 9 to any socket in an empty
column on the breadboard. Let's name this
column "1". Take a 220 Ohm resistor (or close),
and connect one pin in one of the sockets of
column "2" in the breadboard (which is the first
column on the left of column 1), and the other
in a socket in an empty column (make this
column "3").

Connecting a resistor in series with an LED is


important. Because the LED does not offer
much resistance to electricity, connecting an
LED directly to power will cause a high current
to flow through it and quickly burn it. This
situation is described mathematically by Ohm's
Law, which states that R=V/I, where R is the
resistance of a device, V is the voltage at its
two connectors, and I the current that flows through it. If you solve this equation for I, you

2
Peter Dalmaris Lecture 4 Arduino Step by Step

get that I=V/R. For an LED, R is almost zero, so no matter what the V is, the I will be a very
large number.

Now here is the tricky part that has to


do with connecting the LED in
accordance with its polarity: Take an
LED, find the long leg and plug it into an
empty socket in column "1". This
socket conveys the positive ("+")
voltage. Plug the other leg into an
empty socket in column 2. An easy
mnemonic rule to help you remember
the polarity of the LED pins is that the
long leg must be connected to a higher
voltage.

Finally, use a black jumper wire to


connect the Arduino's ground (GND)
socket to an empty socket in column 3.

To finish up with the wiring, plug the


Arduino USB cable into an available
USB port in your computer. What you
should have now is something like this:

!
Sketch
The LED isn't doing anything at the moment. To get it to light up and blink, we need to
upload a sketch to the Arduino with the appropriate instructions.

Here's the program we'll use. I'll explain how it works. You can either type it into a new
Arduino IDE editor window, or load it by selecting File > Examples > 01. Basics > Blink from
the Arduino IDE menu. If you do this, remember to change the number "13" to "9" for
variable "led". I also made it available as a text file download from the materials tab.

!
!
!
!
!
!
!
!
!
!
3
Peter Dalmaris Lecture 4 Arduino Step by Step

!
// give a name to the pin to which the LED is connected:
int led = 9;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off
delay(1000); // wait for a second
}

!
Because this is your first ever Arduino program, I will explain a few things before continuing:

Comments

Any text following "//" or in-between "/*" and "*/" is a comment, and the Arduino will ignore
it. People use these symbols to type comments, like in this example.

Functions

An Arduino program can be broken down in parts by using functions. Functions make it
easy to create little programs within a large program, and to call each of these little
programs by name. In this example, we used 2 functions with names setup() and loop().
These are special functions that the Arduino will call itself. When the Arduino starts, it will
first call the setup() method and execute any commands it finds inside. Then, it will call
loop() again and again until you turn off the power, every time executing whatever
commands it finds inside. You can create your own functions and name them whatever you
like, as long as you don't use a reserved name (like "loop" or "setup"). Function names
can't have white spaces or other "special" characters inside them.

A function may or may not return a value when it finishes its execution. Notice that loop is
declared as void loop()? The void means that loop does not return anything when it
finishes its execution. Same thing happens with setup().

Local and global variables

If you want to store and retrieve values in your sketch, you need to use variables. Variables
can store numbers, text, booleans (true/false values) and other data types. In the very
beginning of this example, we have this statement:

4
Peter Dalmaris Lecture 4 Arduino Step by Step

int led = 9;

This creates a global variable named led, and stores the value 9 in it, which is of type int
(integer). A global variable is accessible from anywhere in your sketch. In this example, you
can see that inside the setup() function, there is a reference to "led", and similarly there is a
reference to "led" from inside the loop() function. On the other hand, a local variable is one
that is only accessible from within it's own context. If we had declared the led variable
inside the setup() function, then it would only be accessible by other statements inside the
setup() function and would not be accessible from the loop() function.

Arduino functions

Arduino's magic is in the functions that are build-in to the language. These functions make
it easy to control many aspects of our hardware.

Notice that in the setup() function, there is a call to the function pinMode. This function
takes in two parameters: first the number of the pin we want to configure, and second the
mode that we want to assign to this pin.

In our example, we have pinMode(led, OUTPUT);. Remember that we have a global


variable called led in which we stored the number "9". So we can re-write the pinMode
instruction as pinMode(9, OUTPUT);. This means that we configure pin 9, which is a
digital pin with possible states HIGH (5V) and LOW (GND) to be an output. Being an output,
this pin can be used to send a value to a connected device, in our case the LED.

With the setup() function complete, the Arduino then starts calling the loop() function. The
first thing that happens there is calling the digitalWrite function:

digitalWrite(led, HIGH);

With digitalWrite, we assign a new state to a pin. We can rewrite this statement as
digitalWrite(9, HIGH);, and, as you can probably guess, we are changing the state
of pin 9 to HIGH, which is 5V. As soon as this happens, your LED will light up!

We want to keep this LED lit for a little while, so we use the instruction delay to keep
things as they are. delay accepts one parameter, that is the number of milliseconds to wait
for. So in our case:

delay(1000);

means: "wait for 1000 milliseconds", which is 1 second.

Then we call digitalWrite again, but this time we change the state of pin 9 to LOW,
which is 0 Volts.

digitalWrite(9, LOW);

5
Peter Dalmaris Lecture 4 Arduino Step by Step

We wait at this state for another second, then the loop starts all over again.

So there you have it, your first Arduino circuit, and a blinking LED!

In the next Lecture, we will make the same LED, using the exact same circuit, fade on and
off, giving us a much nicer visual effect to look at. Before that, please complete the Lecture
4 quiz.

6
Peter Dalmaris Lecture 5 Arduino Step by Step

Section 1 Lecture 5
The fading LED
!
Tweaking the software
In Lecture 4, we created a simple circuit in
which an LED blinks on and off. The
Arduino sketch that drove the circuit
simply wrote a HIGH or LOW value to the
digital output pin 9, and the LED was turn
on or off accordingly.

What we want to do now, is to make the


LED not blink but fade on and off. We will
be keeping the exact same circuit, and
we'll only change the sketch to make this
happen.

Here's the new sketch (slightly modified


from the sample in the Arduino IDE which
you can load by going to File > Examples
> 01.Basics > Fade) (see next page):

!
!
!
!
!
!
!
!
!

1
Peter Dalmaris Lecture 5 Arduino Step by Step

int led = 9; // the pin that the LED is attached to


int brightness = 0; // the bigger this number, the brighter the LED is
int fadeAmount = 5; // the bigger this number, the faster the the LED will fade on or off

// the setup routine runs once when you press reset:


void setup() {
pinMode(led, OUTPUT); // declare pin 9 to be an output:
}
!
// the loop routine runs over and over again forever:
void loop() {
analogWrite(led, brightness); // set the brightness of pin 9:
// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;
// reverse the direction of the fading at the ends
// of the fade:
if (brightness == 0 || brightness == 255) {
fadeAmount = -fadeAmount ;
}
// wait for 10 milliseconds to see the dimming effect
delay(10);
}
!
The most important difference between this sketch and the one in Lecture 4, is that we now
use analogWrite instead of digitalWrite. While digitalWrite can only output a HIGH
or LOW value, analogWrite allows us to output any value from 0 to 255, or, to be more
precise, any of 256 voltage levels from 0V to 5V. The higher the voltage on the pin to which
the LED is connected, the brighter the LED will be lit.

In the loop() function, we first set the brightness of the LED, using the analogWrite
function, by selecting the pin to which the LED is connected, and the 'brightness'.
Brightness is a global variable of type integer that was initialised to be 0 when the program
starts. So, the first time that the program runs in the Arduino, this instruction will look like
this:

analogWrite(9, 0);

In the next instruction, after the comment, we calculate a new value for the brightness. The
new brightness is equal to the old brightness plus the fadeAmount, the value stored in
another global variable that we set to be 5 in the very start of the program. So, the first time
the program runs, this instruction will look like this:

brightness = 0 + 5;

Therefore, brightness will now become 5.

2
Peter Dalmaris Lecture 5 Arduino Step by Step

Next, we use a control structure to determine if we have reached a limit for the brightness,
either the lower limit (0) or the upper limit (255). If we have, then we switch the sign of the
fadeAmount variable. The effect is that if the LED was becoming brighter because the
fadeAmount was positive, then once it reaches it brightest setting (when brightness equals
255), then fadeAmount will be changed its negative (-5) and brightness will start moving
towards zero.

In the statement:

if (brightness == 0 || brightness == 255)

...the part within the parentheses is called a "condition". The "==" tests for equality. You
could test for "greater" with ">" or "less" with "<", as well as for a variety of other
conditions.

In the same statement, the "||" is the boolean operator "OR". You can join two conditions
together, and the result will be true if one of them is true. So, in our example, whatever is
between the curly brackets will be executed if either brightness is zero OR brightness is
255.

Section 1 complete
This concludes the lectures in Section 1 of our course! In Section 2 we will look into various
sensors that allow your Arduino project to take measurements from the world around it.

3
Peter Dalmaris Lecture 6 Arduino Step by Step

Lecture 6
About sensors
!
With the basics right behind us, we can now move on to the next set of lectures where you
get to learn about how to connect and use various kinds of sensors with your Arduino.

Sensors are the eyes and ears of machines: they provide environmental data. There are all
sorts of sensors, some more exotic than others. Here's a shortlist from Wikipedia:

• Light

• Motion

• Temperature

• Magnetic fields

• Gravity

• Humidity and moisture

• Vibration

• Pressure

• Electrical fields

• Sound

• Stretch and stress

Clever gadgets combine multiple sensors in order to capture a more complete snapshot of
their environment. This is similar to our human perception of the environment that is based
on multiple senses, like sight and hearing.

Each sensor that is attached to a machine requires processing power. The more sensors
attached, the greater the processing requirements on the machine. In the Arduino Uno, the
ATMega328 micro-controller is a simple computer running at a clock speed of 16MhZ
(mega-hertz). This means that this Arduino can process roughly 16 million instructions every
second. This processing resource has to be shared between all the things that your Arduino
is supposed to do, like reading values from its sensors, doing calculations, updating a
screen or other outputs, communicating with other devices, and interacting with the user.

The Arduino is fast, but it has a limit, and your design must take that into consideration.

1
Peter Dalmaris Lecture 6 Arduino Step by Step

In the lectures in this section, we will play with the following sensors:

• A photo-resistor for measuring light

• Combined temperature and humidity

• Infrared line sensor

• Barometric sensor for measuring air pressure

• Ultrasonic sensor for measuring distance to other objects

• Tilting, so you know if your gadget has fallen over

• Orientation

Simple sensors, like the photo-resistor for measuring light, work by measuring the voltage
they provide to one of the analog sockets in the Arduino. You can do this by using the
analogRead function (the opposite of the analogWrite function that we saw in the last
lecture, Lecture 5). Other sensors are a bit more involved, and they require special software
libraries to work with the hardware. More often than not, however, these libraries are very
easy to learn and they provide useful extra features at no additional cost.

Let's get right into it, and have a look at the photo-resistor.

2
Peter Dalmaris Lecture 7 Arduino Step by Step

Lecture 7
Measuring light
!
Measuring light is really easy. There are many sensors capable of detecting or measuring
light, but the photo-resistor is one of the easiest to use. A photo-resistor is simply a resistor
in which the resistance changes in accordance to its exposure to light.

You can find these devices on eBay for less that $3 for a
pack of ten. Think about what you can do with a device that
can detect light. Of course, your gadget will be able to know
if its day or night, or if the lights are on. So you could build a
gadget that that turns on a small light at the entrance of you
home when it darkens, so you don't have to walk in the dark.
You could also use a photo-sensitive device to allow two
gadgets to communicate with light; this is the principle
behind the typical television remote control where the
remote control and the television communicate using
infrared light. You could also build a simple robot that follows
a bright or dark line on the floor. Can you think of anything else you could do with a light
sensor?

Let's create a light-sensing circuit


We'll now create a circuit that contains a photo-resistor, and we'll use an Arduino sketch to
take light intensity readings from it.

Look at the circuit in the image below, and try to copy it. Here are a few things to be extra
careful about:

• Counting from the right, the photo-resistor is connected to a socket in column 1. Its
second leg is connected to a socket in column 4.

• We use a 220 Ohm resistor (or close, the exact rating is not important in this exercise) in
series with the photo-resistor in order to create a "voltage divider". More about this in a
minute.

• Connect the resistor's second leg to a socket in column 8.

• Connect the black jumper wire to the GND socket on the Arduino, and the red to 5V. Even
if you switch these connections, this circuit would still work because we are not using any
polarised components.

• Lastly, connect a green jumper wire from a socket in column 4 to A0, which is the Arduino
analog port 0.

1
Peter Dalmaris Lecture 7 Arduino Step by Step

Notice how you connected the green cable in column 4, where the resistor and the photo-
resistor meet? This type of wiring is called a "voltage divider" or "impedance divider", and
its purpose is to create an output voltage that is a fraction
of the input voltage to the divider. Look at the diagram
(right):

Vin is represented by the red jumper wire in our Arduino


diagram, the earth symbol is represented by the black
jumper wire. The Vout is represented by the green jumper
wire. Vout depends on the impedance (resistance) of Z1
and Z2, which in the case of our Arduino circuit are the
resistor and the photo-resistor. Since the resistor's
resistance is fixed, and the resistance of the photo-
resistor varies depending on the ambient light situation,
Vout will also vary. By taking a measurement of Vout, we
gain information about the light intensity in our lab.

The higher the measurement in socket A0, the more intense the light is. The closer to zero it
gets, the darker our lab is.

That's enough for now with the hardware. Let's look at the software.

2
Peter Dalmaris Lecture 7 Arduino Step by Step

The sketch
Here's our program for this exercise:

// the setup routine runs once when you press reset:

void setup() {

// initialize serial communication at 9600 bits per second:

Serial.begin(9600);

// the loop routine runs over and over again forever:

void loop() {

// read the input on analog pin 0:

int sensorValue = analogRead(A0);

// print out the value you read:

Serial.println(sensorValue);

delay(10);

!
Much of this sketch should be familiar to you now. There's
setup(), loop(), and delay(), which we have seen before.

There's a couple of new things here. First, look in the


setup() function. There is this statement:

Serial.begin(9600);

This creates a serial connection which the Arduino can


use to send text output to our terminal. This way the
Arduino can "talk" to us. This terminal can be opened by
clicking on Tools > Serial Monitor, and it looks like this:

3
Peter Dalmaris Lecture 7 Arduino Step by Step

!
We will be printing the light intensity value to the serial monitor in a moment.

Next, have a look in the loop() function. In the first actual statement after the comment, we
use the analogRead(A0) function to get a reading from socket A0 ("Analog 0") and store it to
the local integer variable sensorValue. Easy, right?

We now have a value captured from the photo-resistor's voltage divider circuit, let's print it
to the monitor so we can actually see it. Also easy, just do this:

Serial.println(sensorValue);

This statement, says: "Go to the serial port, print line with content 'sensorValue'". The "ln"
part of the println function means that this particular function will create a new line after
it prints out the text that is contained within the parentheses. You could use just
Serial.print(sensorValue), but then the output would look like this:

9469459469459459469459469469469459469

... not very useful, very hard to read.

When you send this program to the Arduino, wait for it to upload, and then open up the
monitor. You will see something like this:

946

946

946

946

946

946

946

945

946

946

4
Peter Dalmaris Lecture 7 Arduino Step by Step

The actual values will vary because of the differences in the components you used in your
circuit compared to mine, and of course the lighting conditions in our two labs are probably
different. But as long as you see similar values (above 0 and below 1024), then it worked!

Questions
That was easy, right? Please try out these questions before moving on to the next Lecture,
where you will learn about measuring temperature and humidity.

5
Peter Dalmaris Lecture 8 Arduino Step by Step

Lecture 8
Measuring temperature and humidity
!
In this lecture you will learn how to measure temperature and humidity. To do this, we will
use a sensor from the DHT family of temperature and humidity sensors.

The most common DHT sensors are the DHT11 and


DHT22. The DHT22 is double the price of the DHT11,
while still only around $10 on eBay, but has better
accuracy. Electrically, they are exactly the same, so you
could swap them in and out of your circuits at any time.
You can find DHT11's on eBay for less than $2.

In our example in a minute, I will be using the DHT22, like


the one in this picture (right).

There are 4 pins in the sensor's package, but only 3 are


actually used. Looking at the device from the front, going from left to right, pin 1 is for 5V
power, pin 2 is for data, pin 3 is not used, and pin 4 is GND.

Inside, this sensor is fairly sophisticated and contains hardware that does a lot of the work
that otherwise we would have to do in our Arduino sketch. As a result, as you'll see in a
minute, all we have to do is take a reading, there is no need for any conversion calculations
or any other hardware at all.

The DHT11 and DHT22 sensors, within their plastic case, contain:

• A capacitive humidity sensor

• A thermistor

• A chip that does analog to digital conversion

Capacitive humidity sensors


Capacitive humidity sensors are robust solutions for measuring humidity if our application is
ok with the relatively low accuracy of this device. Both DHT11 and DHT22 have a humidity
accuracy of around 5%, and are calibrated in the factory. In a capacitive humidity sensor, a
polymer or metal-oxide material is exposed to the environment and its dielectric properties
change as the humidity changes.

A thermistor is a resistor in which the resistance changes as the temperature changes. In


the DHT11 and DHT22, the readings in temperature are fairly accurate, at around 0.5%
accuracy.

1
Peter Dalmaris Lecture 8 Arduino Step by Step

Assembly
Time to put the demo circuit together. We will need:

• The Arduino

• Three jumper wires

• A DHT11 or DHT22

• A 10kOhm resistor

Here is the circuit we are going to build:

The resistor is used to as a "pull-up" and it


protects the Arduino (or whatever logic
device the resistor is connected to) in case
we either remove the sensor, or the sensor
malfunctions. The Arduino's input sockets
have build-in pull-up resistors, but they are
much smaller and it is a good idea to
provide our own.

2
Peter Dalmaris Lecture 8 Arduino Step by Step

Sketch
With the demo circuit assembled, lets now turn to the Arduino sketch that will drive it.

Here is the sketch, with comments:

// Example testing sketch for various DHT humidity/temperature sensors



// Written by ladyada, slightly modified, public domain

#include "DHT.h" // includes and external library



#define DHTPIN 2 // what pin we're connected to

#define DHTTYPE DHT22 // * The device type DHT22, DHT11, DHT21*

DHT dht(DHTPIN, DHTTYPE); // Initialize the device

void setup() {

Serial.begin(9600); // Start the serial port, set speed



Serial.println("DHT test"); //*Print a message to monitor*

dht.begin(); // Start the device

void loop() {

float h = dht.readHumidity(); //*Set local float variable for humidity*



float t = dht.readTemperature();//Set local float variable for temperature

// *check if returns are valid, if they are *



// NaN (not a number) then something went wrong!

if (isnan(t) || isnan(h)) {

Serial.println("Failed to read from DHT"); //*problem*

} else {

Serial.print("Humidity: "); 

Serial.print(h); //*Print humidity reading*

Serial.print(" %\t"); //*This outputs a tab*

Serial.print("Temperature: ");

Serial.print(t); //*Print temperature reading*

Serial.println(" *C”);

delay(500); //*Introduce a delay because these sensors are* //*slow*

Notice that there is an inclusion of the DHT.h library in the first line.

3
Peter Dalmaris Lecture 8 Arduino Step by Step

This library makes it easy to communicate with the DHT device. We will need to download it
and make it available to our sketch.

Get it from Adafruit's Github account at https://github.com/adafruit/DHT-sensor-library.


Setup instructions are included in that page. Don't forget to restart the Arduino IDE once
you are finished.

Now we'll run that sketch and look at the monitor output:

And that is how you connect and use the DHT22 or DHT11 sensor to the Arduino!

Questions
Please attempt the lecture questions before moving on to
lecture 9.

4
Peter Dalmaris Lecture 9 Arduino Step by Step

Lecture 9
Barometric pressure
!
Measuring the atmospheric pressure has several applications. Obviously, if you are a
meteorologist, knowing the pressure at a geographical location helps forecasting the
weather. But there's more.

Atmospheric pressure is defined as the weight of a column of air above an object. As the
height of a column of air above an object changes depending on its altitude, so does the
weight of that column. Atmospheric pressure at the surface of the sea is higher than that on
the top of a tall mountain because the column of air above it is higher. Therefore, measuring
the atmospheric pressure is also a simple way of figuring out your altitude, or the altitude of
one of your flying gadgets.

The standard unit for measuring atmospheric pressure is "Pa", or "Pascals". At sea level,
the standard pressure is defined to be 101.325 kPa, or 101,325 Pa.

We will be measuring atmospheric pressure by using the BMP085 sensor. This sensor costs
around $8 on eBay. It can measure pressure from 300hPa to 1100hPa, which converts to
around 500 meters below sea level to 9,000 meters above sea level. It's accuracy is also
excellent, around 0.03hPa. "hPa" is pronounced "hectoPascal".

Another nice thing about this sensor is that it also measures the temperature.

The BMP085 talks to other devices via the I2C interface, a digital serial communications
interface that only needs two wires for communication, and two for power. One
communication wire is called SDA, and it transmits
data, while the second, SCL, is for the clock signal.
A clock signal is needed because I2C is a
synchronous interface.

The sensor uses 3.3V (not 5V!), which the Arduino


conveniently provides. Here's what this sensor looks
like (right).

!
The BPM085 measures pressure by taking
advantage of the piezo-resistive property that silicon and germanium have. This property
involves the change in resistance in those materials depending on the amount of
mechanical load that is put on them.

!
1
Peter Dalmaris Lecture 9 Arduino Step by Step

Assembly
Let's puts together this circuit and try out the sensor.

We will need:

• The Arduino

• Four jumper wires

• A BMP085 sensor device

Here's what we are going to build (right).

This is very simple wiring. In Lecture 8


we connected a humidity and
temperature sensor, and we included a
pull-up resistor. We don't need this
resistor now because it is included
within the sensor's package. That's one
less thing for us to do.

If you are unsure of the connections,


double check the markings of each pin
on the sensor.

2
Peter Dalmaris Lecture 9 Arduino Step by Step

Sketch
Done with the assembly, lets work on the sketch now.

Just like in Lecture 10, to use the barometric sensor we include an external library in our
sketch. This comes from Adafruit, and you can find it on Github. Follow the instructions in
the README.txt file for setting it up, and don't forget to restart your Arduino IDE!

Here's the sketch, it comes straight of the examples that are included with the Arduino IDE.
I have added some comments to help you understand what is going on:

#include <Wire.h> //*Include the Wire library which allows *



//*To use the I2C interface*

#include <Adafruit_BMP085.h> //*Include the Adafruit_BMP085 



//*library to easily take*

//*readings from the sensor*

Adafruit_BMP085 bmp; //*Declare the bpm variable,



//*an easy to remember reference for the

//*device

void setup() {

Serial.begin(9600); //*Setup serial communication and speed*



if (!bmp.begin()) { //*Try to start the device*

//*If it is not starting, print message*

Serial.println("Could not find a valid BMP085 sensor, check


wiring!”);

while (1) {} //* Go in an endless loop. This prevents the*


//*Arduino from calling the loop function*
}

void loop() {

Serial.print("Temperature = ");
Serial.print(bmp.readTemperature()); //*Read and *
//*print temperature*
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bmp.readPressure()); //*Read and print*
//*pressure*
Serial.println(" Pa");
// Calculate altitude assuming 'standard' barometric
// pressure of 1013.25 millibar = 101325 Pascal
Serial.print("Altitude = ");
Serial.print(bmp.readAltitude()); //*Read and print*
//*altitude*
Serial.println(" meters");

3
Peter Dalmaris Lecture 9 Arduino Step by Step

// you can get a more precise measurement of altitude



// if you know the current sea level pressure which will

// vary with weather and such. If it is 1015 millibars

// that is equal to 101500 Pascals.

Serial.print("Real altitude = ");


Serial.print(bmp.readAltitude(101500)); //*Read and print*

//*calibrated altitude*
Serial.println(" meters");
Serial.println();
delay(500);
}

Now we'll run this sketch and look at the monitor output:

And that is how you connect and use the BMP085 barometric sensor with the Arduino!

Questions
Please attempt the lecture questions before moving on to lecture 10.

4
Peter Dalmaris Lecture 10 Arduino Step by Step

Lecture 10
Motion
!
Knowing if something is moving is useful in many applications. The classic example is
security, where an alarm system can detect an intruder moving inside a room, so that it can
notify the police. Another common use is in home and office automation, where you could
get the lights to turn on and off automatically depending on whether someone is still in the
room or turning on the flood light in your driveway as
your car approaches.

There are several technologies used in motion sensors,


each with their own capabilities and price points.

Passive infrared (PIR) sensors are very common and


typically found in home electronics. They detect the heat
that is emitted by the body of a person in a room as it
contrasts against the background heat. A PIR sensor
does not emit any energy, it just sits there and waits for a
heat source to enter its field of vision. They look like this
(an example of a home security system motion sensor -
right).

!
An ultrasonic motion sensor uses ultrasounds
to detect moving objects. Just like bats, an
ultrasonic sensor emits ultrasounds at
frequencies from 30khz to 50kHz and then
picks up their echo. These sensors can often
measure the time a signal takes to return, and
from that it can calculate the distance to the
object. Therefore, ultrasonic sensors can
calculate both distance from an object as well
as whether the object is moving. We will be
looking at ultrasonic sensors in the following
Lecture.

!
A microwave motion sensor works on the same principle as the ultrasonic sensor, except
that instead of ultrasounds it emits microwaves. They are still relatively cheap, and because
microwaves are much higher in terms of frequency than ultrasounds, motion can be

1
Peter Dalmaris Lecture 10 Arduino Step by Step

detected with a lot more detail. Many microwave


motion sensors can determine not only the
motion itself, but also distance and speed using
the Doppler effect.

Here is what a microwave sensor module looks


like (of course the module is covered by a plastic
cover when installed - right).

!
!
In this lecture, we will connect a passive infrared sensor to our Arduino, calibrate it, and
turn an LED on every time motion is detected.

Assembly
Let's puts together this circuit and test out the motion sensor.

We will need:

• The Arduino

• Four jumper wires

• A PIR sensor, like the HC-SR501

• One resistor, 1kΩ

• One LED

Here's what we are going to build (right).

While you are connecting the motion


sensor, it's a good idea to remove the
sensor cover so you can see the pin
markings, ensuring that power is
connected the right way.

This circuit will detect motion through


the sensor, and send a signal to the
Arduino via digital pin 2. The Arduino will
receive the signal and in turn activate
the LED via digital PIN 13. Notice that
the Arduino UNO board already has an
small LED connected to digital port 13, so you could choose to not connect yours.

2
Peter Dalmaris Lecture 10 Arduino Step by Step

!
Sketch
Done with the assembly, let work on the sketch now.

/*

* PIR sensor tester

*/

int ledPin = 13; // choose the pin for the LED



int inputPin = 2; // choose the input pin (for PIR sensor)

int pirState = LOW; // we start, assuming no motion detected

int val = 0; // variable for reading the pin status

void setup() {

pinMode(ledPin, OUTPUT); // declare LED as output

pinMode(inputPin, INPUT); // declare sensor as input

Serial.begin(9600);

}

void loop(){

val = digitalRead(inputPin); // read input value

if (val == HIGH) { // check if the input is HIGH

digitalWrite(ledPin, HIGH); // turn LED ON

if (pirState == LOW) { // we have just turned on 

Serial.println("Motion detected!”);

// We only want to print

// on the output change, not state

pirState = HIGH;

}
} else {

digitalWrite(ledPin, LOW); // turn LED OFF

if (pirState == HIGH){

// we have just turned off

Serial.println("Motion ended!");

// We only want to print on

// the output change, not state

pirState = LOW;

}

3
Peter Dalmaris Lecture 10 Arduino Step by Step

By now, this sketch should be easy to read and understand. We start by setting constants
for the pins and values. The LED is connected to digital pin 13, and the sensor's output to
digital pin 2. We also assume that when the Arduino starts, there is no motion, so variable
pirState is set to LOW, and val, the variable to which the output state of the PIR sensor is
stored, is 0 (LOW).

In the setup() function, we set pin 13 to be output, and pin 2 to be input. We also initialise
the serial port so that we can see text output in the monitor window.

In the loop() function, we constantly read the value of the PIR sensor by using the
digitalRead(inputPin) function. This function reads voltage in the range of 0V to 3.3V (at
least for the sensor I am using), and the Arduino translates that to LOW and HIGH
respectively.

If HIGH is detected, the Arduino will set pin 13 to HIGH and this will activate the LED. If the
previous state of the sensor was LOW, then the Arduino detects this as new motion, so it
will print a message to the monitor, and set pirState to HIGH. This will prevent the Arduino
from continuously printing out that new motion was detected while the actual motion is still
continuing.

Upload it to see it working, don't forget to open up the monitor window (Tools > Serial
Monitor). You should see something like this:

!
If you are not sure what the pirState variable is actually doing, do this little experiment:

4
Peter Dalmaris Lecture 10 Arduino Step by Step

Modify the sketch by replacing the lines:

if (pirState == LOW) {

Serial.println("Motion detected!");

pirState = HIGH;

}

with only:

Serial.println("Motion detected!");

... and the lines:

if (pirState == HIGH){

Serial.println("Motion ended!"); 

pirState = LOW;

}

... with only:

Serial.println("Motion ended!");

Upload the edited sketch. Open the monitor and activate the sensor by waving your hand
above it. What can you see in the monitor?

You can calibrate the sensitivity and amount of time that the sensor stays activated by
turning the two small orange knobs. Experiment with them to see the effect they have on
the sensor's output.

That's it with the PIR sensor for now. Please attempt the quiz questions before continuing
with the next lecture, were you'll learn about the ultrasonic distance sensor.

5
Peter Dalmaris Lecture 11 Arduino Step by Step

Lecture 11
Distance
There are lots of applications where we not only need to know that an object, or a person,
in nearby, but also how far they are. Imagine a robot moving around in a room. The robot
can use a distance (or proximity) sensor to detect that it is approaching a wall or another
object. Or, you could use a proximity sensor to automatically open a door if a person is
within a meter of the sensor. You find
such sensors in cars (to help with
parking and to avoid small accidents),
and in smart phones where the
smartphone can detect, for example,
that the phone is held against the
user's head, useful so that the screen
is turned off to avoid accidental
touchscreen input.

There are many types of technologies


that can be used to make a proximity
sensor. In this lecture we will focus on
the ultrasonic sensor, which is
essentially a "land sonar": it emits a
high frequency sound, far beyond
what the human ear can hear, and
waits for the echo. Once it captures
the echo, it counts the time that
elapsed between the emission of the
ultrasound signal and the capture of
its echo, and based on that it
calculates the approximate distance
of the object that produced the echo.

Ultrasonic sensors are solid-state devices, very reliable and cheap. Especially in indoor
environments, and for small spaces (or measuring small distances), these sensors represent
a good choice. Anything that is solid enough to allow sounds to bounce will work with
these sensors. If you want to measure or detect things like smoke and clouds, you will need
to use something else, perhaps a microwave doppler radar.

For the Arduino, a commonly used proximity sensor is the HC-SR04. You can find them on
Ebay for less than $2 each.

They are very easy to use, let's have a look.

!
1
Peter Dalmaris Lecture 11 Arduino Step by Step

Assembly
Let's puts together this circuit and test
out the motion sensor.

We will need:

• The Arduino

• Six jumper wires

• An ultrasonic sensor, like


the HC-SR04.

Here's what we are going to build:

[show image of "S2 L12 - distance.png"]

The sensor will constantly take distance


measurements of whatever happens to
be in front of it: your hand, books etc. The
Arduino will receive these readings and
print them to the monitor. Very simple.

!
Sketch
Done with the assembly, let work on the sketch now.

#define trigPin 13



#define echoPin 12

void setup() {

Serial.begin (9600);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

}

void loop() {

long duration, distance;

digitalWrite(trigPin, LOW);

delayMicroseconds(2);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

duration = pulseIn(echoPin, HIGH);

distance = (duration/2) / 29.1;


2
Peter Dalmaris Lecture 11 Arduino Step by Step

if (distance >= 200 || distance <= 0)



{

Serial.println("Out of range”);

}

else {

Serial.print(distance);

Serial.println(" cm");

} 

delay(500);

}

!
There's quite a lot happening in this small amount of code.

We define the sensor's trigger and echo pins to be 13 and 12 respectively. In the setup
function, we initialise the monitor, and set pin 13 to be the output and pin 12 to be the
input.

Through pin 13, the Arduino will ask the sensor to trigger a ping, similar to the "boing" noise
that submarines emit when they use their sonar. This ping, assuming it bounces of an
object in range, will come back and will be picked up by the sensor's receiver. The Arduino
will know when that happens because it is monitoring pin 12, which is connected to the
sensor's echo pin.

In the loop() function, we first setup two variables of type long. Long numbers are 4 bytes in
size, a total of 32 bits, and can hold very large numbers: -2,147,483,648 to 2,147,483,647.
The variable duration will hold the total number of microseconds that it took for the ping to
reach the object and return to the sensor. The variable distance will contain the distance to
that object in centimetres.

The Arduino is triggering a ping by writing to the trigger pin three pulses: first, a digital LOW
for 2 microseconds, then a digital HIGH for 10 microseconds, and finally a digital LOW
which stays low until the next iteration of the loop.

1
0.5
0

Ping 1 Ping 2 Ping 2

!
It then uses the function pulseIn to get the number of microseconds in takes of the ping to
come back. PulseIn accepts two parameters: a pin number (in our case it is 12, stored in
variable echoPin), and the pulse level we want to detect, in our case it is HIGH because we

3
Peter Dalmaris Lecture 11 Arduino Step by Step

want to detect the 10 microsecond ping we just emitted. As soon as the Arduino calls the
pulseIn function, it starts timing. It returns the number of microseconds from the time the
function was called until it detects the ping echo.

The distance is calculated by the Arduino. It divides by two the duration that the pulseIn
function returned, since the ping travels a total of twice the distance to the object (going
there and its echo coming back). It then divides again by the "magic number" 29.1. This
number derives from this calculation:

The speed of sound at 0 degrees celsius is measured to be 331.5 meters per second. At
different temperatures, the speed of sound is calculated by adjusting 331.5m/s for the
temperature by multiplying by 0.6:

SpeedOfSound(Temperature) = 331.5 + 0.6 * Temperature


At 20 degrees, this works out to be 343.5 m/s.

We need to convert the seconds to microseconds and the length from meters to
centimetres:

SpeedOfSound = 343.5 * 100 / 1,000,000 = 0.03435 cm/


microseconds
This means that sound, at 20 degrees, can travel a distance of 0.03435 centimetres in one
microsecond. If a signal and its echo take X microseconds to do the round trip, then the
total distance covered is:

Total_distance = X * 0.03435 = X / 29.1


We adjust this so that we only include the duration of the one-way trip to the target (instead
of the return trip), and the formula becomes:

distance = ( X / 2) * 0.03435 = ( X / 2 ) / 29.1


Wikipedia has a very good article on how to calculate the speed of sound, for the curious.

Limitations
If the distance to a target is over 200 centimetres, the Arduino reports that the target is out
of range, since at that distance measurements are not reliable. The same happens if the
distance is negative (question to consider, why do we need to test for negative
distance???). Any other distance condition is valid, so the monitor will print out the distance
in centimetres.

4
Peter Dalmaris Lecture 12 Arduino Step by Step

Lecture 12
Measuring acceleration
Acceleration is defined as the rate by which the velocity of an object changes. The velocity
of an object changes when a force is applied to it. Acceleration is quantified by a direction
and a magnitude. Direction is the way to which a force is directing the object, and
magnitude relates to the strength of the applied force. Acceleration is described by
Newton's Second Law.

Having the ability to measure acceleration is very useful. For this purpose, we use an
accelerometer. An accelerometer measures the force that is applied to a small test mass.
This test mass is placed inside the device and is held in place by one or more springs (or
something equivalent). As gravity, or other forces, are applied on the test mass, they make
it move towards a particular direction. The device measures the distance this mass travels
from its resting position. The longer the distance, the stronger the force.

Imagine the accelerometer (or your self) in free fall, the test mass, as it is falling, is "feeling"
no force being applied upon it. In a free-fall situation, the accelerometer would report no
acceleration at all.

We use accelerometers in cars to detect collisions (and deploy airbags), or to gather


performance statistics. Accelerometers are embedded in smart phones to provide
orientation information, and for making games that are played by moving a controller
device. You could use one in a toy car so that the car's wheels stop spinning if it has turned
over, or to make toys that react to the movement of a controller in 3-D space.
Accelerometers are also part of Inertial Navigation
Systems (INS) that help vehicles (ships, planes,
cars, submarines etc.) maintain knowledge of their
location when other positioning systems, like GPS,
are not available.

In our experiment, we will use a common 3-axis


accelerometer, the ADXL335. It is very cheap at
around $7 on eBay, and very easy to connect to the
Arduino through any of the analog pins. It reports
acceleration in 3 dimensions, X, Y and Z. It is very
robust as it can detect forces of up to 10,000 Gs (1
G is equivalent to the Earth's gravity at the surface).

!
!

1
Peter Dalmaris Lecture 12 Arduino Step by Step

Assembly
Let's puts together this circuit and test out the
motion sensor.

We will need:

• The Arduino

• Five jumper wires

• An ADXL335 3-axis
accelerometer.

The sensor takes three acceleration


measurements, X, Y, and Z. The Arduino reads
the analog outputs 0, 1, and 2, acquires the
measurements, and prints them to the monitor.

Also, be very mindful of the power limits of this


device. It needs 3.3V input, not 5V! If you
provide 5V you may actually damage it!

Sketch
Done with the assembly, let work on the sketch now.

!
int x, y, z;

void setup()

{

Serial.begin(9600); // sets the serial port to 9600

}

void loop()

{

x = analogRead(0); // read analog input pin 0

y = analogRead(1); // read analog input pin 1

z = analogRead(2); // read analog input pin 1

Serial.print("accelerations are x, y, z: ");

Serial.print(x, DEC); // print acceleration in the X axis

Serial.print(" "); // prints a space between the numbers

Serial.print(y, DEC); // print acceleration in the Y axis

Serial.print(" "); // prints a space between the numbers

Serial.println(z, DEC); // print acceleration in the Z axis

delay(100); // wait 100ms for next reading }

2
Peter Dalmaris Lecture 12 Arduino Step by Step

!
We have not seen the analogRead() function before, but I am sure you can guess what it
does: it reads the voltage present at one of the analog pins. The accelerometer outputs
voltage to its three outputs relevant to the forces applied to it.

For example, at rest, the reading on the Z axis is around 410. If I push the device upwards, I
apply force along the Z axis which makes the test weight inside the accelerometer "feel"
heavier, and the voltage on the Z pin increases, causing the reading to increase (i.e. to
~470, in my experiment). If I push the device downwards, the opposite happens.

By taking and evaluating measurements in all three axis, you could make it possible for your
device to know the precise direction of its movement and the force applied to it.

3
Peter Dalmaris Lecture 13 Arduino Step by Step

Lecture 13
Infrared line sensor
!
An infrared line sensor is a simple device made up of an infrared emitting LED and an
infrared sensitive photo-resistor.

You could use one of these sensors to build a robot that follows a dark line on the floor, or
your own heart rate monitor.

The principle of operation is very simple: The transmitter produces infrared light which
bounces of a surface and comes back to be captured by the photo-resistor. The more
infrared light is reflected back into the photo-resistor, the
higher the output of the sensor gets.

In our experiment we will use a QRE1113 line sensor from


Sparkfun. You can get something like this on eBay for
less than $2.

Assembly
Let's puts together this circuit and test out the motion
sensor.

We will need:

• The Arduino

• Three jumper wires

• An QRE1113 line sensor or equivalent


(like this ywRobot device).

Here's what we are going to build (right).

For power, you can plug this sensor into


either the 3V or 5V sockets on the Arduino.

!
!

1
Peter Dalmaris Lecture 13 Arduino Step by Step

Sketch
This one is very simple, just read the analog output at pin A0 and print it to the monitor:

// Line Sensor Breakout - Analog



int out;

void setup()

{

Serial.begin(9600); // sets the serial port to 9600

}

void loop()

{

out = analogRead(0); // read analog input pin 0

Serial.println(out, DEC); // print acceleration in X axis

delay(100); // wait 100ms for next reading

}

2
Peter Dalmaris Lecture 14 Arduino Step by Step

Lecture 14
Tilt and impact sensor
!
In many cases, knowing the exact force and direction applied to our gadgets is an overkill;
just knowing that a bottle has been tipped over is enough to know that the lid should close
automatically. For simple cases like that, a 3-axis accelerometer is an overkill. We could use
a simple sensor that can detect the shock of an impact or for being upside down.

The tilt and impact sensor is a simple switch which closes a


circuit when positioned in a particular way. They are very cheap,
around $5 on eBay for a pack of 10. They come in a variety of
shapes, but usually they are made of a tiny metallic cylinder with a
thin copper wire coming out of one end. The cylinder contains
wires or a metal ball. When the device is hit or when its orientation
changes, the wires or the ball come in contact with the wall of the
cylinder and closes a circuit between the cylinder and the external
wire. They can be very sensitive, so care must be given to
compensating for this sensitivity, otherwise we would be getting readings
that look chaotic. We are going to ignore this sensitivity for now.

Here is what a tilt sensor looks like from the outside (right - top)…

... and on the inside (right - bottom).

!
!

1
Peter Dalmaris Lecture 14 Arduino Step by Step

Assembly
To put this circuit together, we'll just
use the Arduino, no breadboard is
required.

We need to do a bit of soldering in


order to connect the sensor to wires
which we can connect to the
Arduino. If you have never done
soldering before, follow this tutorial
for some instructions. Be careful not
to get burned!

Here's what we are going to build


(right)…

!
!
Sketch
This is another very simple sketch. We'll just use the analog port to determine if the switch
inside the sensor is closed or open. You could just as easily have used a digital pin since
there are only two states to detect, open or close, which nicely translate to HIGH or LOW.

!
int out;

void setup()

{

Serial.begin(9600); // sets the serial port to 9600

}

void loop()

{

out = analogRead(0); // read analog input pin 0

Serial.println(out, DEC);

delay(100); // wait 100ms for next reading

}

2
Peter Dalmaris Lecture 14 Arduino Step by Step

Try out by connecting the sensor to the Arduino and moving the sensor in different
directions. This is easier if you use some electrical tape to keep the sensor wires tidy. You
could even stick the sensor onto the Arduino, and move the whole assembly instead of only
the sensor. This will help in keeping the connections firm.

3
Peter Dalmaris Lecture 15 Arduino Step by Step

Lecture 15:
Button
!
A button is a simple on-off switch. There are many kinds of buttons, distinguished by the
mechanism used to close or open a circuit, but essentially all buttons belong to one of two
families: those that keep the connection in either an open or a closed state, and those that
return to their original (default) state.

Here are some examples of switches.

Clock-wise from the top:

• A toggle switch. It stays open or closed after pushing it.

• An on/off switch that also remains open or


closed.

• A momentary button that remains closed


while pressure is applied to it, then returns to
the open position.

!

A keyboard key or a door bell button are both momentary buttons. Momentary buttons are
also known as "biased" because they have a tendency to return to their original position. A
light switch, on the other hand, stays at the position it was pushed to, so it is often called
"un-biased".

1
Peter Dalmaris Lecture 15 Arduino Step by Step

Experiment
Let's create a simple circuit to demonstrate a
button.

We don't really need the Arduino for this. A


battery, an LED, a resistor and the button itself
would suffice.

But, using the Arduino is simple enough, and


it's already got an LED in pin 13 we can use
anyway, and no need to worry about a battery
pack.

Plus, we can use the monitor to actually see a


message when the button is pressed.

So, we'll setup this circuit (at right).

!
Once assembled, the project will look like this
(below):

2
Peter Dalmaris Lecture 15 Arduino Step by Step

Sketch
The sketch is simply taking a reading from digital pin 2, where one of the pins of the button
is connected, and writing a value to digital pin 13, where the LED is connected.

I could have written this script to be even smaller, but I will leave that for you to do as an
exercise.

/*

Pushbutton sketch a switch connected to pin 2 lights the LED
on pin 13

*/

const int ledPin = 13;



const int inputPin = 2;

void setup() {

pinMode(ledPin, OUTPUT); // choose the pin for the LED

// choose the input pin (for a

// pushbutton)

// declare LED as output

// declare pushbutton as input

pinMode(inputPin, INPUT);

}

void loop(){

int val = digitalRead(inputPin); // read input value

if (val == HIGH)
{
digitalWrite(ledPin,HIGH);
} else
{
digitalWrite(ledPin,LOW);
}
}
And that's how you can use a momentary button with the Arduino!

3
Peter Dalmaris Lecture 16 Arduino Step by Step

Lecture 16
Potentiometer
In this lecture I'll show you how to use a potentiometer. A
potentiometer is a device that allows you to change the value of a
resistance by turning a knob.

Let's put this circuit together, and then we'll discuss how it works. In
particular, we'll see what is happening
inside the potentiometer.

Assembly
Let's assemble the circuit. You will need:

• The Arduino

• A potentiometer

• An LED

• A resistor to protect the LED (I used a


1kΩ resistor)

As you turn the knob of the potentiometer,


the resistance connected to its output pin
changes. This in turn changes the voltage
on that pin. This output voltage is read by
the Arduino at analog pin 0 (A0).

The Arduino will then use digital pin 11 to


drive the LED. Although pin 11 is digital, we
are using its Pulse Width Modulation (PWD)
feature, like we did back in Lecture 5. We
just glossed over this feature back then: we
used the analogWrite instruction which
makes use of this feature. Later in this
lecture I will explain how PWD works.

Here’s a photo of the assembled circuit:

!
!

1
Peter Dalmaris Lecture 16 Arduino Step by Step

How it works
!
Potentiometer
Remember back in Lecture 7 where you learned
about the voltage or impedance divider? Back then,
the divider was fixed as we used two fixed resistors.

In a potentiometer, we still have these two resistors


inside the package, but at least one of them is
variable, that is, the resistor changes as we turn the
knob.

In the diagram on the right, the pin in the middle is


connected to a dial that is made of conductive
material, like copper. They gray-coloured circle
represents a resistor, with its two ends connected to V+ and Ground. As the dial comes in
contact with different parts of the resistor, it samples a voltage between V+ and ground,
and we can read this voltage from the middle pin.

So there you have it, a potentiometer is nothing more than a variable voltage divider.

Pulse Width Modulation


Arduino's digital pins can output HIGH and LOW, as we have already seen. Some of these
digital pins, however, are special: although they can still only output HIGH and LOW, their
output can be modulated is a way that this output can behave as if it was analog.

Have a look at this diagram, taken


from the Arduino web site. A
"normal" digital pin outputs 0V or
5V, like in the top and bottom
waveform examples. But, in a pin
that supports PWM, we can output
5V for only part of the period. In the
second waveform, for example, we
output 5V for 25% of the period,
and 0V for the rest. In the third
example, its 50% and 50%
respectively.

On the LED, this kind of modulation


on the output signal has an effect
similar to using an analog pin and
outputting voltage in the range of
0V to 5V. In effect, we simulate
analog output using a digital pin!

2
Peter Dalmaris Lecture 16 Arduino Step by Step

Sketch
Here's the sketch that drives this circuit:

int potentiometerPin = 0;



int ledPin = 11;

int potentiometerVal = 0;

void setup()

{

Serial.begin(9600); // setup serial

}

void loop()

{

potentiometerVal = analogRead(potentiometerPin);

//I use the map function because PWM pins can only accept

//values from 0 to 255. Analog pins can output values from

//0 to 1023. With the map function, the range 0-1023 is

//converted to appropriate values from 0 to 255.

int mappedVal = map(potentiometerVal,0,1023,0,255);

Serial.print(potentiometerVal);

Serial.print(" - ");

Serial.println(mappedVal);

analogWrite(ledPin,mappedVal);

delay(10);

}

There is nothing new here. We have seen the "map" function in an earlier lecture, so you
know that this function is used when we want to make a range of values fit within another
range of values. In this case, we read values in the range of 0 to 1023 from analog pin 0,
and we want to make this fit in the range 0 to 255, which is what the pulse width
modulation-capable pin 11 can output.

Other than that, we simply use the "analogRead" function to read a value from analog pin 0,
and the "analogWrite" function to create a PWM pulse on digital pin 11.

Simple!

3
Peter Dalmaris Lecture 16 Arduino Step by Step

Here's an experiment: Take a small speaker and connect it to the breadboard so that it
replaces the LED. Fire up the circuit. Can you hear the sound coming out of it? Can you
notice how its pitch changes as you turn the knob?

4
Peter Dalmaris Lecture 17 Arduino Step by Step

Lecture 17
Flex sensor
!
A flex sensor is a device made of a thin, flexible
material of which the resistance changes (it increases)
as it flexes. Hence, its name.

You can use these sensors to detect stress in machines


or structures, but also in things like this "power glove":

There's lots of other uses, like in biometrics, in fitness products, and in gaming devices.

Let's have a look at the flex sensor in action.

1
Peter Dalmaris Lecture 17 Arduino Step by Step

Assembly
This is what we are going to build:

You will need:

• The Arduino

• A flex sensor (you can get one from Sparkfun


for around $12)

• A 1kΩ resistor (to build a voltage divider)

• Three jumper wires.

!
Here’s the completed circuit:

!
2
Peter Dalmaris Lecture 17 Arduino Step by Step

Sketch
And, here's the script. All we need to do is to read the voltage at analog pin 0 and print it in
the monitor.

void setup() {

// initialize serial communication at 9600 bits per second:

Serial.begin(9600);

}

// the loop routine runs over and over again forever:

void loop() {

// read the input on analog pin 0:

int sensorValue = analogRead(A0);

// Convert the analog reading (which goes from 0 - 1023) 

//to a voltage (0 - 5V):

float voltage = sensorValue * (5.0 / 1023.0);

// print out the value you read:

Serial.println(voltage);

}

Upload it to your Arduino and open up the monitor. Bend the sensor back and forth. See
how the output fluctuates as the sensor's shape changes?

What's inside a flex sensor?


A flex sensor is made of carbon resistive elements surrounded by a plastic flexible
protective cover. As the elements are bend, their resistance increases as a function of its
radius because the resistive material becomes slightly thinner. In effect, when the material
becomes thinner, there is less carbon to conduct electricity, therefore the resistance
increases.

3
Peter Dalmaris Lecture 18 Arduino Step by Step

Lecture 18
Membrane potentiometer
A rather unusual type of potentiometer is the
membrane potentiometer.

A membrane potentiometer is electrically


exactly the same as a typical rotary
potentiometer. The difference is in the user
interface. Instead of rotating a knob in order
to change the resistance of the middle pin,
you can slide your finger over the sensor's
surface.

Assembly
What we are going to build is exactly
the same circuit as in Lecture 16.
We'll just replace the rotary
potentiometer with the membrane
potentiometer.

Here's the parts we need:

• The Arduino

• A membrane potentiometer

• 3 Jumper wires

Here's the circuit:

!
!

1
Peter Dalmaris Lecture 18 Arduino Step by Step

And here’s the assembled circuit:

The monitor output is essentially the same as with the potentiometer. The only difference is
that the actual resistance of the voltage divider will be different between the two devices so
the actual reading will be different in analog pin 0.

2
Peter Dalmaris Lecture 18 Arduino Step by Step

Sketch
Here's the sketch, as a reminder since we've seen this before.

void setup() {

// initialize serial communication at 9600 bits per second:

Serial.begin(9600);

}

// the loop routine runs over and over again forever:



void loop() {

// read the input on analog pin 0:

int sensorValue = analogRead(A0);

// Convert the analog reading (which goes from 0 - 1023) 

// to a voltage (0 - 5V):

float voltage = sensorValue * (5.0 / 1023.0);

// print out the value you read:

Serial.println(voltage);

}

What's inside a membrane potentiometer?


The membrane potentiometer works on the same principle as a
regular potentiometer. The difference is that a rotary potentiometer
has a conductive wire attached to the knob, and as the knob turns, it
makes the conductive wire come in contact with a circular resistor.

!
The membrane
potentiometer,
however, is made by having a conductive
membrane (hence the name) that is
suspended over a resistor material. As one
presses the membrane, it comes in contact
with the resistor under it at different lengths
of the resistor, and closes a circuit, thereby
implementing the voltage divider.

3
Peter Dalmaris Lecture 19 Arduino Step by Step

Lecture 19
Buzzer
A buzzer is a device that can generate simple
tones, typically used to provide audible feedback
to the user. Buzzers are used in alarm clocks,
keypads, many household appliances and simple
toys.

To show you how a buzzer works with the Arduino,


we will re-purpose the circuit we used back in
Lecture 16, where we controlled the brightness of
an LED using a potentiometer. What we'll do here,
is to control the tone of the sound emitted by a
buzzer using the same potentiometer. We'll just
replace the LED with the buzzer.

Assembly
This is what we'll make:

We will need:

• The Arduino,

• A buzzer,

• 7 jumper wires.

The circuit is essentially the same as


in Lecture 16. We use the digital pin
11 to generate PWD pulses that
depend on the voltage measured at
analog pin 0. This is the voltage
controlled by the potentiometer.

As the potentiometer generates a


higher voltage, the pulses in digital
pin 11 have a longer duty cycle and
trigger the buzzer to generate a
louder, higher pitch sound. When the
potentiometer generates a lower
voltage, pin 11 generates a shorter duty cycle pulse which makes the buzzer generate a
softer, lower pitch sound.

!
1
Peter Dalmaris Lecture 19 Arduino Step by Step

And here's the assembled circuit:

!
!

2
Peter Dalmaris Lecture 19 Arduino Step by Step

Sketch
The only difference between this script and the one from Lecture 16 is the variable name for
the buzzer pin. ledPin is now buzzerPin.

int potentiometerPin = 0;



int buzzerPin = 11;

int potentiometerVal = 0;

void setup()

{

Serial.begin(9600); // setup serial

}

void loop()

{

potentiometerVal = analogRead(potentiometerPin);

//I use the map function because PWM pins can only accept

//values from 0 to 255. Analog pins can output values from

//0 to 1023. With the map function, the range 0-1023 is

//converted to appropriate values from 0 to 255.

int mappedVal = map(potentiometerVal,0,1023,0,255);

Serial.print(potentiometerVal);

Serial.print(" - ");

Serial.println(mappedVal);

analogWrite(buzzerPin,mappedVal);

delay(10);

}

And there you go, making sounds with the Arduino is super easy.

3
Peter Dalmaris Lecture 20 Arduino Step by Step

Lecture 20
Direct current motor
!
Direct current motors represent the easiest way to add movement to your projects. But
“easy” does not mean “less capable”. A direct current or DC motor can be a very cost
effective and flexible solution for all sorts of projects: robots, cars, boats, toy helicopters,
home automation, and many more.

In this lecture I will show you how to use a DC motor through a series of demos. All involve
two geared DC motors (why use just one when we can use two?) and a motor break-out
circuit. I’ll explain what these are in a minute. Here’s what we are going to build in this
lecture:

• First, we’ll just hook the motors to the Arduino via the motor break-out board, and make
them spin in a single direction.

• Second, we’ll get the motors spinning forwards and backwards using a potentiometer as
a controller.

• Third, we’ll use an ultrasonic sensor to get the motors to spin faster or slower depending
on the distance between the sensor and an object in front of it.

Before we get into the demo, I want do a quick introduction to motors, and specifically to
discuss the kinds of motors people can use in their projects.

!
!

1
Peter Dalmaris Lecture 20 Arduino Step by Step

Motors
The most common type of motor is the DC motor. These are
low cost devices that work by connecting two wires to
positive and negative voltage. Once you connect them to
power, the shaft will start spinning towards a direction. This
direction depends on the polarity of the connection. To
reverse the direction of the spin, just switch the electrical
connections.

All electrical motors work by taking advantage of the forces


generated by a magnet (permanent or temporary electro-magnet) and the electric field
generated by electrical current as it travels through a coil. (Schematic taken from http://
www.electrical4u.com/working-or-operating-principle-of-dc-motor/).

The DC motor can spin very quickly, which often is not what we want in our applications.
For example, if you are building mechanism that opens the shutters of a window, you would
like the shutter to open slowly to avoid damaging it. A DC motor on its own would try to go
full speed immediately. So, in most cases people attach a gear box to the motor. The gear
box will convert high rotational spin from the shaft of the motor to lower rotational speed,
and often with a higher torque so that large loads can be moved.

In the examples in this lecture, I will show you what a gear box
looks like.

Another common type of motor is the stepper motor. Stepper


motors operate by moving the motor shaft in steps, hence the
name. While the DC motor will move constantly while there is
power, a stepper motor will move by one step when a signal is
send via a wire, and then stop. How big each step is depends on
the construction of the motor. For applications where you need

2
Peter Dalmaris Lecture 20 Arduino Step by Step

fine control and small movements, a stepper motor is a good choice. For example, they are
used in 3-D printers, where milli-meter accuracy is needed.

Stepper motors tend to be much bulkier and expensive then DC motors. They contain
multiple coils and more complicated mechanical components, and that reflects in the price.
Your circuitry also needs to be more complicated because you need to provide several
signal lines of control to make it work.

A common problem with stepper motors is that in certain situations


(usually under high load), there is a mismatch between the signal
that the motor controller is sending and the actual mechanical
movement that the motor produces. In simple words, the motor
may “miss” steps and the controller will never know because
usually there is no feedback mechanism to track and confirm
movement.

A servo motor comes in to fix this problem. A servo motor contains a DC


(usually) motor, a gear box, and a position feedback mechanism. This mechanism can make
the humble DC motor as accurate as a stepper motor (for a lower price), with the added
benefit of monitoring and confirming the actual position of the shaft. Servo motors are used
extensively in robotics, manufacturing automation systems, and high-end toys.

!
!
!

3
Peter Dalmaris Lecture 20 Arduino Step by Step

Demo 1: Motor quick start guide


Let’s build a simple circuit that controls 2 geared DC motors from a toy tank that I stole
from my kids (they originally stole it from me).

Even though you could connect a DC motor directly to the Arduino, that is not a good idea.
The Arduino can only provide very little current
to external devices, and only tiny motors
would be satisfied with that. In virtually all real-
life applications, we need to provide external
power to the motor, and only signalling from
the Arduino.

To do this, I am going to use a break-out board


that contains the L298N motor driver “bridge”.
This IC can provide high current to our motors,
so we can use it in power-hungry applications.
You can’t use this IC on its own, you need to
provide supporting capacitors and diodes, so I
find it a lot more convenient to use a break-out
board that contains the L298N, such as the
one in this image.

You can get these devices fully assembled and ready to use on eBay for a couple of dollars.

Here’s the schematic of the circuit we are going to build:

4
Peter Dalmaris Lecture 20 Arduino Step by Step

!
!
And here’s what the assembled
circuit looks like:

!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
BEWARE! I was not able to find an appropriate part in the software I use to create the
circuit diagrams (Fritzing) for the L298N break-out board, so I am approximating it with this
basic black device containing 11 pins. From left to right, the pins on this mockup device
are:

1 2 3 4 5 6 7 8 9 10 11

Out1 Out2 Out3 Out4 In1 In2 In3 In4 12V+ Gnd 5V+

!
Try to match these pins against the marked connectors in your break-out board and you
should be ok.

I’ll explain what the role of each pin is on the break-out board now.

Out1 and Out2 control the speed and direction of motor 1. Out3 and Out4 control motor 2.
As we are using DC motors, the higher the voltage differential between the pins in those
pairs, the faster the motors will spin. If you want to reverse the motors, you must change
the polarity of these pins. This is something that the L298N will do for you with the
appropriate signal in the input pins.

5
Peter Dalmaris Lecture 20 Arduino Step by Step

In1 and In3 control the direction of spin for motor 1 and motor 2 respectively.

In2 and In4 control the speed for each motor.

Pin 9 receives +12V or higher


from an external power source.
In the schematic, I show two 9V
batteries is series, to give us a
total of 18V. Alternatively, you
could use an external power
supply.

Finally, pin 10 is for ground, and


should be connected to one of
Arduino’s Gnd pins so that both
the Arduino and the break-out
board are grounded together.

Ok, enough with the preliminary,


let’s put this circuit together, and
also look at the sketch!

[VIDEO]

!
!

6
Peter Dalmaris Lecture 20 Arduino Step by Step

Sketch for Demo 1


Here’s the sketch for Demo 1.

!
//Arduino PWM Speed Control:
int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;

void setup()
{
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
}

void loop()
{
int value;
for(value = 0 ; value <= 255; value+=1)
{
digitalWrite(M1,HIGH);
digitalWrite(M2,HIGH);
analogWrite(E1, value); //PWM Speed Control
analogWrite(E2, value); //PWM Speed Control
delay(30);
}
}
!
We start by setting the digital pins for the motor 1 and motor 2 control. We need two pins to
control each motor. The “M” pins control the direction of rotation for the motor shafts, and
the “E” pins control the speed.

In the setup() function we set the mode for pins M1 and M2 to be output (so we can control
the direction of the spin).

In the loop() function, we have a “for” loop that cycles from 0 to 255, so it covers all the
possible PWM values that can be written to pins E1 and E2 (Arduino pins 5 and 6
respectively).

Every time that the block in this loop runs, we first set the direction of spin for both motors
by writing a HIGH value to pins M1 and M2 (Arduino pins 4 and 7 respectively), and then
we set the spin by using the PWM function analogWrite. The value we write to these pins
is controlled by the “for” loop.

Once you connect this circuit and run the loop, you will have your motors starting from zero
speed, speeding up gradually until they reach their maximum rotational speed, before they
suddenly stop to a halt and then repeating the same processes again, until power is
switched off.

7
Peter Dalmaris Lecture 20 Arduino Step by Step

To change the direction of rotation, just change the value you write to either M1 or M2 pins
to LOW, and upload the sketch. You will see the corresponding motor shaft moving the
opposite way compared to the original sketch.

Easy!

!
Demo 2: Control speed and direction with a
potentiometer
The circuit for demo 1 is interesting but
not very useful. It would be great if we
could control both the direction and the
speed of rotation of our motors, right?

That’s what we’ll do now. We’ll use a


potentiometer in two ways:

• First, when we turn the knob, the


motors will turn faster or slower.

• Second, we’ll modify our sketch so


that with the same potentiometer we
can control both the direction of spin
and the speed of our motors.

Here’s the demo 2 circuit (right).

The only difference to the demo 1 circuit


is the addition of the rotary
potentiometer. It is connected to the 5V and Gnd columns on the breadboard, and to
analog pin 0 on the Arduino.

!
!
!
!
!

8
Peter Dalmaris Lecture 20 Arduino Step by Step

Sketch for Demo 2, version 1: control speed with a


potentiometer
!
Here’s the first sketch for Demo 2. This sketch allows the control of only the rotational
speed of the two motors:

!
//Arduino PWM Speed Control:
int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;
!
void setup()
{
Serial.begin (9600);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
}
!
void loop()
{
int potentiometerVal = analogRead(A0);
Serial.println(potentiometerVal);
move_motors(potentiometerVal);
}
!
void move_motors(int potValue)
{
int mappedVal = map(potValue,0,1023,0,255);
digitalWrite(M1,HIGH);
digitalWrite(M2, HIGH);
analogWrite(E1, mappedVal); //PWM Speed Control
analogWrite(E2, mappedVal); //PWM Speed Control
delay(30);
}
!
I have highlighted the changes and additions from the sketch in Demo 1 in red.

In the loop() function, we take a reading from analog pin 0 where the middle pin of the
potentiometer is connected. We then call the function move_motors and pass the
potentiometer reading to it. Inside move_motors, we simply map the potentiometer reading
(which comes in the range of 0 to 1023) to a value between 0 and 255 (which is the range of
valid values for the PWM pins), set the direction of rotation for the two motors using the
digitalWrite functions, and set the speed using the PWM function analogWrite to be
mappedVal (which in turn is relevant to the value we set by turning the potentiometer).

Upload this sketch and turn the knob of the potentiometer back and forth. See how the
speed of the motors change accordingly?

9
Peter Dalmaris Lecture 20 Arduino Step by Step

!
Sketch for Demo 2, version 2: control speed and
direction with a potentiometer
!
There’s one more thing to do, and that is to also be able to control the direction of rotation
of the motors, not just the speed. What I’d like to do is to be able to accelerate the motor
towards one direction when I turn the knob of the potentiometer towards the left, and to the
opposite direction when I turn the knob towards the right. Schematically, this is what I
would like to achieve: The red circle represents the potentiometer knob, and the black
shows movement of the knob towards the left or the right.

!
!
! Motors move Neutral - Motors move
! anti-clickwise motors don’t clickwise
! move
!
!
!
!
We are only going to make an adjustment to the sketch to make this happen, no need to
modify the circuit at all.

Here is the modified sketch:

!
//Arduino PWM Speed Control:
int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;
!
void setup()
{
Serial.begin (9600);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
}
!
void loop()
{
int potentiometerVal = analogRead(A0);
Serial.println(potentiometerVal);
move_motors(potentiometerVal);
}
!
void move_motors(int potValue)

10
Peter Dalmaris Lecture 20 Arduino Step by Step

{
if (potValue < 512)
{
int mappedVal = map(potValue,0,512,0,255);
//Going forward
digitalWrite(M1,HIGH);
Block 1
digitalWrite(M2, HIGH);
analogWrite(E1, mappedVal); //PWM Speed Control
analogWrite(E2, mappedVal); //PWM Speed Control
delay(30);
} else
{
//Going backward
int mappedVal = map(potValue-512,0,512,0,255);
digitalWrite(M1,LOW);
digitalWrite(M2, LOW); Block 2
analogWrite(E1, mappedVal); //PWM Speed Control
analogWrite(E2, mappedVal); //PWM Speed Control
delay(30);
}
}
!
I have highlighted in red the part of the sketch that has changed from the script in demo 2.
In the move_motors(int pot_value) function, potValue, the value read from analog pin 0
where the potentiometer is connected, is tested using the if function. If potValue is less than
512, then the first block is executed, if not then the second block is executed.

In block 1 and 2, the motor control functionality from demo 2 is repeated with the difference
that now we now need to recognise that the potentiometer’s range of outputted values is
divided to two parts. The first part, from 0 to 512, is used for moving the motors towards
one direction, while the second one, 513 to 1023, moves the motors towards the other
direction.

So, we need to adjust the code so that the new range of the potentiometer is taken into
account. In Block 1, the range from 0 to 512 is converted to the PWM range of 0 to 255. In
Block 2, potValue values are from 513 to 1023, still 512 possible values, so the range is
effectively the same as with Block 1, except that we need to make an adjustment to
potValue by subtracting 512 from it so that the value that the map function evaluates nicely
fits within this range.

The only other difference between these two blocks is that in Block 1, a HIGH is written to
M1 and M2, while in Block 2 we write a LOW, therefore spinning the motors towards the
opposite direction.

Go ahead, try it.

If you are having any difficulty understanding what is going on in Blocks 1 and 2,
experiment with the sketch. Try changing the map function values to something different.
For example, in Block 2, instead of map(potValue-512,0,512,0,255) try map(potValue,

11
Peter Dalmaris Lecture 20 Arduino Step by Step

0,512,0,255) and upload the sketch. What happens to the rotational speed of the motors?
Perhaps you could try this too: map(potValue,512,1023,0,255). Upload and compare to the
previous two versions. Any difference in behaviour? Can you explain any differences or
similarities?

Demo 3: Control speed with a distance sensor


By now, you have learned how to control a motor through code, and through an external
controlling device like a potentiometer. The sketch would look much the same if you used a
simple joystick instead. You can see how from a humble beginning you can start branching
out and experimenting with different types of hardware, gradually reaching more interesting
and capable configurations.

We’ll do one last experiment for this lecture. We will connect an ultrasonic distance sensor
in the place of the potentiometer, and use that to control the rotational speed of the motors.
The idea is this: The distance sensor will tell the Arduino how close it is to an obstacle. If it
gets too close, it will start slowing down the motors, effectively slowing down our prototype
vehicle. Otherwise, it will forge ahead full speed.

Here’s the schematic:

!
!
!
!
!
!
!
!
!
!
!
!
!
!

12
Peter Dalmaris Lecture 20 Arduino Step by Step

!
Have a look at Lecture 11 if you need a reminder on how to connect the ultrasonic distance
sensor. This sensor uses 4 wires, two for power (5V and Ground), one for the Trigger pin,
and one for Echo. Connect those wires as shown in the schematic, and upload the
following sketch:

//Arduino PWM Speed Control:


int E1 = 5;
int M1 = 4;
int E2 = 6;
int M2 = 7;
!
#define trigPin 13
#define echoPin 12
!
void setup()
{
Serial.begin (9600);
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
!
void loop()
{
long duration, distance;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
!
move_motors(distance);
}
!
void move_motors(int distance)
{
if (distance >= 50 ){
Serial.print(distance);
Serial.println(" cm - 255");
digitalWrite(M1,HIGH);
digitalWrite(M2, HIGH);
analogWrite(E1, 0); //PWM Speed Control
analogWrite(E2, 0);
delay(30);
}
else {
int mappedVal = map(distance,0,50,0,255);

13
Peter Dalmaris Lecture 20 Arduino Step by Step

Serial.print(distance);
Serial.print(" cm - ");
Serial.println(mappedVal);
digitalWrite(M1,HIGH);
digitalWrite(M2, HIGH);
analogWrite(E1, 255-mappedVal); //PWM Speed Control
analogWrite(E2, 255-mappedVal); //PWM Speed Control
delay(30);
}
}

Much of this code, at least the part in the loop() function, has been taken from the sketch in
Lecture 11. It generates the ping pulse that is emitted by the sensor, and then calculates
the distance of an object from the time it takes for the echo to return.

Once the distance is calculated, the move_motors function is called, and the distance is
passed as an integer parameter. Just like in Demo 2 Version 2, motors are moved in one of
two ways: if distance is 50cm or less, the motor speed is proportional to the distance. The
smaller the distance is, the smaller the speed. Otherwise, if the distance is over 50cm, then
motors will move at their maximum speed.

If these motors were part of a fully assembled vehicle, the effect of this sketch would be
that the vehicle would be capable of avoiding hitting an object by slowing down on
approach, until it came to a full stop.

Upload the sketch and play with it to get a sense of it in “real life”. Try to imagine how it
would behave in a real situation. Can you foresee any limitations? Can you imagine any
improvements?

Improvements
For example, in the current version of the sketch, the vehicle would come to a complete
stop only when the distance to a wall was 0cm. Is this sufficient? Perhaps it should come to
complete stop a bit earlier, maybe at 5cm? Or perhaps, to be even more cautious, the
vehicle should backup slightly away from the obstacle in order to provide room for a turning
manoeuvre?

Can you make changes to the Demo 3 sketch and implement these scenarios (or whatever
other improvement you can think of)?

14
Peter Dalmaris Lecture 23 Arduino Step by Step

Lecture 23
Servo motors
!
In Lecture 20, you learned about the DC motor: a versatile yet low-priced solution for
providing motion to your projects. A “weakness” (or characteristic) of the plain vanilla DC
motor is that it spins like crazy, and while it does we don’t know where the shaft is or how
far it has traveled because there is no feedback provided! Once you apply power, it wants
to go as fast as it can for at long as it can!

This is great for applications were continuous movement is needed, like for propelling a
vehicle, but not when we need to be able
to generate precise movement.

But imagine building a robot that


performs surgery on humans. Some of
you may hopefully work on something
like this in the not so distant future. In
such application, precision and control
feedback is paramount. You don’t just
want to tell the motor to rotate its shaft
by 90 degrees, you also want
confirmation that it did.

!
In Lecture 20 there was a passing mention of the servo
motor. The servo motor is a spruced up DC motor
that includes circuitry for fine movement control and
feedback. In this Lecture, we will learn about how to
use this kind of motor. We will use both the build-in
servo motor library that comes standard with the Arduino IDE,
and a third party library that adds a bunch of very useful
features.

Let’s go straight to the assembly and sketches.

1
Peter Dalmaris Lecture 23 Arduino Step by Step

Demo 1a: quick start


guide
We are going to use the servo motor library
that is build-in to the Arduino IDE to start
playing with our servo motor real quickly. First,
let’s put the circuit together, then we’ll have a
look at the sketch.

This is what we are going to assemble (right).

There are a couple of things to notice here.

First, there is no motor break-out board like


the one we used in the DC motor lecture. Back
then, I said that because the Arduino cannot
provide much current, it is best to always use
an external power source to power our
motors, and that is what the break-out board
was meant to do. I did not lie back then, but
sometimes we can make an exception. In this
circuit, my servo motor is small enough to not
stress the Arduino too much. So, I decided to
plug it straight into the Arduino in order to keep things simple.

But that’s not where this decision ends. Notice the big round tube at the lower part of the
breadboard? That is a capacitor. Even though my servo motor is small, occasionally in may
draw more power than what the Arduino can provide, but only momentarily, like when it
starts a new move. To counteract that, I have plugged in a capacitor between the Ground
and +5V columns. A capacitor is a reservoir of electricity, a bit like a battery that can charge
and discharge very quickly. Plugged into the circuit like this, when the servo motors starts
and draws more power than what the Arduino can provide, the capacitor will start
discharging and providing the motor the additional power it needs. Just plug in a capacitor
that is 300μF or more and you’ll be ok.

The motor itself has three wires coming out of it. Two are for power (+5V and Gnd), and one
for signal. Plug the signal wire to digital pin 9, and the other two to the +5V and Ground
columns on the breadboard.

We could try to control the servo motor through the Arduino digitalWrite functions but that
would require us figuring out the right values to write, and the timing for writing those
values. That’s too much work. We are lucky, though, because with the Arduino IDE we get
the Servo library, which contains functions that allow us to easily work with servo motors.
We’ll using this library first, and then I’ll show you an alternative third-party library that
provides additional functionality.

2
Peter Dalmaris Lecture 23 Arduino Step by Step

Demo 1a sketch
Here’s the sketch:

#include <Servo.h>

Servo myservo; // create servo object to control a servo


// a maximum of eight servo objects can be created

int pos = 0; // variable to store the servo position

void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop()
{
for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees
{ // in steps of 1 degree
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // Block 1
waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); Block 2
// waits 15ms for the servo to reach the position
}
}

!
This is one of the demo sketches that also come with the Arduino IDE. You can find it by
clicking on File —> Examples —> Servo —> Sweep.

We first declare our intention to use a servo motor by including the Servo library (“#include
<Servo.h>”), and creating the variable myservo that we use as a handle to the Servo
object (“Servo myservo;”).

In the setup function, we tell the Arduino that the control wire from our servo motor is
attached to digital pin 9 (“myservo.attach(9);”).

The work is done in the loop() function, where we use the for loop to count from 0 to 180,
and another one to count backwards, from 180 to 0. This has the effect of the shaft of the
servo motor travelling 180 degrees to one side, and 180 degrees to the other side, 1 degree
at a time, constantly.

Inside each for block, we first write a value to the motor using myservo.write(d), where “d”
is a number representing the degree to which the shaft should turn. If we want to turn it by
15 degrees, we write myservo.write(15). Simple, right?

3
Peter Dalmaris Lecture 23 Arduino Step by Step

In Block 1, we get the shaft to turn from 0 to 180 degrees, and in Block 2 to travel all the
way back to 0 degrees.

Finally, notice how we set a delay of 15 milliseconds inside each block, after a movement
has been written? We need this because it takes a bit of time for the motor to move, and we
want to make sure that any previous instruction has been completed before sending
through the next move instruction.

That was easy but not satisfying enough. I want to be able to control the servo motor my
self, instead of the Arduino being in charge. How about we try to connect a potentiometer
and use it as a controller for the motor?

Demo 1b: Control the servo


with a potentiometer
Let’s attach a rotary potentiometer, and adjust
our sketch to enable us control of the motor by
turning the knob.

Here’s the new circuit (right).

The potentiometer is attached to power, and


middle pin goes to analog pin 0 (A0) on the
Arduino.

The new sketch looks is this:

#include <Servo.h>

Servo myservo; // create servo object to control a servo

int potpin = 0; // analog pin used to connect the potentiometer


int val; // variable to read the value from the analog pin

void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
}

void loop()
{
val = analogRead(potpin); // reads the value of the potentiometer (0 to 1023)
val = map(val, 0, 1023, 0, 179); // scale it to use it with the servo (0 to 180)
myservo.write(val); // sets servo position according to the scaled value
delay(15); // waits for the servo to get there
}

4
Peter Dalmaris Lecture 23 Arduino Step by Step

Just like in Demo 1a, we include the Servo library and set pin 9 as the servo pin. In the
loop() function, we constantly take readings from analog pin 0 (A0) where the potentiometer
is attached. Because the range of values read in A0 is not the same as the values we can
send to the servo, we use the map function to scale appropriately.

Finally, we use the myservo.write(val); function to send the scaled value to the
potentiometer.

Try it out!

Demo 2: Setup and play with VarSpeedServo


The build in Servo library is good
and very simple to use. However,
there’s more we can do with the
hardware than it allows us.

For example, how fast should the


motor move from one position to
the next? What about the ability
to define a set of movements for
the motor to perform, and then
send them with a single
instruction?

To achieve functionality like that,


we need to use an external
library. I am going to show you
how to use the VarSpeedServo library, written by Korman and updated by Philip van Allen.
Thank you to both for their work and contribution!

First, you will need to get this library. Go to https://github.com/netlabtoolkit/VarSpeedServo


and look for the “Download ZIP” button.

Download it somewhere on your computer,


and double-click on it to extract the files
from the archive. You will end up with a new
folder named “VarSpeedServo-master”.

!
!
!
!
!
5
Peter Dalmaris Lecture 23 Arduino Step by Step

!
You need to rename this folder, so that its
now called “VarSpeedServo” (i.e. remove
the “-master” part.

You now need to copy this folder to the


folder where Arduino keeps its third-party
libraries. Don’t know where that is? No
problem, the Arduino IDE luckily
knows.

From the Arduino menu item, click


on Preferences. This dialog box
appears, and at the very top you
can see the Arduino folder. Go to
this folder using your Finder (Mac)
or Windows Explorer (Windows),
and look for a subfolder named
“libraries”.

Copy the VarSpeedServo folder into


the libraries folder. You are done.

Restart the Arduino IDE by closing


it and opening it up again. To verify
that the VarSpeedServo library was
imported succesfuly, click on
Sketch —> Import library, and look
for the new library. It usually goes
to the bottom of the list.

Now that we have the new library


imported, lets use it.

I’ll show you two sketches that come


as examples with this libraries that
compare exactly the two examples from
Demo 1.

The first one is the Sweep example.


Assemble the circuit you used in Demo
1a, and load the sketch on the Arduino
IDE by clicking on File —> Examples —>

6
Peter Dalmaris Lecture 23 Arduino Step by Step

VarSpeedServo —> Sweep.

Here’s the sketch:

#include <VarSpeedServo.h>

VarSpeedServo myservo; // create servo object to control a servo


// a maximum of eight servo objects can be created

const int servoPin = 9; // the digital pin used for the servo

void setup() {
myservo.attach(servoPin); // attaches the servo on pin 9 to the servo object
myservo.write(0,255,true); // set the initial position of the servo, as fast as
// possible, wait until done
}
!
void loop() {
myservo.write(180,255,true); // move the servo to 180, max speed, wait until done
// write(degrees 0-180, speed 1-255, wait to
// complete true-false)
myservo.write(0,30,true); // move the servo to 180, slow speed, wait until
// done
}

!
!
You can probably see the similarities and differences between the original Sweep sketch
and this one. We include the library and create the myservo object reference. We set the
servo signal pin to 9.

In the loop() function, we attached the servo at pin 9 to the myservo object.

We then send the first instruction to the servo by using the myservo.write function. This
looks the same as in the original Sweep sketch, except that is takes three arguments, not
just one.

It works like this: myservo.write(position, speed, wait);

The position argument accepts an integer, denoting the degree we’d like the servo to turn
to. For example, 15 degrees.

The speed argument controls how fast the movement should be. Top speed is 255, stopped
is 0, and anything is between is allowed.

Finally, the wait argument allows us to stop the program at that line and wait for the motor
to finish its movement. To wait, we make this argument “true”. If we want to just continue

7
Peter Dalmaris Lecture 23 Arduino Step by Step

running the sketch and let the servo finish its movement on its own, we make this argument
“false”.

Nice, isn’t it?

What do you think happens in the loop() function?

Let’s now connect the potentiometer, like we did in Demo 1b, and load the VarSpeedServo
example sketch titled Knob into the Arduino IDE.

Here it is:

#include <VarSpeedServo.h>

VarSpeedServo myservo; // create servo object to control a servo

const int potPin = 0; // analog pin used to connect the potentiometer


const int servoPin = 9; // the digital pin used for the servo
!
int val; // variable to read the value from the analog pin

void setup() {
myservo.attach(servoPin); // attaches the servo on pin 9 to the servo object
}

void loop() {
val = analogRead(potPin); // reads the value of the potentiometer (0 to 1023)
val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (0 to 180)
myservo.write(val); // sets the servo position according to the scaled value
delay(15); // waits a bit before the next value is read and written
}

Compare this against the sketch from Demo 1b. Isn’t it practically identical? Notice how the
sketch above also makes use of the myservo.write(val); function, with just a single
argument? The VarSpeedServo library allows you to use the familiar functions from the
build-in Servo library, so that any existing sketches you may have lying around will still
work. You get the additional functionality, as we saw in the Sweep sketch, for free!

An exercise
Can you build a circuit that contains a servo motor and three buttons? When you press button 1, the
motor moves to 60 degrees. When you press button 2, it moves to 90 degrees. When you press
button 3, it moves to 180 degrees.

8
Peter Dalmaris Lecture 24 Arduino Step by Step

Lecture 24
LCD character screen
!
Liquid crystal displays, LCD screens, are one of the most common ways for a gadget to
speak to us. They come in many different shapes, sizes, colours and prices. It is a common
and reliable technology. It is no surprise that the Arduino makes it super easy to connect to
them with a build-in library that provides several capabilities, and several modes of
operation.

In general, we can distinguish LCD


screens in two categories: character and
TFT screens.

Character screens are those that limit their


display to show character icons only. You
can write and manipulate characters in
rows and columns. Here’s an example:
[show LCD character screen image]. Their
sizes (in terms of characters), vary, but
most common are those with 2 lines, each
fitting 16 characters, or the half one at 2
lines by 8 characters.

TFT LCD screens, on the other hand, provide


you with an array of pixels on which you can
draw whatever shape you like. You can draw
text, of course, or circles, boxes, lines and
triangles, so the information you display to the
user can be a lot richer.

In this lecture I will show you how to use a


character LCD screen, and in a later lecture
we’ll look at the TFT screen.

Demo 1: quick start guide to the parallel LCD


character screen
In this first demo, I’ll show you how to connect an LCD screen to your Arduino. There are
two ways to make this connection: parallel and serial.

With a parallel connection, we connect each of the screen’s data pins to an individual digital
pin on the Arduino. The LCD screen I’ll be using is an 8-bit device, meaning that each
message from the Arduino is made up of 8 bits. This LCD screen has one pin for each bit,

1
Peter Dalmaris Lecture 24 Arduino Step by Step

so, this kind of connection will occupy 8


out of 13 digital pins on my Arduino Uno.
Not much left to connect other devices,
right?

Lucky enough, this LCD screen has a 4


bit mode. Using this mode, enables us to
only connect 4 out of the 8 data pins.
Communication will be a bit slower since
we will need to transmit the full 8 bits
over two cycles, but the difference is
hardly noticeable for most applications.

I also mentioned a serial connection


mode, right? Yes, with serial
communication the LCD screen only
needs one pin to be connected to the
Arduino, and all 8 bits will be transmitted
through that single pin. You need some
additional hardware for this to work, so I
am going to prepare a special lecture for
this topic.

Let’s move ahead and have a look at the


circuit.

In this schematic, the first pin from the left of the LCD is number one, and the last on the
right is 16.

The green wires represent the 4 data lines. From the LCD screen, pins D4, D5, D6, D7,
connect to Arduino digital pins 5, 4, 3, 2 respectively.

LCD pin 1 goes to ground, and pin 2 go to +5V. These two supply power to the display.

The potentiometer is used to control the contrast. Plug the middle pin of the potentiometer
to LCD pin 3, and the other two to power and ground, as we have done in the past.

[Show assembly and sketch video]

2
Peter Dalmaris Lecture 24 Arduino Step by Step

Sketch for Demo 1


Here’s the sketch for the circuit in Demo 1:

#include <LiquidCrystal.h> // include the library code:


!
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
!
void setup() {
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
lcd.print("hello, world!”); // Print a message to the LCD.
}
!
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
lcd.print(millis()/1000); // print the number of seconds since reset:
}

We start by including the LiquidCrystal library to our sketch. This library comes build-in with
the Arduino IDE so we don’t have to do anything to import it to our environment.

Then we declare and initialise the lcd object. The parameters that we pass to the initialiser
are the interface pins on the Arduino. The last four parameters are the data pins, and this is
how the Arduino knows that we will be using the four bit mode. The first two parameters are
the screen reset and enable pins. Have a look at the reference page for more details: http://
arduino.cc/en/Reference/LiquidCrystalConstructor

In setup(), we call the begin function and setup the screen’s number of columns and rows.
In this demo, I am using a screen with 16 columns in 2 rows. Change these numbers if you
are using a different sized screen.

Once we call the begin function, we can start sending content to the screen. So in the very
next line, we are printing the “hello world!” message, to greet the world!

In the loop() function, we make use of another function, setCursor(a,b). This function does
what you think it does: set the cursor where the next set of character will appear at a
particular column (parameter a) and row (parameter b).

And that’s how you can use a parallel LCD character screen in 4-bit mode with your
Arduino!

!
!

3
Peter Dalmaris Lecture 24 Arduino Step by Step

Demo 2: Show temperature and humidity on an LCD


character screen
!
In this second demo, we’ll add a DHT22 humidity and temperature sensor and use the LCD
screen instead of the monitor to show the readings.

Refer back to Lecture 8 if you need a reminder.

Here’s the Demo 2 schematic:

The only change compared to the


schematic in Demo 1 is the DHT sensor.
Connect +5V, and Gnd (pins 1 and 4),
and the data pin 2 to Arduino digital pin
7.

!
!
!
!
!
!
!
!
!
!

4
Peter Dalmaris Lecture 24 Arduino Step by Step

The sketch is essentially a merge of the sketch we saw in Lecture 8, and that of Demo 1 in
this lecture. Here it is:

#include <LiquidCrystal.h>
#include "DHT.h"
!
#define DHTPIN 7 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
!
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
!
void setup() {
lcd.begin(16, 2); // set up the LCD's number of columns and rows:
lcd.print("DHT test”); // Print a message to the LCD.
dht.begin();
}
!
void loop() {
float h = dht.readHumidity();
float t = dht.readTemperature();
!
// check if returns are valid, if they are NaN (not a number)
// then something went wrong!
if (isnan(t) || isnan(h)) {
lcd.clear(); // clear the screen
lcd.setCursor(0, 0);
lcd.print("Can't get reading");
lcd.setCursor(0, 1);
lcd.print("from DHT");
!
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hum: ");
lcd.print(h);
lcd.print(" %");
lcd.setCursor(0, 1);
lcd.print("Temp: ");
lcd.print(t);
lcd.print(" *C");
}
}

The only new function we use here are the lcd.clear() function, which… clears the screen so
we can write on a clean canvas.

5
Peter Dalmaris Lecture 24 Arduino Step by Step

The rest of this sketch is clear, I think. Setup the DHT sensor and the LCD screen, initialise
the objects for each sensor, start the devices, then take readings from the sensor and print
the acquired values to the screen.

Could not have been simpler!

An exercise
Can you build a circuit that contains a servo motor, an LCD screen, two potentiometers (one for the
screen and the other one for controlling the motor). As you turn the potentiometer and the servo
changes position accordingly, write the current angle on the screen. For example, if you have turned
the knob to 60 degrees, a message on the screen should show “60 degrees”.

6
Peter Dalmaris Lecture 25 Arduino Step by Step

Lecture 25
TFT LCD screen
!
The Thin-Film Transistor (TFT) liquid crystal
display screen is a member of the LCD family of
displays. TFT screens contain numerous pixels
(tiny screen elements that can be turned on an off
in order to create visible markings) organised in
rows and columns.

!
!
A TFT computer screen can contain many millions of
these pixels. In small consumer electronics, like feature
phones, there could be several tens or hundreds of
thousands.

Use a magnifying glass on your computer screen, and you


will see these tiny pixels. In this colour example, each
pixel is actually three: one for green, one for blue, and one
for red. The circuitry that controls the screen decides which ones to turn on, how bright
they should be, and how long they should stay on. The end result is rich, colourful graphics.

You can see that TFT LCD screens are far more versatile that LCD screens because there is
no restriction on the things you can display on them. While on a humble LCD screen you
can only display text, in a TFT screen you can draw anything at all.

In this example, I’m displaying a clock on my Arduino’s


TFT display shield. I’ll show you how to do this later on in
this lecture as one out of several examples.

Because TFT screens have so many pixel elements to


control, they come equipped with a screen controller IC as
part of the package. Your Arduino communicates with this
IC via a serial connection, and makes requests for shapes
to be drawn on the screen. Because the intricacies of
communicating with the screen controller can be
complicated for anyone other than the designers of the
screen, people have created libraries, like the one we saw in the servo motor lecture.
Through such libraries, the programmer can use simple instructions, like setCircle, to draw
a circle, and setStr to draw a string of text.

1
Peter Dalmaris Lecture 25 Arduino Step by Step

In this lecture I am use the first shield we play with in this course. A shield is a PCB on
which several components are mounted, with pin connectors that match exactly those of
the Arduino’s headers. You plug the shield on top of the Arduino, and you are good to go.
No wiring and no soldering is required. This greatly minimises chances of making a mistake
and breaking something, and is a good way to experiment with more complicated devices,
like ethernet adaptors, SD card readers, motor controllers, etc.

Demo 1: quick start guide


To get started, you first need to download and install the library that best matches the
screen that you have. In my case, I purchase this one from ebay: http://r.ebay.com/rlUg4W.
After a little searching around on Google, I discovered that the best matching library comes
from its manufacturer’s website at http://www.elecfreaks.com/store/color-lcd-shield-
p-462.html?zenid=d96eddbde9a0lmr9j7rkhrmmp2.

To make the library available to your Arduino project, and to get access to the example
sketches, follow the exact same procedure as you did back in the servo lecture:

1. Download and expand the archive file.

2. Once expanded, ensure that the name of the folder matches exactly the name of the .h
file inside it (the name of the folder should not contain the “.h” extension). For this
library, the name of the folder should be “ColorLCDShield”. Case is important.

!
2
Peter Dalmaris Lecture 25 Arduino Step by Step

!
!
3. Copy the folder in your Arduino’s library folder (if not sure, look at your Arduino IDE
preferences).

4. Restart the Arduino IDE.

You should now be able to see the ColorLCDScreen examples by clicking on File —>
Examples —> ColorLCDShield —> Examples.

Next, plug the shield onto the Arduino. Because of the way the the headers are build into

the Arduino, and especially the distances between the four header segments, it is really

3
Peter Dalmaris Lecture 25 Arduino Step by Step

impossible connecting the shield the wrong way without seriously damaging the shield by
bending its pins. Just play around with the shield and the Arduino to ensure you have
perfect pin alignment, and then apply some gentle force to make the two come together
securely.

Now that we have the shield installed, let upload one of the example sketches. Plug the
Arduino to your computer, go the the Arduino IDE, and click on File —> Examples —>
ColorLCDShield —> Examples —> ChronoLCD_Color.

Here’s the sketch, I am showing you only the part that is relevant at the moment:

#include <ColorLCDShield.h>



void setup()
{



/* Initialize the LCD */
lcd.init(PHILLIPS);



}

The important consideration at the moment is to figure out the type of screen controller
your screen uses. There are no external markings to help you out, and often the
manufacturer does not provide any documentation either. So most often this is a game of
trial and error. The controller will either be “PHILLIPS” or “EPSON”. Mine happens to be
PHILLIPS.

Go ahead and upload this sketch and find that it doesn’t work, edit this line to EPSON to
see if it fixes the problem.

Hopefully, a clock will appear on the screen after a few seconds:

4
Peter Dalmaris Lecture 25 Arduino Step by Step

There’s a lot happening in this sketch, so it’s better to leave it alone for now, and instead
have a look at something simple.

Leave everything connected, and load this sketch into the IDE:

#include <ColorLCDShield.h>
!
#define BACKGROUND BLACK // background color
#define C_COLOR RED // red color constant
#define M_COLOR GREEN // green color constant
!
LCDShield lcd;
!
void setup()
{
pinMode(10, OUTPUT);
analogWrite(10, 1023); //PWM control blacklight
/* Initialize the LCD, set the contrast, clear the screen */
lcd.init(PHILLIPS);
lcd.contrast(40);
lcd.clear(BACKGROUND);
lcd.setStr("STARTING", 50, 0, C_COLOR, BACKGROUND);
delay(1000);
lcd.clear(BACKGROUND);
}
!
void loop()
{
char* Str4[ ] = {"arduino 1","arduino 2","arduino 3"};
for (int i=0;i<3;i++)
{
printString(Str4[i], 15 * i,0);
}
}
!
void printString(char* toPrint, int x, int y)
{
lcd.setStr(toPrint, x, y, M_COLOR, BACKGROUND);
}

Upload it, you should see this on the screen:

The sketch starts by including the LCD library. Then, we create (“define”) three constants. A
constant is simply a name that we give to a value, so that when we need to use it later, we
can just use it by referring to the name. Constant also help to make code more readable,
especially when the values we assigns to them are “esoteric” data like hexadecimal or
binary values.

In this sketch, for example, we define the background color like this:

5
Peter Dalmaris Lecture 25 Arduino Step by Step

#define BACKGROUND BLACK

Notice that there is no ending semicolon (;) necessary for ending regular lines in the C
programming language (the Arduino language is really C with the added special Arduino
libraries). BACKGROUND is the name of the constant, and BLACK is its value.

At a later part of the sketch, we find a reference to this code:

lcd.clear(BACKGROUND);

Here, we are calling the clear function of the lcd object, and passing the BACKGROUND
constant reference to it. We could have written this instead:

lcd.clear(BLACK);

… and the result would be exactly the same. But consider this: the same code appears at
several places in this sketch. If at some point we decide to change the background color to
pink, we will need to find all references to the clear function and change its attribute. But
now, because we use a constant reference as an argument, we just go to the top of the
sketch, find the definition of this reference, and make the change from BLACK to PINK
there. Done!

The next line of interest is this:

LCDShield lcd;

We declare an object reference of type LCDShield. We can now use this reference, lcd, to
call all of the functions that the LCDShield object class offers.

6
Peter Dalmaris Lecture 25 Arduino Step by Step

!
In the setup() function, we configure digital pin 10, which provides power to the screens
backlight.

pinMode(10, OUTPUT);

analogWrite(10, 1023);

We set it as output, and we turn its brightness to maximum by writing a 1023 value to it. If
you would like your screen to be dimmer, just reduce the value you write to pin 10.

Next, we tell the lcd object the kind of controller chip it is talking to:

lcd.init(PHILLIPS);

In my case, my screen uses a PHILLIPS controller. Remember, that the alternative is an


EPSON controller.

We then set the contrast like this:

lcd.contrast(40);

Play with this parameter to see the effect it has on the contrast.

Finally, these two instructions change what’s shown on the screen:

lcd.clear(BACKGROUND);

lcd.setStr("STARTING", 50, 0, C_COLOR, BACKGROUND);

The first one makes everything black, since at the start of the sketch we defined the
constant BACKGROUND to be black. And then, we write our first piece of string using the
setStr function. This one takes several parameters:

lcd.setStr([text to show], [start vertical pixel - y], [start horizontal pixel -


x], [text color], [background color]);

If you wanted to write something at the top-left corner of the screen, in red, with green
background, you would do it like this:

lcd.setStr(“hello”, 0, 0, RED, GRENN);

Simple, isn’t it?

In the loop() function, we first define an array that contains three pieces of text:

char* Str4[ ] = {"arduino 1","arduino 2","arduino 3”};

Notice that the definition is “char* Str4[];”. The “char*” part tell the Arduino that the
variable that follows is a pointer (the “*” symbol) to a location in its memory were a bunch

7
Peter Dalmaris Lecture 25 Arduino Step by Step

of characters (the “char” data type) are stored. A string of text is made up of lots of
characters, hence, “char”. We then give this pointer a name, Str4, and signify that this is
actually an array by using the square brackets next to the name: “[]”.

Finally, we initialise this pointer variable to an array of strings by providing the 3 strings
inside curly brackets: {"arduino 1","arduino 2","arduino 3”}.

We iterate through this array using the for function. For each item in the array, we call the
printString function, which is defined at the end of this sketch.

The printString function accepts three parameters: the string we want to write on the string,
the horizontal (x) start position and the vertical (y) start position:

void printString(char* toPrint, int x, int y)

You may also remember that “void” means that this function does not return a value, it just
does something (like write text on the screen) and then finishes.

Inside printString, there is a single call to the setStr function, just like we saw in the
setup() function earlier.

Now you know how to write text on the screen!

8
Peter Dalmaris Lecture 25 Arduino Step by Step

Demo 2: Use the buttons


In this second demo, I’ll show you how to use the 5 buttons that are integrated into the
joystick that comes with the shield.

Here’s the sketch (continues to next page):

#include <ColorLCDShield.h>
!
#define BACKGROUND BLACK
#define C_COLOR RED
#define M_COLOR GREEN
!
LCDShield lcd;
!
int buttonPins[5] = {A0, A1, A2, A3, A4};
!
void setup()
{
/* Set up the button pins as inputs, set pull-up resistor */
for (int i=0; i<5; i++)
{
pinMode(buttonPins[i], INPUT);
digitalWrite(buttonPins[i], HIGH);
}

pinMode(10, OUTPUT);
analogWrite(10, 1023); //PWM control blacklight
/* Initialize the LCD, set the contrast, clear the screen */
lcd.init(PHILLIPS);
lcd.contrast(40);
lcd.clear(BACKGROUND);
lcd.setStr("STARTING", 50, 0, C_COLOR, BACKGROUND);
delay(1000);
lcd.clear(BACKGROUND);
}
!
void loop()
{
takeInput();
printString("Waiting...", 50,10);
}
!
void sayHello() {
char* Str4[ ] = {"arduino 1","arduino 2","arduino 3"};
!
for (int i=0;i<3;i++)
{
printString(Str4[i], 15 * i,0);
}
}

9
Peter Dalmaris Lecture 25 Arduino Step by Step

!
void printString(char* toPrint, int x, int y)
{
lcd.setStr(toPrint, x, y, M_COLOR, BACKGROUND);
}
!
void takeInput()
{
if(!digitalRead(buttonPins[0]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 0", 100, 0);
}

if(!digitalRead(buttonPins[1]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 1", 100, 0);
}

if(!digitalRead(buttonPins[2]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 2", 100, 0);
}

if(!digitalRead(buttonPins[3]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 3", 100, 0);
}

if(!digitalRead(buttonPins[4]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 4", 100, 0);
}

if(!digitalRead(buttonPins[5]))
{
lcd.clear(BACKGROUND);
printString("LAST INPUT: 5", 100, 0);
}
}

Let’s look at the differences between the sketches for Demo 1 and Demo 2.

!
!
10
Peter Dalmaris Lecture 25 Arduino Step by Step

Here’s the first one:

int buttonPins[5] = {A0, A1, A2, A3, A4};


!
Here, we declare an array that will contain references to the five Arduino analog pins that
convey the status of the five buttons that the LCD shield provides. These five buttons are
integrated into a mini joystick soldered onto the PCB, next to the screen. We could refer to
these buttons using individually declared variables, like we have done in previous sketches.
But because we have several, it is more convenient to bundle them in a single array, and
then cycle through this array in order to set them up or to read their values using and
reusing the same code.

That is what we do in the very beginning of the setup() function:

for (int i=0; i<5; i++)



{ pinMode(buttonPins[i], INPUT);

digitalWrite(buttonPins[i], HIGH); }

Here, we are cycling (looping) thew the contents of the array that contains the references to
the button pins, and first setting them as inputs, second turning on their pull up resistor.
This pull-up resistor (the opposite of the pull-down resister we saw earlier in this course),
keeps the voltage of the switch to high. When we close the switch by pressing it, the
voltage goes down, and the Arduino (guided by the code in the takeInput() function)
detects the event.

In the loop() function, we constantly call the takeInput() function and then calling the
printString function.

We have seen the printString function in Demo 1, so let’s jump to takeInput() instead.

There, we individually examine the state of each button. When you push the joystick to the
side, one of the buttons creates a connection to Ground, so the digitalRead function
returns FALSE. Using the ! operator, we inverse this FALSE value and get TRUE instead.
We the “if” function, we examine this value, and if it turns out to be TRUE, the Arduino will
continue within the block and execute any instructions in it, like to clear the screen and
write some text in it.

So there you have it, you now know how to use the TFT LCD screen shield with the
Arduino. But there is more to learn. Best learn with an exercise.

Exercise
!
Have a look at the examples that come with the ColorLCDShield library. Can you figure out
how to draw a line, a rectangle and a circle?

11
Lecture 28
Keypad
Keypads represent an intuitive way for people to
provide input to gadgets and computers. You’ll find
them in elevators, microwave ovens, TV remote
controls, phones, and countless other machines that
we interact with daily.

Sooner or later you will need to provide


alphanumerical input to your gadgets via a keypad,
and in this lecture I’ll show you how!

Keypads come in a variety of sizes and styles. Some


are using push buttons, others use touch buttons.
Some are organised in 3 rows with 3 columns each,
others with 3 rows and 4 columns, and others with 4
rows and 4 columns.

Regardless of all that, most keypads you are likely to


use in your projects consist of an array (or matrix) of
buttons, and wiring that connects them to connectors
so that when a button is pressed, a circuit closes. A
device that reads the keypad is responsible for
figuring out which key was pressed by monitoring the
state of these circuits.

Have a look at this diagram. If you press key “3”, then


a circuit that connects column 3 and row
1 is created. Current will flow through
this circuit, and some voltage differential
will be generated. The device that
receives input from the keypad will
somehow detect this differential and
determine that key “3” was pressed.

In this lecture, I will demonstrate how to


connect a common 4x4 keypad that
contains the numbers, letters “A”, “B”,
“C”, and “D”, a “*” and a “#”. I will do it
in two ways. First, I’ll use the keypad
library that comes with the Arduino IDE
in a sketch that reads the keypad, while
the keypad is connected in parallel,

1
which means that all column and row wires from the keypad are connected to 8 of the
Arduino’s digital pins.

Because this way of connecting the keypad is extremely wasteful of our precious digital
pins (the Arduino Uno only has 13), in demo 2 I will show you how to hack together a
solution that allows for a connection that uses a single signal pin.

Demo 1: easy but wasteful


In the first demo, we’ll plug a 4x4 matrix keypad
directly into the Arduino, and configure the
sketch so that the correct symbol appears
when a button is pressed.

The ugly schematic on the right represents a


keypad with 4 rows and 4 columns. It connects
to the outside world with 8 wires, four for the
rows and four for the columns on which the
keys are placed. The blue wires connect the
rows to Arduino digital pins 2, 3, 4 and 5, and
the yellow wires connect the columns to
Arduino pins 6, 7, 8, and 9.

You can see that this way of connecting a


single peripheral device is easy but very
wasteful. There’s not many pins left for sensors
or other peripherals like LCD screens or
Ethernet adaptors. So we’ll just play along for
now and understand how the keypad works
with the Arduino at it’s simplest configuration,
and then, in Demo 2, we’ll have a look at a more
real-life configuration.

Once the connections are done, the circuit depends solely on the software side to figure out
which button has been pressed and to display the right symbol in the monitor.

Let’s have a look at the sketch now.

2
#include <Keypad.h>

const byte ROWS = 4; //four rows


const byte COLS = 4; //four columns

//define the symbols on the buttons of the keypads


char hexaKeys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[COLS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[ROWS] = {6, 7, 8, 9}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad


Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup(){
Serial.begin(9600);
}

void loop(){
char customKey = customKeypad.getKey();

if (customKey){
Serial.println(customKey);
}
}

The Keypad library provides a few convenience functions that are being used in the sketch,
so we include it in the first line. I find that this library is not absolutely necessary for our
purposes, so in the second demo I am not going to use it.

Next, we declare constants for the number of rows and columns my keypad has. These
constants are used later in the keypad object constructor. A constructor is a special
function that we use to initialise an object in a program. I’ll discuss this in a bit more detail
further down.

We also need a map that assigns a symbol to each of the buttons of the keypad. We do this
by declaring a 2-dimensional array, in which each element is a character (an item of data of
type “char”). A 2-dimensional array is simply an array in which each element is another
array. In other words, think of it as “an array within an array”. To declare this array, we used
this syntax:

char hexaKeys[ROWS][COLS]

The first part is the data type of the data that the array holds in its cells, i.e. “char”. Next,
“hexakeys” is the name of the array. Finally, “[ROWS][COLS]” define the size for this array’s

3
two dimensions. Remember that at the very beginning of this sketch we defined the
constants ROWS and COLS? Well, here’s the first place were these constants are being used.

To keep things simple, in the same line we also initialise the array with the data it will hold.
We do that by using curly brackets to delimit the array’s rows, and commas for the
columns.

rows by brackets
{
{'1','2','3','A'}, columns by commas
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

Your keypad may have a different key layout, so this array is the place were you define the
mappings of keys vs symbols.

Before we can use the Keypad library, we need to define the digital pins on the Arduino
where the keypad’s row and column pins are connected. To do this, we create two arrays
that hold single bytes in each cell, rowPins[COLS] and colPins[ROWS]. Within the brackets,
we insert the values we stored in the two constants at the start of the sketch. Bytes are
integer numbers that range from 0 to 256.

We could have used the int data type to define these arrays here, but that would have been
a waste of several bytes in Arduino’s limited memory. Each int occupies 2 bytes, even
though we only need 1 to store the small numbers that represent the values reported at
digital pins we use to connect the keypad.

Finally, we can go ahead and initialise the keypad object that we will be used to get the key
presses. We give this object a name, “customKeypad”, and a type, “Keypad”. We then use a
constructor function which has the same name as the type of the object. This is not by
chance: In the Arduino language, which is standard C with added libraries, a constructor is
a function with the same name as the name of the class. We know that calling such function
will create an object for that class, store it in memory, and return a pointer (or handle) to it
so that we can use it. A class can have several constructors, each accepting a different set
of parameters. The keypad library only has a single constructor though, so this is not an
issue here (see documentation).

So, to initialise the keypad, we pass the key map array, rowPin array, colPin array, number
of rows and number of columns to the constructor.

Then, we can make use of the keypad object by calling its “getKey” function in a loop to
read any keys pressed. This is what happens in the loop() function, where the Arduino
repeatedly calls “customKeypad.getKey()”. When you press any key on your keypad, this

4
function will return something that is other than null (null is a data type that represents
nothing - which means that in C, nothing is something!).

In the next instruction, the function “if” evaluates the data that getKey returned, and if it is
not null it will evaluate it as true, causing the block within the curly brackets to be executed,
and the symbol that corresponds to the key pressed to be displayed in the IDE monitor.

So there you go, in just a few lines of code (but with many wires), you can connect and use
a keypad with your project! But can we make our hardware more efficient?

Yes we can!

5
Demo 2a: a bit of extra work, but efficient
Occupying most of the Arduino’s digital pins just for the keypad is not an efficient use of our
hardware. Although Demo 1 was simple to put together and make it work, it isn’t good
enough for practical use. In Demo 2a and 2b, we’ll improve the design so that a single pin is
used on the Arduino to transmit button pressing information.

We’ll do this using two different scripts, but the same hardware design.

Let’s start with the hardware.

Have look at the schematic. First to notice


is that there is only one wire (orange) that
connects the breadboard to the Arduino
(the black and red are for power). The
connected pin is analog 0. This is really
nice, as from the 8 digital pins we used in
demo 1 we have reduced the count to just
1!

R4
Next to notice is that the breadboard is R1
now fairly busy, with a series of resistors
and diodes arranged in rows and columns.
With the assistance of these resistors, what
we are doing is that when a button is
pressed, current flows through a unique
path that includes a unique combination of
one of the vertical resistors and one of the
horizontal resistors. The combined
resistance is unique, in the sense that no
other key press can match it exactly.
Therefore, that voltage as sampled by the
Arduino analog pin 0 will be unique for
each button. Based on that voltage, the
Arduino will be able to detect the identity of
the key that was pressed.

This table in the next page contains the


values for each resistor. When you
assemble this circuit, try to find resistors
that come close as much as possible to
these values. It is unlikely to find an exact
match because in resistors, the advertised rating is an approximation of the actual rating. In
Demo 2a, I will show you the kind of problems that this kind of imperfection creates, and in
demo 2b a way to go around it.

6
In the table below (left), R1 is the first resistance from the right in the schematic, R2 is the
next one to the left, and so on (counter-clock wise).

R1 1KΩ

R2 2.2ΚΩ

R3 3.3ΚΩ

R4 220Ω

R5 480Ω

R6 680Ω

R7 1.5KΩ

A representation of the way that resistors were connected to the keypad matrix is shown
above (right). Imagine that you press one of the keys, and that current flows through the
circuit that was just created. Only two of the resistors will be included in this circuit.
Pressing any other key will engage two different resistors, in a unique combination. So, the
voltage produced at the analog input pin will be unique to each resistor combination
engaged by each button pressing.

Therefore, it is important to pick resistors with particular values so that we can guarantee
that there are no two keys that can produce the same voltage at the Arduino’s analog input.

Next, let’s have a look at the sketch that decodes these voltages and assigns them to a
symbol.

Here’s the sketch (next page).

7
String keys=“123A456B789C*0#D"; //define the symbols on the keypad as a string
int key; //holds the index position of the key pressed
//in the keys string
boolean key_lockout=false; //Helps to prevent multiple press

void setup(){
Serial.begin(9600);
}

void loop(){
key=getKeypad(); //call the getKeypad function to see if there was
//a key press
if(key!=-1) //if there was a key press, print the key symbol
Serial.println(keys[key]);
delay(10);
}

int getKeypad(){
int ret=-1; //define the variable to hold the calculated
//key symbol position. Initialise with -1 which
//indicates no key pressed
if(analogRead(A0)==0)
key_lockout=false;
else if(!key_lockout){
delay(20);
Serial.println(analogRead(A0));
ret=15-(log((analogRead(A0)-183.9)/58.24)/0.1623)+0.5; //calculate the key symbol
//position based on a formula with ‘magic’ numbers
key_lockout=true; //‘Lock’ the key to avoid multiple key detection
}
return ret;
}

This script approaches the problem of detecting the key pressed by applying a calculation
(highlighted in red) to the voltage measured in analog pin 0. The result of the calculation is
an integer that represents an index to the keys string that contains the key symbols. So, if
you press key 1, then the voltage measured in analog pin 0 will generate a reading that
once applied to the formula, will generate an index value 0. In the keys string, the symbol at
index 0 is “1”.

The numbers in this formula are “magic” in the sense that they were calculated to
specifically match the resistors that we use in the circuit. If any of the resistors are slightly
off their advertised value, than this formula will not be able to reliably detect which keys
were pressed. Indeed, in my experiment, this happened.

Go ahead and try it your self. Some of the keys will work, but some others will not.

8
The lesson to take away is that although this solution is elegant (a single calculation
encapsulates the key detection logic), we have too many dependencies to worry about, and
that those dependencies are out of our control to calibrate (unless you have the ability to
create and solve an array of complicated differential equations).

Demo 2b: less elegance, more control


So, instead lets go for a solution that is less elegant, but allows us to calibrate our circuit for
the resistors that we have in hand. I use resistors with advertised values as in the resistor
table from the previous section, but without the expectation that they are perfect. I will
show you how to deal with the variations and how to calibrate the circuit so that key
presses are identified correctly.

char* keypressed = 0;
int keyboardPin = 0; // Analog input pin that the keypad is attached to
int keyboardValue = 0; // value read from the keypad

void setup(){
Serial.begin(9600);
}

void loop(){

keyboardValue = analogRead(keyboardPin); // read the keyboard value (0 - 1023)

while (keyboardValue < 5){ //do nothing until a key is pressed


keyboardValue = analogRead(keyboardPin);
delay(50);
}

readkeyboard(); //get the value of key being pressed "keypressed" i.e. 0-9
}

//CONTINUES IN NEXT PAGE

Sketch, part 1
I have split the sketch in two parts. In part 1 we take a reading from analog pin 0 and if it is
valid (that is, it is not less than 5 in the pin’s 0 to 1023 range1), then it will call the
readkeyboard() function that will evaluate the reading and determine which key was
pressed.

1As you will see in part 2, the lowest value we measure in analog pin 1 in my implementation was 242. This
means that instead of 5, we could set a value up to 241 in the test for valid keyboard input. None of this is set in
stone, however, so I can experiment for a while until I find values that are reliable and produce stable results.

9
//read the keyboard routine
void readkeyboard(){
keyboardValue = analogRead((keyboardPin)); // read the value (0-1023)
Serial.print("Pin value:");
Serial.println( keyboardValue);
if ((keyboardValue >842) && (keyboardValue < 845)){keypressed = "1";}
if ((keyboardValue >735) && (keyboardValue < 738)){keypressed = "2";}
if ((keyboardValue >639) && (keyboardValue < 642)){keypressed = "3";}
if ((keyboardValue >516) && (keyboardValue < 518)){keypressed = "4";}
if ((keyboardValue >474) && (keyboardValue < 476)){keypressed = "5";}
if ((keyboardValue >432) && (keyboardValue < 435)){keypressed = "6";}
if ((keyboardValue >349) && (keyboardValue < 351)){keypressed = "7";}
if ((keyboardValue >329) && (keyboardValue < 331)){keypressed = "8";}
if ((keyboardValue >309) && (keyboardValue < 311)){keypressed = "9";}
if ((keyboardValue >257) && (keyboardValue < 259)){keypressed = "0";}
if ((keyboardValue >269) && (keyboardValue < 272)){keypressed = "*";}
if ((keyboardValue >=245) && (keyboardValue < 247)){keypressed = "#";}
if ((keyboardValue >598) && (keyboardValue < 600)){keypressed = "A";}
if ((keyboardValue >416) && (keyboardValue < 419)){keypressed = "B";}
if ((keyboardValue >303) && (keyboardValue < 305)){keypressed = "C";}
if ((keyboardValue >242) && (keyboardValue < 245)){keypressed = "D";}

while (keyboardValue > 25) {


delay (100);
keyboardValue = analogRead((keyboardPin)); // read the value (0-1023)
} //wait until key no longer being pressed before continuing

Serial.println(keypressed); // print the value back to the Serial view window on your PC
delay(1000); // wait 1000 milliseconds before the next loop
}

Sketch, part 2
In the second part of the sketch, we look at the function that evaluates the input
measurement from analog pin 0, and determines which symbol matches the key that was
pressed.

The function starts with taking a fresh measurement from analog pin 0. Note that we could
have reused the original measurement that was taken while in the loop() function by passing
it as a parameter to the readkeyboard function. Maybe you can try out this modification on
your own once you get this version working properly.

The function then goes into a series of comparisons. It is trying to find a matching symbol
by evaluating the measurement against maximum and minimum values for each symbol.
These maximum and minimum values can be determined by trial and error. Here’s how it
can work:

10
In the third line of the function, we print the measured value to the monitor. Press key “1” a
few times to see what values come out. Make a note of the maximum and minimum values.
In my implementation, the output was always within the range of 842 and 845 (not
inclusive). Yours might differ. So, take these values and use them to edit the “if” statement
for value 1 accordingly. What you will have is something like this:

if ((keyboardValue >842) && (keyboardValue < 845)){keypressed = “1";}

This means that if keyboardValue is greater than 842 AND keyboardValue is less than 845,
then the key that was pressed represents symbol “1”. The operator “&&” is a boolean AND,
which means that both expressions around it must be true in order for the combined
expression to be true.

Repeat this process for every key in your keypad, then do some thorough testing to make
sure there is no overlap. An overlap would cause at least one value to be possible for more
than one key. If this happens, the Arduino would always return the last match as the
corresponding symbol.

Another thing to notice is that in my implementation, each of the keys has a tolerance of 2
or 3 units, out of 1023. This is very precise spacing between the keys, which means that we
potentially have room to decode a keyboard with more keys.

Maybe another time.

Exercise
In this lecture you learned not only about how to connect a keypad to your Arduino, but
also gained some skills in calibrating your project to match exactly your specific
configuration. You also discovered that there is a range of possible solutions to the same
problem, and that solutions differ in terms of elegance and practicality.

I think you are ready now for your most challenging exercise to date.

For this project, you will need:

1. A keypad

2. An LCD screen

3. A light intensity sensor (photoresistor)

4. A DHT22

5. An Arduino

Build a project that combines these components, and works like this:

1. If the user presses key 1, the LCD screen displays the temperature.

11
2. If the user presses key 2, the LCD screen displays the humidity.

3. If the user presses key 3, the LCD screen displays the light intensity.

4. If the user presses key A, the LCD screen will say “hello”.

12
Peter Dalmaris Lecture 33 Arduino Step by Step

Lecture 33
Ethernet
!
So far in this course, our Arduino has been capable of communicating only with its host
computer. And that communication was very limited: upload the sketch from the host
computer to the Arduino, and sent text messages from the Arduino to the computer via the
USB serial interface.

We would like to do much more with communications, and in this lecture I will show you
how to get your Arduino gadget to speak to the Internet!

There are several ways to make this work. In this lecture we will look at the Ethernet shield,
which represents the easiest (while still very capable) method. There is also Wifi, which is
technically very similar to Ethernet but wireless. I will leave wifi aside for another time.

Ethernet is the most common Local Area Network (LAN) technology around. You probably
have an Ethernet device in your home connecting your computers, printers, storage servers
etc together and to the Internet via a router.

The easiest way to add Ethernet


capability to your Arduino is via
the Ethernet shield. When this
shield was added to the
Arduino’s product line up, it
opened up a world of
possibilities: your project could
now be connected to the Internet
and be part of the Internet of
Things, an Internet where
devices are represented as
virtual objects with which people
or other objects can interact. For
example, your Internet-
connected fridge could report its temperature and alert you in case of malfunction, or you
garden watering system could log the soil humidity levels to an online logging service like
xively.com (more about this later in Lecture 38).

I personally find the Internet of Things a fascinating concept, and people come up with all
sorts of applications to show what is possible to do this Universe. Here’s some examples of
people have done: http://postscapes.com/internet-of-things-examples/

!
!
1
Peter Dalmaris Lecture 33 Arduino Step by Step

Demo 1: Quick setup


In this demonstration, I will show you how to connect your Ethernet shield, and how to
make your Arduino part of your local
network. Specifically, I will show you how
to connect to the network by automatically
acquiring an IP address via DHCP, or how
to acquire an IP address manually. For
each connection, your Arduino will report
the connection attributes in console.

You need:

• Arduino Uno

• Arduino Ethernet Shield

If you are using an Arduino Uno, then the Ethernet shield will fit perfectly on top of it. Note
that the Ethernet shield comes equipped with a mini SD-
card slot. You can use this feature to make it possible
for your sketches to read data from files (like images,
CSS files etc), or for writing data onto files. For
example, you could store output from sensors in a log
file for later processing, of for uploading to an external
service periodically.

One more thing I want to quickly discuss before moving


onto the demo is that the Ethernet shield is not strictly
needed to connect your Arduino to your LAN. Especially
if you want to deploy your completed gadget in a small
package and for a slightly smaller cost, you could choose to use an Ethernet break-out
board instead, which contains only the bare essentials for providing Ethernet functionality. I
will not discuss this breakout board in this lecture, but leave it for another time.

So, plug the shield onto the Arduino, no wiring required. This is what you end up with:

2
Peter Dalmaris Lecture 33 Arduino Step by Step

!
Done with the hardware!

Let’s have a look at the first Ethernet sketch. This sketch simply makes the Arduino a
member of the LAN and waits for someone to connect to its Telnet server. When a client
sends it a message (simple text), the server will simply send it back to the client (echo).

I will discuss several concepts related to how Ethernet LANs work rather than being
specific to the Arduino, so please bear with me if you are already familiar with them (or just
skip ahead to Demo 2).

#include <SPI.h>
#include <Ethernet.h>
!
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network.
// gateway and subnet are optional:
byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
IPAddress ip(192,168,1, 177);
IPAddress gateway(192,168,1, 1);
IPAddress subnet(255, 255, 0, 0);
EthernetServer server(23); // telnet defaults to port 23
boolean gotAMessage = false; // whether or not you got a message from the client yet
!
void setup() {
Serial.begin(9600); // Open serial communications and wait for port to open:
while (!Serial) { // this check is only needed on the Leonardo:
; // wait for serial port to connect. Needed for Leonardo only
}
!
// start the Ethernet connection:
Serial.println("Trying to get an IP address using DHCP");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
Ethernet.begin(mac, ip, gateway, subnet); // initialize the ethernet device
// not using DHCP:
}
Serial.print("My IP address: “); // print your local IP address:
ip = Ethernet.localIP();
for (byte thisByte = 0; thisByte < 4; thisByte++) {
Serial.print(ip[thisByte], DEC); // print the value of each byte of the IP address:
Serial.print(".");
}
Serial.println(); // start listening for clients
server.begin();
}

This sketch is one of the samples that come with the IDE. You can load it by going to 

File —> Examples —> Ethernet —> DhcpChatServer.

3
Peter Dalmaris Lecture 33 Arduino Step by Step

At the top of the sketch we have the inclusions of the SPI and Ethernet libraries. The SPI
library provides the functions necessary for the Ethernet shield to communicate with the
Arduino using the SPI bus. The Serial Peripheral Interface bus is a full-duplex

!
void loop() {
EthernetClient client = server.available(); // wait for a new client:
if (client) { // when the client sends the first byte, say hello:
if (!gotAMessage) {
Serial.println("We have a new client");
client.println("Hello, client!");
gotAMessage = true;
}
!
char thisChar = client.read(); // read the bytes incoming from the client
server.write(thisChar); // echo the bytes back to the client
Serial.print(thisChar); // echo the bytes to the server as well
}
}

communications standard created by Motorola to allow simultaneous two-way


communication between a master (in our case, the Arduino) and multiple slaves (for this
shield one slave is the Ethernet adaptor and the SD card). We are not going to worry about
how SPI works since the Ethernet library hides these details from us. Using the SPI library
directly is a topic for another lecture.

For a device to be a member of a LAN, it needs to have three pieces of information:

1) A MAC (Media Access Control) address, which is the physical (hardware) address of the
network controller. This is a bit like the VIN number of a car, or the serial number
marked at the back of your TV. The Ethernet protocol uses this address to figure out
which device is sending a message and who the recipient is supposed to be. The
Arduino Shield also has such an address, and it should be printed somewhere in the
packaging or on an insert sheet of paper. Look up yours and copy the information in
header of the sketch:


byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };


Can’t find your controller’s MAC address? No problem. I have also lost mine. Chances
are that if you only have one Arduino Ethernet shield in your network, you will be just
fine by using the MAC address from this example. As long as there are no two
controllers with the same MAC address, the shield will work. If you suspect there is a
conflict, just change one of the fields of the mac[] byte array. For example, this should
also work (change in red):


byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x03 };

4
Peter Dalmaris Lecture 33 Arduino Step by Step

2) The IP (Internet Protocol) address is the address that any device connected to the
Internet needs to have. The IP address is also known as “logical address” because it
can be assigned to the device dynamically, unlike something like the MAC address
which need to be hardwired or at least statically defined (which is what you did in the
previous item). In most networks, including (most likely) your own home network, there
is a service called DHCP (Dynamic Host Configuration Protocol), which makes it
possible to just plug in an IP device and have it made part of the LAN by leasing it an IP
address (among other things). In your network, if you can just plug in your computer
and access the Internet, there are 99.999% chances that your network has a DHCP
server running. In the unlikely case that you don’t, then configure your Ethernet shield
with a unique (for your network) IP address like this:


IPAddress ip(192,168,1, 177);


In my case, I had to make a change to this address (change in red):


IPAddress ip(192,168,111, 177); 


That is because my LAN has addresses in the block 192.168.111.1 to 192.168.111.255.
This information is usually defined by your home network router, so you will need to
look at its settings. There are too many variations of this scenario to cover here, so if
anyone if having problems with this, post me a message.

3) Next up is the gateway. The gateway variable holds the IP address of the device to
control access to the outside world, a.k.a. the Internet. If your Arduino needs to access
a web server or web service outside your LAN, it will need to know who to ask for
access, and that is the gateway. If there is a DHCP service running in your network,
than this is a piece of information that the DHCP will provide (I will explain how this
happens in a minute). If not, or if you just want to have a fallback, you can specify this
in this line:


IPAddress gateway(192,168,1, 1);


Again, I had to edit this setting because in my network the gateway is at a different
address (change in red):


IPAddress gateway(192,168,111, 1);


If you are on Windows, to find out your default gateway, try out this: http://
answers.yahoo.com/question/index?qid=20100221132909AA7jMQk


On Mac, look at Preferences —> Network —> (Your network controller).


Linux people, I think you already know what yours is ;-).

5
Peter Dalmaris Lecture 33 Arduino Step by Step

4) The last required network configuration is the subnet mask. Because the possible IP
addresses (and hosts) in a single network are 2 in the power of 32, we find it much
easier to split this pool of addresses in small parcels, and deal with each parcel as a
separate network. The subnet mask is the bit of information we need in order to know
how our network has been split. In the example, the default subnet mask is:


IPAddress subnet(255, 255, 0, 0);


Notice the two zeros at the end? This means this network allows 8 + 8 = 16 bits for the
host addresses, which means 2^16 hosts. That is 65,536 hosts. In my network, I have
lots of computers but not THAT many, so instead I am using this subnet mask:


IPAddress subnet(255, 255, 255, 0);


This allows me to allocate 255 IP addresses in my network. That’s enough for most
home networks, and most likely what your network is using too.

!
So that how we setup out sketch so that our Arduino becomes part of the LAN.

In the next instruction, we create an object for a server:

EthernetServer server(23);

A server is an object that constantly listens for messages send to it by clients that connect
to a particular TCP port. The parameter we specified here, 23, represents one of 65,536
such ports. We could have chosen any one of those ports, however because we will be
using Telnet in minute, it’s best to keep things simple and use the default port for Ethernet.
In lecture 34, we will setup a web server to run on the Arduino, so the default port for that
will be 80.

Because we want the server to only do something when a message is received, we declare
a boolean variable to keep track of these events:

boolean gotAMessage = false;

When a message is received, gotAMessage will be changed to true and this will be picked
by the server later on to send a copy of the message back to the Telnet client.

In the setup() function we first initialise the Serial connection to the IDE monitor, and then try
to setup the Ethernet controller. This instruction is very important:

Ethernet.begin(mac)

This tries to contact a DHCP server and lease an IP address, as well as to get information
about the gateway and subnet mask. If a DHCP server responds, then any values it
provides will be used to setup our Ethernet adapter. But, if the begin(mac) function fails (it

6
Peter Dalmaris Lecture 33 Arduino Step by Step

will return a 0 if it does), then the sketch will initialise the Ethernet adaptor by using the
default values we provided at the start of the sketch.

Once this process is complete, the sketch will print out the allocated IP address. The
function

Ethernet.localIP();

returns the IP address as an array of bytes, and in the loop that follows the sketch converts
each field in that array to its equivalent decimal:

Serial.print(ip[thisByte], DEC);

Finally, at the end of the setup() function, the Sketch starts the Telnet server:

server.begin();

Now the server is active and just waiting for a message to arrive. We test for incoming
messages in the loop() function.

First, we check that a client is attempting to connect by calling the available function of
the server object, and if there is, we assign it to a new client object of type EthernetClient:

EthernetClient client = server.available();

If the client just became connected, the greet it!

Otherwise, read the transmitted character and copy it to both the serial port, and to the
server object so that it is displayed to the user via the Telnet console.

To try out this connection, start up a console (command line) and type this1:
 

telnet 192.168.111.61

… which works for my Arduino ethernet shield, and you will probably need to adjust for
your settings. You should see something like this:

1If you are using Windows, especially Windows 7, read this article for a guide on how to enable Telnet client on
your computer: http://social.technet.microsoft.com/wiki/contents/articles/910.enabling-telnet-client-in-
windows-7.aspx

7
Peter Dalmaris Lecture 33 Arduino Step by Step

When I start typing random characters, these are echoed back to my console (to the right,
with the black background):

You can see that every character I type is copied both to the monitor using the
Serial.print(thisChar) function as well as the Telnet console using the
server.write(thisChar) function. But on the console side, every character I type appears
twice: once for my original key press, and the second for the response from the server.

Don’t worry about the text garbage that appears in the monitor. We’ll worry about this later.
For now, congratulations, you made your first Ethernet connection through your Arduino!

Demo 2: Control an LED


and read a photo-
resistor through a
Telnet connection
Echoing characters is a decent first step,
but we always want more! I would really
like to be able to control this hardware!

So in this demo I will show you how to


turn on and off an LED, and to read light
intensity through a Telnet connection to
your Arduino from your computer.

You need:

• Arduino Uno

• Arduino Ethernet Shield

• Photo-resistor

• LED

• 1KΩ resistor

8
Peter Dalmaris Lecture 33 Arduino Step by Step

• jumper wires

Let’s add the LED and photo-resistor to our circuit.

Let’s see what this we are trying to achieve with this circuit before looking at the sketch.

. . . This part is omitted because it identical to Demo 1 . . .


int ledPin = 2;
String commandString;
!
void loop() {
EthernetClient client = server.available(); // wait for a new client
commandString = "";
if (client) { // when the client sends the first byte, say hello
if (!alreadyConnected) {
client.flush(); // clear out the input buffer
commandString = ""; //clear the commandString variable
server.println("--> Please type your command and hit Return...");
alreadyConnected = true;
}
while (client.available()) {
char newChar = client.read(); // read the bytes incoming from the client
if (newChar == 0x0D) // If a 0x0D is received, a Carriage Return,
// then evaluate the command
{
server.print("Received this command: ");
server.println(commandString);
processCommand(commandString);
} else
{
Serial.println(newChar);
commandString += newChar;
}
}
}
9
Peter Dalmaris Lecture 33 Arduino Step by Step

When a user connects via Telnets, they can type commands for the Arduino to execute. In
this version of the sketch there are three commands, but you can add as many as you
want.

Type “photo”, and the Arduino will respond with a reading from the photo-resistor. If you
type “ledon”, it will turn the LED on, and if you type “ledoff” it will turn the LED off. Anything
will give you the instructions:

And now to the sketch:

void processCommand(String command)


{
server.print("Processing command ");
server.println(command);

if (command.indexOf("photo") > -1){


Serial.println("Photo command received");
server.print("Reading from photoresistor: " );
server.println(analogRead(0)); //Print the integer returned by analogRead
//to the server object
commandString = "";
return;
}

if (command.indexOf("ledon") > -1){


server.println("LED On command received");
digitalWrite(ledPin, HIGH); // sets the LED on
server.println("LED was turned on");
commandString = "";
return;
}

if (command.indexOf("ledoff") > -1){


Serial.println("LED Off command received");
digitalWrite(ledPin, LOW); // sets the LED off
server.println("LED was turned off");
commandString = "";
return;
}

commandString = "";
instructions();
}
!
void instructions()
{
server.println("I don't understand");
server.println("Please use one of these commands:");
server.println("* photo, to get a reading from the photoresistor");
server.println("* ledon, to turn on the LED");
server.println("* ledoff, to turn off the LED");
}

10
Peter Dalmaris Lecture 33 Arduino Step by Step

The first part of the sketch is identical to the one in Demo 1, except for the declaration of
the ledPin integer, which contains the pin number where the LED is connected, and the
string commandString which will hold the last command we send to the Arduino.

In the loop() function, we wait for a client to connect, just like in Demo 1. Once we have a
connection, we clear the commandString variable to get it ready to store a new command.
If a client is not already connected, i.e. a new one just got connected, the clean the input
buffer to make sure there’s no garbage from previous connections, print out a message to
the client to let them know the Arduino is ready to receive a command, and change the
alreadyConnected variable to true.

What happens next is the most interesting part of this sketch. Here it is:

Because the Telnet connection is a serial connection, whatever command we type is


transmitted to the Arduino one character at a time. The sketch must store all these
characters as they arrive but wait until a line feed or carriage return is given before it can
evaluate the command. The client.read() instruction take a character at a time and stores
it in the newChar variable. The the sketch evaluates this character. If it is something other
than a Carriage Return, it will append it at the end of the commandString variable and wait
for the next character. But if it is a carriage return (which is the hexadecimal 0D character in
the ASCII system which Telnet uses) then it will print out the command it captured and cal
the processCommand function to evaluate it.

In processCommand (next page), the sketch checks to see if the command given matches any
of the three valid commands (“photo”, “ledon”, “ledoff”). It does that by using a string
function:

command.indexOf(“photo")

The “indexOf” function checks to see if the string “photo” exists in the string stored in the
command variable. If it does, it will return a positive integer number, but if it doesn’t it will
return -1. If you want to expand the repertoire of commands for your Telnet server, just add
new blocks that test for the new commands using the indexOf function.

The content of each command block should be self-explanatory, but do ask me if


something doesn’t make sense.

Once a command is found, we want the sketch to execute whatever code is in its block and
then continue listening for new commands instead of trying to match. That is why we
include the return statement at the end of every block: we want to stop the command
evaluation there.

If none of the commands available match the command we issued, the Arduino will call the
instructions function which will print out a set of instructions.

Simple!

11
Peter Dalmaris Lecture 33 Arduino Step by Step

So what did you learn in the lecture? Quite a lot! You got through the fundamentals of
connecting a host to an Ethernet LAN and to the Internet, and you learned about getting the
Arduino connected to your LAN. But most important, you learned about controlling simple
components connected to your Arduino using Telnet. It only takes one more step to
connect to your Arduino using Telnet from the Internet, which will allow you to control your
LED, your motors, or whatever else is connected to it from anywhere in the world. That’s
the Internet of Things!

You can do this by making a configuration change to your home router and enable port
forwarding. Wikipedia has a good article to help you understand what this is, and this web
site contains an extensive list of modem/routers with specific instructions for each model.
Hopefully your’s will be in this list. In a nutshell, port forward allows a user from the Internet
to access a server running inside a LAN without exposing this server to the Internet.

Exercise
I hope you are feeling excited now! How about you try out these exercises to stretch your
skills a little more

1. Add a DHT22 to your Demo 2 setup, and extend the repertoire of commands of the
Telnet server so that it also returns the temperature and humidity.

2. Add an LCD screen which displays the IP address of your Arduino when it starts up and
connects to the network. Once connected, the LCD screen displays the commands it
receives from the Telnet client.

12
Peter Dalmaris Lecture 35 Arduino Step by Step

Lecture 35
A simple reporting web server
!
The Web is an open and well understood technology for disseminating information.
Equipped with an Ethernet shield, your Arduino can host a simple web server to which
clients can connect and interact with.

In the simplest of cases, an Arduino web server will be used to report readings from its
sensors to whomever is asking. In this lecture, we’ll look into the scenario of using a web
server running on the Arduino that reports values from its sensors. We will do this reporting
in two different modes: First, for humans to view using HTML, and second for machines to
read where the data reported will be formatted as simple comma separated values.

Before we get started with the demos, let’s go through a really quick discussion on running
a web server on the Arduino.

!
Principals of Arduino web servers
!
The Arduino is a remarkable piece of hardware, but it isn’t build to be a full blown web
server. It has a single tiny processor with very limited memory when compared to build-for-
purpose web servers. And this processing power is really optimised for dealing with
sensors and input/output components, not with the kind of processing that a web server is
required to do.

Another limitation is the programming language. The Arduino language is standard C with
added libraries, like the Ethernet library we saw in lecture 33. It is a bare-minimal language
that is fairly close to the hardware so that it can be compiled efficiently for the AtMega
micro-controllers, and as a result it doesn’t have the kind of programming “sugar” that high-
level languages like Ruby and PHP have. This “sugar” makes it a lot more easier for
programmers to build elaborate web applications with relative ease when using, for
example, Ruby, as opposed to C.

For example, take images. A jpeg image you might find in a simple web site may be 15 or
20Kbytes. The Arduino Uno only has room for 32KBytes in its RAM, so the image will not fit
and we will need to store it in an SD card or on another web server and make a reference to
it from the Arduino sketch.

What about SSL encryption? This is a standard feature for most non-trivial web sites these
days, but the Arduino simply does not have the computational power required to support
SSL.

These reasons, in a nutshell, require that any server we host on an Arduino, be it a web
server, a telnet server, or anything else, has to be minimal.

1
Peter Dalmaris Lecture 35 Arduino Step by Step

!
Minimal, because we don’t have much memory to spare, because programming anything
more complicate will take a lot of programming efforts, and because we want to maintain
CPU resources for sensing and control, rather than reporting.

However, with all that said, it is possible to interface the Arduino with a more capable
computer and offload to that computer the more elaborate features we would like to enrich
our Arduino-power web site with.

Here is a possible architecture for something like this:

!
!
With this kind of arrangement, you use the Arduino for sensing and control. You also have a
very simple web server running on it, like the one we’ll see in this lecture. But instead of
opening it up to the whole world, you allow only a single client to connect to it. The green
device in the middle of this schematic is a Raspberry Pi, a single board computer that costs
around $45. Yes, this is an actual computer which can run Linux, and that means that you
can have a full-blown web server on it build with a high-level language. You can build your
application on the Raspberry Pi (or similar) so that clients from the Internet will connect to it,
and use it as a proxy for your Arduino. This architecture makes it possible and easy to have
an Arduino-powered web site with SSL, graphics, CSS, and all the bells and whistles to
which we are accustomed.

Showing you exactly how to do this, is a topic for another lecture though. Just know that it
is possible for the time being.

With these points in mind, let’s go ahead and have a look at an Arduino bare-minimal web
server.

!
Demo 1: The essential Arduino web server
In this Demo, I’ll show you how to setup a basic reporting web server on your Arduino. We’ll
look at the simple web server from one of the examples that come with the IDE. In Demo 2
we’ll make a few changes to it so that it reports data from a humidity/temperature sensor,
and a photo-resistor.

2
Peter Dalmaris Lecture 35 Arduino Step by Step

To assemble the hardware, just plug the Ethernet shield on the Arduino. The sketch we will
play with takes measurements from the analog pins and shows them in a web page. You
can connect whatever analog sensors you have handy, but that is not necessary. In the
absence of actual sensors providing readings, the values on the analog pins will be random.
To load this sketch, go to File —> Example —> Ethernet —> WebServer.

#include <SPI.h>
#include <Ethernet.h>
!
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);
!
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
!
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
!
!
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

This block of the sketch is familiar: it is identical to the definition and setup parts of the sketch in
Lecture 33. It sets up the Ethernet connection and a server. The only difference is that in this sketch,
the server will be listening for connections on TCP port 80 (highlighted in red).

!
The next block is a lot more interesting. It is there where the parsing logic of a web server is
implemented. Have a quick read but don’t spent too much time on it for now. There is something
else I should show you first before the parser can make sense.

!
!
!
!
… sketch continues next page …
!
!
!
3
Peter Dalmaris Lecture 35 Arduino Step by Step

void loop() {
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
boolean currentLineIsBlank = true; // an http request ends with a blank line
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed
//after completion of the response
client.println("Refresh: 5"); // refresh the page automatically
// every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}

4
Peter Dalmaris Lecture 35 Arduino Step by Step

!
Parsing a HTTP request
Web pages travel from web server to web client on top of HTTP: the Hyper Text Transfer
Protocol. This protocol has certain rules which web servers and clients must abide by if
they are to work together. A web server or client parser is a computer program that knows
how to understand HTTP. When your web browsers send a request to a web server, it
makes a HTTP request.

Lets have a look at what a HTTP request looks like first.

I’ll use Requestbin, requestb.in, a website that shows me the bare content of a HTTP
request, a kind of X-ray vision for the Web. Visit this site, and you will see this:

Click on the green button, this will create a RequestBin for you, which is a URL to which
you can send an HTTP request.

Go ahead, create a new RequestBin.

5
Peter Dalmaris Lecture 35 Arduino Step by Step

As a response, you will see something like this (next page):

!
In the Bin URL box, you have exactly that, a URL to which you can send HTTP requests.

In a new window or tab of your web browser (keep the page above handy), copy/paste the
URL in the Bin URL box, and hit Enter.

You will get something like this:

!
!
This just means that RequestBin received your HTTP request. Now go back to the tab or
window that contains the Bin URL box and refresh it. You will see something like this:

(see next page)

6
Peter Dalmaris Lecture 35 Arduino Step by Step

!
What you see here are the raw contents of your HTTP request. In the red box, I have
highlighted the most important part of this request for our present discussion: It is the first
line that your web browser trasmitted to the server. It starts with a verb, in this case “GET”,
and a path for the resource that was requested, in this case pebptxpe.

There are other bits of information provided here, like in the headers section.

All this is text that the Arduino will have to parse in order to correctly respond to a client’s
request.

Back to our first example now…

Our Arduino sample web server sketch is only programmed to identify the end of a client
HTTP request, and then to send out its HTTP response.

7
Peter Dalmaris Lecture 35 Arduino Step by Step

According to the HTTP protocol, a HTTP GET request must end with a blank line. In the box
below, you can see the complete HTTP GET request, and the last blank line.

GET / HTTP/1.1

Host: 192.168.111.177

Connection: keep-alive

Cache-Control: max-age=0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36


(KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36

Referer: http://192.168.111.177/

Accept-Encoding: gzip,deflate,sdch
blank line
Accept-Language: en-US,en;q=0.8,el;q=0.6

!
This blank line is identified by this statement in the sketch:

if (c == '\n' && currentLineIsBlank)


!
This means: “if the current line is blank and the current character is a new line”, then the
expression is true, so the sketch will go ahead and print its response.

The boolean currentLineIsBlank is there to keep track of new lines: when a new line
character is found (“\n”), then currentLineIsBlank becomes true. When anything else is
found, it becomes false. This is happening in this code block:

if (c == '\n') {
currentLineIsBlank = true;
} else if (c != '\r') {
currentLineIsBlank = false;
}
!
So, the Arduino, will know that the HTTP request is finished if it finds two new lines (“\n”)
are found, one right after the other.

You may need to read these last coupe of pages a few times before you continue, but
before doing that, consider this: we did all this just so that we can detect when a HTTP
request has finished so that the server can respond. We haven’t done any serious parsing
yet!!!

8
Peter Dalmaris Lecture 35 Arduino Step by Step

Creating the response


This request is more like a trigger, it asks the server to send back whatever it wants to send.

For the server to send a response back, it needs to be formatted in accordance with the
HTTP rules. A response needs to start with a response header, followed by the response
body.

This code implements the response header:

client.println("HTTP/1.1 200 OK");

client.println("Content-Type: text/html");

client.println("Connection: close"); // the connection will be closed after completion of the


response

client.println("Refresh: 5"); // refresh the page automatically every 5 sec

client.println();

In the first line, the server sends a “200” HTTP code, which tells the client that it understood
its request and there is no problem to worry about. Always nice to hear that!

Next line informs the client of the type of content that will be following in the body of the
response. In this case, it will be HTML text.

Next, the server tells the client that once it sends what it has to send, it will close the
connection. If the client needs something else, it will have to initiate a new connection via a
new HTTP request.

Next line contains a “non-standard” instruction. “Refresh” tells the browser to send a new
GET request to the server in order to get an updated page. Most browsers are able to
understand this instruction, even though it is not a standard HTTP instruction.

Finally, the server prints a new line. Don’t forget that! In order for the client to know that the
HTTP response header has completed its transmission, there has to be a blank line!

The body of the response follows, and the Arduino will construct the HTML for it line-by-
line. Here’s the code for this:

client.println("<!DOCTYPE HTML>");

client.println("<html>");

// output the value of each analog input pin

for (int analogChannel = 0; analogChannel < 6; analogChannel++) {

int sensorReading = analogRead(analogChannel);

client.print("analog input ");

client.print(analogChannel);

client.print(" is ");

client.print(sensorReading);

client.println("<br />");

client.println("</html>");
9
break;
Peter Dalmaris Lecture 35 Arduino Step by Step

The first bit of text printed to the client stream is the HTML declaration. This is not actually
an HTML tag, but an instruction to the browser informing it about the version of HTML used
in the page that follows.

The actual HTML follows. You can see that there is a “for” loop that samples the analog
ports, and the prints out their captured values to the client stream.

When the loop ends, we close the HTML page.

Finally, there is a break statement. This breaks the while loop that started with the “while
(client.connected())” instruction earlier. The sketch is about to close the connection by
calling the stop() function of the client object, but before doing so it waits for 1 millisecond
for the client to finish receiving the response.

Upload the sketch and fire up your browser. Visit your Arduino’s web site, and this is what
you should see:

I have not connected any sensors to the analog ports, so the values you see here are
random.

With this detailed discussion on getting a web server running on the Arduino for simple
reporting, let’s go ahead and try out a simple modification from this basic example sketch.

Lets connect a humidity and temperature sensor, and a photo-resistor, and report the
values they report through our web server using HTML and CSV. The HTML will be useful
for humans, while the CSV is more machine-friendly.

10
Peter Dalmaris Lecture 35 Arduino Step by Step

Demo 2: Practical reporting for humans and


machines
!
In this demo, I would like to use my trusty DHT22 and photo-resistor sensors. I would like
to be able to use my web browser and get readings from the sensors like this:

If a machine makes the same request, I would like it to receive this response instead:

The two sketches that correspond to these


two scenarios are almost identical. The only
difference is that one outputs HTML, while
the other one outputs text as comma-
separated values.

Here’s the hardware schematic:

It includes the DHT sensor connected to


digital pin 2, and a photo-resistor with a
10KΩ resistor as voltage divider connected
to analog pin 0.

Have a look at the HTML version of the


sketch in the next page.


11
Peter Dalmaris Lecture 35 Arduino Step by Step

… first part of this sketch is omitted because it is identical to Demo 1 …


void loop() {
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 5");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
int sensorReading = analogRead(0);
client.print("analog input ");
client.print(0);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
}
else {
client.print("Humidity: ");
client.print(h);
client.println("<br />");
client.print("Temperature: ");
client.print(t);
client.print(" *C");
client.println("<br />"); }
client.println("</html>");
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
delay(1);
// close the connection:
client.stop();
Serial.println("client disonnected");
}
}
! 12
Peter Dalmaris Lecture 35 Arduino Step by Step

!
What is new in the sketch compared to the one in demo 1 is highlighted in red. The new
sketch just takes readings from the DHT sensor and from the analog pin 0 and prints them
out in the client stream.

What about the CSV version of the sketch?

Just replace the red block with this:

int sensorReading = analogRead(0);


client.print(sensorReading);
client.print(",");
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(t) || isnan(h)) {
Serial.println("Failed to read from DHT");
}
else
{
client.print(h);
client.print(",");
client.print(t);
}

We removed any printouts of HTML tags, and add commas to delimit the values.

Although it is out of scope for this lecture, it is worth mentioning that for transmitting simple
values like the numbers in this example, the CSV format is a very efficient of going about
sending data from one machine to the other.

Conclusion
You covered a lot of ground in this lecture. You learned about how HTTP requests are
structured, and how the Arduino can host a very simple reporting server. There were a lot of
details involved, but what I think would be most useful to remember is the fact that a web
server is essentially a parser of text which interprets HTTP requests and responses.

Although the examples in this lecture did not do much parsing other than figuring out where
a HTTP request ends so that a responds can be sent, what you learn will prove very useful
in the next lecture. In that lecture, you will learn about creating a server that parses a
request so that it can find out the specific parameters of what is it that it is being requested
to do. You will learn, for example, how to get the server (i.e. the Arduino) to turn on the LED
at pin 9. I call this kind of server “controlling”, because it allows you to control the Arduino
via the web, not just to get readings of its status.

!
13
Peter Dalmaris Lecture 35 Arduino Step by Step

Exercises
Try to add a couple of sensors of your choice to the HTML version of the Demo 2 sketch.
Adjust the sketch so that the values are printed nicely to the client. If you have CSS skills,
perhaps improve the looks of the output by incorporating some styling to the page that the
Arduino generates.

14
Peter Dalmaris Lecture 37 Arduino Step by Step

Lecture 38
A simple controlling Arduino web server
!
In Lecture 35, you learned about the basics of parsing HTTP requests and you implemented
a simple web server. I referred to that web server as “reporting” because it was build to only
report the values of pins on the Arduino but did not offer any way of changing their state.

In this lecture, I will show you how to setup a web server on the Arduino that does just that.
A user will be able to connect to the Arduino using their web browser and turn LEDs on and
off. You could replace the LEDs for other devices, like motors, without having to introduce
significant changes to the sketch we’ll see here. We will actually do this in the next lecture
on web-based motor control.

Just like in lecture 35, we first need to look at the HTTP request parsing issues that we will
need to deal with before implementing the controlling web server sketch. Because the web
browser will be sending information with instructions to the Arduino, the Arduino’s web
server HTTP parser will have a lot more work to do.

Let’s go through the demo, and start by looking at how HTTP deals with data going from
the client to the server.

Demo: controlling LED via HTTP


Sending data to a web server can be done in two ways: “GET” and “POST”.

Parsing a GET request


Simply speaking, in a GET request, the data that you want to send, travels to the server as
part of the URL. When you go to your browser’s URL field, type in a URL like “google.com”
and hit the Enter key, you are triggering an HTTP GET request.

So, here is an example. If I want to sent a message to my Arduino asking it to turn the LED
in pin 8 on, I could put this in the URL:

http://192.168.111.177/?pinD8=1

In this example, you can recognise the first part of the URL, in black. It is simply the
protocol followed by the IP address of the web host, which is my Arduino. After the slash,
there is a green question mark “?”. I am using this character as a marker for the location in
the URL where the instructions I want to sent begin. The parser running on my web server
on the Arduino will be looking out for this special character and once it finds it, it will start
looking with great interest for whatever follows.

The part in red is the actual instruction. I have chosen to keep things very simple, and use a
protocol that provides me some flexibility for future changes of the parser as my
requirements change. In the current iteration, my protocol says that a command should

1
Peter Dalmaris Lecture 37 Arduino Step by Step

start with the three characters “pin”, followed by an integer, followed by an equal sign “=“,
followed by another integer. Once the parser in the web server encounters the “?”, it will
then start looking for the “pin” instruction. Whatever character comes next will signify the
type of pin we want to manipulate. After that is an integer which signifies the pin number
that we want to manipulate. And finally, after the “=“ character, any integer that the parser
finds signify the value that we want to write to this pin.

In the example above, I am asking the web server to write value “1” to digital (“D”) pin 8. If I
wanted to write value 32 to analog pin 2, according to my protocol, I would issue this URL:

http://192.168.111.177/?pinA2=32

Simple, right? The current version of the sketch that is published on Github only supports
the first example, but later on we will discuss the parser itself and you will see that
changing it to accommodate the second example is very easy.

Now, let’s have a look at the raw information that travels to the Arduino’s web server. This
will help us figure out exactly what is it that the parser will need to work with. To look at the
raw contents of the GET request, I’ll use Chrome’s “Inspect Element” feature. We first had a
look at this really nice tool in Lecture 33.

This is what I see:

2
Peter Dalmaris Lecture 37 Arduino Step by Step

To access the source of the GET request, go to any page, right click anywhere on the page,
and select Inspect Element. Then, click on Network. Click on a link on the page to trigger a
GET request, and observe how several new rows are added to the box in the right side of
the Inspect Element pane. Each one represent an HTTP request. Click on any of them to
get the request’s details. The Request Headers section displays a nicely formatted view of
the information that the GET request transmitted to the server. This view is nice, but we
want to know EXACTLY was is it that the web server received, so click on “view parsed” to
switch to the raw view of the headers.

What you see now is what the server sees. In the case of my example, notice that the first
line (in the blue box) contains the word “GET”, which is the HTTP verb for this kind of
request, followed by “/?led8=1”. This matches the second part of the URL I typed in the
browser, right?

Well, yes, this is the simplest way to transmit data with instructions to the server. The parse
can ignore anything else below the first line (unless it is interested to know, for example,
who is sending the request, what kind of browser is used, etc.).

Parsing a POST request


An alternative to post, is to use the POST HTTP method. This method transmits the user
data to the server in the body of the message instead of the URL. This is nice in case you
don’t want your user to be able to see exactly what is being transmitted. It is also preferable
if you have lots of data to transmit, since the number of characters you can fit in the URL is
limited. Let’s have a look at a POST request and spot the differences between it and a GET
request.

To switch my example from using the GET method to using the POST method, I change the
“form” HTML element “method” attribute to “POST”:

<form action="http://requestb.in/16pydf71" method="POST" target="_blank">

<input type='hidden' name='pin8' value='0'><input type='submit' value='Off'/>

</form>

<form action="http://requestb.in/16pydf71" method="POST" target="_blank">

<input type='hidden' name='pin8' value='1'><input type='submit' value='On'/>

</form>

The rest of the code is identical. When I click on either the On button or the Off button, the
data is submitted to Request Bin (requestb.in) so I can inspect the details of the request.

Here is what I see when I click on one of the buttons:

!
3
Peter Dalmaris Lecture 37 Arduino Step by Step

!
First and foremost, in the request header and in the URL, my data is nowhere to be seen.
However, looking at the Form Data, which is the segment of the POST request that exists in
the body of the request, I can see the data I submitted. Everything else is the same.

The conclusion of all this is that this little difference between GET and POST requests
means that parsing a POST request is significantly harder than parsing a GET request, and
will take much longer to complete on the Arduino. While in a GET request, the information
we are sending is available in the very first line and right after the HTTP verb, for a POST
request it is tacked way down in the document. The Arduino and the parser will have to
search for this information by first scanning every single character that precedes it. This fact
alone means that there will be a significant impact on performance, not to mention the
significant programmer unhappiness (to say the least) that is unavoidable when you try to
write and debug code like this.

Bottom line: Avoid POST requests unless you really have to, and even then consider
alternatives!!!

!
!
4
Peter Dalmaris Lecture 37 Arduino Step by Step

On with the Demo!


We’ll be using a circuit that has two LEDs,
a red and a yellow, the Ethernet shield, and
the Arduino.

!
!
!
!
!
!
!
!
!
The sketch that we’ll use
implements this web page
(right).

Click on the On button, and


the LED connected to
digital pin 8 will light up.
Click on the On button, and
the same LED will turn off.

I have only implemented the


buttons for one of the two LEDs in the circuit. I left the implementation of the second set of
buttons for you to do as an exercise.

5
Peter Dalmaris Lecture 37 Arduino Step by Step

Sketch
This sketch is larger than those we have seen so far. Because of this, I have added several
functions that help with the added complexity by packaging functionality in individual
functions. For example, there is special function that creates the header of the server’s
response, another one that generates the HTTP form part of the web page that the server
returns, and one that implements the parser, to name a few.

Have a read first, and we’ll discuss.

#include <SPI.h>
#include <Ethernet.h>
!
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,111,177 };
String message = ""; //Will hold the confirmation message
//that will be shown to the user
EthernetServer server(80);
String get_request = ""; //Holds the GET request
boolean reading = false; //TRUE while the GET request is being received
!
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
Serial.println("ready");
}
!
void construct_page(EthernetClient &client, String &rmessage)
{
print_header(client);
print_form(client);
print_confirmation(rmessage, client);
end_page(client);
}
!
void print_header(EthernetClient &client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print("GET request example");
client.println("</title><body>");
}
!
void print_confirmation(String &confirmation_message, EthernetClient &client)
{
client.print("Action(s) performed: <b>");
client.print(confirmation_message);
client.print("</b>");
}

6
Peter Dalmaris Lecture 37 Arduino Step by Step

!
void print_form(EthernetClient &client)
{
client.println("<h2>Click buttons to turn pin 8 on or off</h2>");
client.print("<form action='/' method='GET'><p><input type='hidden' name='led8'");
client.println(" value='0'><input type='submit' value='Off'/></form>");
client.print("<form action='/' method='GET'><p><input type='hidden' name='led8'");
client.print(" value='1'><input type='submit' value='On'/></form>");
}

void end_page(EthernetClient &client)


{
client.print("</body>");
client.print("</html>");
}
!
String parseGetRequest(String &str) {
Serial.print(" Parsing this string:");
Serial.println(str);
int led_index = str.indexOf("led");
int led_pin = str[led_index + 3] - '0';
int led_val = str[led_index + 5] - '0';
String return_message = "";
return_message = "Setting LED ";
return_message += led_pin;
return_message += " to ";
return_message += led_val;
executeInstruction(led_pin, led_val);
return return_message;
}
!
void executeInstruction(int pin, int val)
{
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
}

!
… the loop function is shown in the next page …

!
!
!
!
!
7
Peter Dalmaris Lecture 37 Arduino Step by Step

void loop() {
EthernetClient client = server.available();
String return_message;
if (client) {
Serial.println("new client");
boolean sentContent = false;
get_request = "";
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if(reading && c == ' ')
{ reading = false;
parseGetRequest(get_request);
break;
}

if(c == '?'){
reading = true; //found the ?, begin reading the info }
!
if(reading){
get_request += c; }
!
if (reading && c=='\n')
{
break;
}

if (c == '\n' && currentLineIsBlank) {


break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}

if (!sentContent){
construct_page(client, return_message);
sentContent = true;
}

delay(1);
client.stop();
Serial.println("client disonnected");
}
}

8
Peter Dalmaris Lecture 37 Arduino Step by Step

Sketch disassembly
A lot is happening here, and much of this sketch you have not seen before.

Let’s take it from the start.

The first few lines are familiar as thats where the EthernetServer object is being setup with a
MAC and IP address.

I am declaring a String called “get_request” in which the sketch will store the actual
instructions send by the GET request. For example, if my browser sends out this:

http://192.168.111.177/?pinD8=1

… then the value that will be stored in the get_request variable will be “pinD8=1”. The work
for extracting this string from the HTTP request and storing it in this variable is done in the
loop() function as we’ll see in a minute.

After the get_request declaration, I am setting up a boolean variable called reading. This
variable is true when the loop() function detect the “?” symbol in the HTTP request. The “?”
symbol, as you may remember from earlier, is used as a market that signifies the beginning
of the part of the URL that contains the instructions that the user is sending to the server.

Next are the definitions and code of several functions, starting with construct_page. This
function makes calls to other functions that implement the basic components of the
response web page (i.e. the page that the web server returns to the browser):

• The header, implemented by the print_header function,

• The HTML form part of the page, implemented by the print_form function,

• The part of the page that contains a confirmation message for the user, implemented by
the print_confirmation function,

• The ending tags of the HTML page, implemented by the end_page function.

Have a look at these functions and you should see recognisable HTML. The print_header
function is slightly different because it also contains the HTTP response header, with the
first two lines carrying the HTTP declaration and content type, then a blank line. The HTML
document follows.

Also have a good look at the print_form function. I have created one form per button
because when a button is clicked on I only want a single value-pair to be sent to the server.
Also notice that the form method attribute is set to “GET”, not “POST”.

You can notice that each of these functions receive one or two parameters. The
construct_page function received two parameters:

9
Peter Dalmaris Lecture 37 Arduino Step by Step

• The first one is called “client”, is of type EthernetClient. The “&” means that client is
actually a pointer to the memory location where the object of type EthernetClient is
stored. If we don’t use this “&” modifier, the Arduino will actually create a copy of this
object and pass it to the function. Because memory is at a premium, we don’t want to
make copies of objects for which we can simply pass around a pointer, so that is what is
happening here and anywhere else you see the “&” modifier.

• The second one is another pointer, this time pointing to a memory location where a String
object is stored. The String rmessage contains the confirmation message that will be
shown to the user.

Now, let’s move our focus to the loop() function.

It’s starts as we have seen in the previous two Ethernet lectures, by acquiring a client. It
also declares a String variable that will be used later to store a message that will be
returned to the user.

Once it acquires a client, it will declare and initialise the sentContent boolean variable. This
variable is used so that for every client only a single response is sent. For a new client, the
sentContent variable is set to false, to indicate that a response has not yet been sent.
Once, at some point in time later, a response is sent, the this variable will be set to true.

Next, the get_request String is set to empty, getting it ready for the new instruction.

There is also another boolean declared and initialised to true. It’s currentLineIsBlank, and
is used to remember a blank line when one is found. This is needed because according to
the HTTP protocol, a GET request ends with a blank line, which also ends with a new line
(“\n”).

What does currentLineIsBlank do?


Do a quick scan a few lines further down, and you will find this code:

if (c == '\n' && currentLineIsBlank) {



break;

}

if (c == '\n') {

currentLineIsBlank = true;

} 

else if (c != '\r') {

currentLineIsBlank = false;

}

If a new line is found (“c==‘\n’”), then we have a new line and currentLineIsBlank is set to
true, otherwise its set to false. If we have already found a blank line, and now we have
another one, then break out of this “while” block of code because we have reached the end
of the GET request and there is nothing else that the server needs to look into.

10
Peter Dalmaris Lecture 37 Arduino Step by Step

The while loop


In the “while” loop, the Arduino assembles the instructions send by the web browser.

The “client.connected()” statement is true for as long as the client is sending data to the
server or there is still data for the server to read even if the client has disconnected. This
function, therefore, ensures that the server reads everything the client sends. With this
statement in a while loop, we ensure that the Arduino will keep reading data until everything
has been read.

The “client.available()” statement, returns the total available (not yet read) number of bytes
that the client has sent to the server. Because we are not interested in the actual number of
bytes but rather the fact that there are still bytes to be read by the server, we put this
statement in an “if” block.

The “while” and “if” functions make up the framework of the web server. Inside this
framework, the server will scan for instructions.

Scanning for instructions


It starts by grabbing the next byte from the byte stream send by the client and storing it in a
local char variable:

char c = client.read();

A series of “if” statements follows, each checking for a particular pattern.

In the first check, it looks for the case where the Arduino is reading an instruction (reading
variable is true) AND the current character c is one white space ‘ ‘. If this happens, then the
String variable get_request has captured the instruction sent by the client, and the sketch
will call the parseGetRequest function to parse it. It will then break the while block
because it is not interested in anything else that the client has sent. Why did I choose to
stop the parsing of the request here?

Remember that the first line of the GET request looks like this:

GET /?led8=1 HTTP/1.1

I am only interested in the red string. While the red string is being red, the boolean variable
reading is set to true. And while this is true, the c variable will eventually read the white
space character in between the “1” and the “H”. This is the signal that there is nothing else
to be read, so parsing can stop right here to stop wasting resources. If you wanted to read
some of the metadata that follow you could choose to not break here but to continue
reading. I will come back to the parseGetRequest function in a minute.

Next test that happens is the one that checks for the “?” character that signifies the
beginning of the string that carries the client instruction. As soon as the Arduino hits this
character it sets reading to true.

11
Peter Dalmaris Lecture 37 Arduino Step by Step

Next, it tests that the Arduino is currently reading an instruction. If this is true, it will append
the current character to the get_request String variable. The operator “+=“ is the append
operator, and adds whatever is given in the right side of the expression to the existing
contents of the variable.

The last three tests in this block we have already discussed so I will not repeat here.

In summary, the “while-if” loop goes through the data that the client sends to the server and
grabs the only thing our server is interested in, the instruction component of the URL. Once
it does that, the while loop breaks.

If the response has not yet been sent, then the construct_page function will be called to
do so. A 1 millisecond delay is inserted to give enough time to the client to complete
receiving the response, and then the connection is closed.

The instruction parser


The only function left to discuss is the parseGetRequest function. It’s job is to receive
something like “led8=1” and figure out what it means.

We have already discussed the pattern used here: the string “led” followed by a letter,
followed by an integer, followed by the “=“ sign, followed by an integer.

This function implements this pattern definition in code.

• “int led_index = str.indexOf(“led”)”: The “indexOf” function searches for the


string “led” inside the string “str”. If it finds it, the first position of the match is stored in
the “led_index” integer variable.

• “int led_pin = str[led_index + 3] - ‘0’”: Add three to the led_index (since the
string “led” contains three characters) and return the character at this position after
subtracting ‘0’. What is happening here is ASCII arithmetic. A string like “led8” is made
up of chars. According to the ASCII system (which the Arduino observes), character “8”
corresponds to decimal number 561. However, what I want this expression to return is the
 

actual number 8, not the ASCII equivalent of character 8. So, I adjust the formula so that
it subtracts 48 from it, which is the ASCII value for character “0”. And I have 56-48 = 8. If
the client had sent “led6” instead, that this expression would have evaluated 54-48 = 6.

• “int led_val = str[led_index + 5] - ‘0’”: Now add 5 to the led_index so that


the value after the “=“ sign is returned. Again, we need to adjust for the ASCII values, so
the expression subtracts the ASCII value for ‘0’ from the character at index led_index + 5.

In the next 5 lines, the function constructs the response that will be sent to the user as part
of the HTML page.

1 Have a look at the ASCII table at http://ascii.cl

12
Peter Dalmaris Lecture 37 Arduino Step by Step

And finally, action is taken by setting the LED on or off by calling the executeInstruction
function.

Conclusion
If all this has caused you a headache, I understand. You have created a web server, and
even though it is capable of understanding only simple GET requests, this is not a trivial
matter.

But I encourage you to stick with it, go through the sketch a few times on your own, change
things and learn from whatever you break. This sketch also has a lot of room for
improvement.

Feel free to post a questions if you need help, and suggestions for improvement if you have
any.

Learning is best done by doing, so try out the exercises.

Exercises
1. Upload the sketch to your Arduino, and use your browser to access it. Click one of the
buttons and make sure that the LED in pin 8 is working. Notice that according to the
Demo schematic, there is an LED in pin 7, but there is no button for it. Hmm… First,
make sure that you can turn it on and off by editing the URL directly. Change this:
http://192.168.111.177/?led8=0 to this http://192.168.111.177/?led7=0. I have
highlighted the difference in red. Can you edit the sketch so that the web page contains
an on button and an off button for the LED in pin 7?

2. For the more adventurous in you, can you edit the sketch, and specifically the
parseGetRequest and executeInstruction functions so that you can also control the
analog pins? think about the change(s) that this will require in the string pattern that the
parser will need to understand.

3. Modify the sketch so that the server will be able to both receive an instruction (like in
the default sketch) but also to report the values from a couple of sensors of your
choice. Imagine that you are building a home automation system. You want to be able
to close a window shutter by turning on a DC motor, and to confirm that the light
intensity inside the room is reduced by reporting the value of an attached photo-
resistor.

13
Peter Dalmaris Lecture 37 Arduino Step by Step

14
Peter Dalmaris Lecture 40 Arduino Step by Step

Lecture 39
Motor control through a web server
!
In the previous lecture, you learned about controlling the state of a digital pin through
sending GET requests with your web browser.

What if you had to control two pins at once, and if you had to send over values other than
1s and 0s?

In this lecture, I’ll show you how to do something like that by demonstrating how you can
control a DC motor through your web browser.

You may remember from lecture 20, that to properly control a DC motor you need two bits
of information: speed and direction. So, in this demo, we will look at how we can send
speed and direction information to the Arduino from the browser encoded in a GET request.

This makes for slightly higher parsing complexity on the Arduino, but nothing that we can’t
handle by building on our current knowledge.

Demo: motor control


!
In this demo, we’ll implement a
circuit like the once from
lecture 20, that controls 2 DC
motors through an L298N
motor control break-out board.

You may want to review Lecture


20 for a detailed reminder of
the connections. Note that I am
using a battery pack instead of
an external power supply to
power the motors.

Instead of using a
potentiometer knob to control
the speed and direction of the motors, we’ll use a web user interface composed of radio
buttons (see image in next page).

Each radio button, when clicked, sends direction and speed values to the Arduino via HTTP.
The web server running on the Arduino parses the HTTP request and isolates those values
so that it can the requested control signals to the motors.

!
1
Peter Dalmaris Lecture 40 Arduino Step by Step

In this image, also notice the structure of the URL. You may remember that in the previous
lecture, the URL was composes of two parts: the host address and the key-value pair
containing the data that the user sent to the Arduino web server. These two were separated
by the “?” character (a delimiter we chose).

In this example, the same holds true. The difference now is that we have two key-value
pairs after the “?” delimiter, instead of one. And these two value pairs are delimited by the
“&” character.

Let’s have a closer look at the URL from this example:

192.168.111.177/?speed5=122&direction4=0
Remember that the L298N motor control break-out board uses two pins to control a motor:
one for direction and one for speed. In the colourful example above (hopefully you are not
color blind!), in orange I mark the delimiters, purple mark the keywords, green are the pins,
and blue are the values. The web server will need to use the following logic in order to
extract the necessary information from this string of characters:

1. Look for the location of the “?” character. This indicates that the instruction key-value
pairs follow.

2. Look for the keyword “speed”.

3. Read the character immediately after the keyword “speed”. Convert this character to an
integer value.

4. Look for the “&” character.

2
Peter Dalmaris Lecture 40 Arduino Step by Step

5. Read the character(s) after the “=“ and before the “&” characters. Convert these
characters to an integer.

6. Look for the keyword “direction”.

7. Read the character immediately after the keyword “direction”. Convert this character to
an integer.

8. Read the character after the “=“ and before the end of the string. Convert this character
to an integer.

The code needed to implement this “pseudo-code” is slightly more complicated then the
one use in the previous lecture (where there was a single key-value pair to deal with), but I
promise it is not scary at all. Let’s have a look at it next.

Sketch
Here’s the sketch. Highlighted in red is the part that deals with analysing the two key-value
pairs. There are also changes in the function that generates the HTML, and the function that
executes the received instructions. Everything else is the same (I am including the whole
sketch for completeness).

#include <SPI.h>
#include <Ethernet.h>
!
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,111,177 };
String message = ""; //Will hold the confirmation message that
will be shown to the user
EthernetServer server(80);
String get_request; //Holds the GET request
boolean reading = false; //TRUE while the GET request is being
received
!
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
Serial.println("ready");
}

… continues next page …

3
Peter Dalmaris Lecture 40 Arduino Step by Step

void loop() {
EthernetClient client = server.available();
char return_message[30];
if (client) {
Serial.println("new client");
boolean sentContent = false;
get_request = "";
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if(reading && c == ' ')
{ reading = false;
parseGetRequest(get_request);
break; }
if(c == '?'){
reading = true; //found the ?, begin reading the info
}
if(reading){
get_request += c; }
if (reading && c=='\n')
{ break;}
if (c == '\n' && currentLineIsBlank) { break; }
if (c == '\n') { currentLineIsBlank = true; }
else if (c != '\r') { currentLineIsBlank = false; }
}
}
if (!sentContent){
construct_page(client);//, return_message);
sentContent = true;
}
delay(1);
client.stop();
Serial.println("client disconnected");
}
}

… continues next page …


4
Peter Dalmaris Lecture 40 Arduino Step by Step

void construct_page(EthernetClient &client)


{
print_header(client);
print_form(client);
print_confirmation(client);
end_page(client);
}
void print_header(EthernetClient &client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print("GET motor control example");
client.println("</title><body>");
}
void print_confirmation(EthernetClient &client)
{
client.print("Action performed: <b>");
client.print(get_request);
client.print("</b>");
}
void print_form(EthernetClient &client)
{
client.print("<form action='/' method='GET'>");
client.print("<h1>Forward Speed</h1>");
client.print("<input type='radio' name='speed5' value='0'
onclick='this.form.submit()'>Stopped</input>");
client.print("<input type='radio' name='speed5' value='63'
onclick='this.form.submit()'>1/4</input>");
client.print("<input type='radio' name='speed5' value='127'
onclick='this.form.submit()'>1/2</input>");
client.print("<input type='radio' name='speed5' value='184'
onclick='this.form.submit()'>3/4</input>");
client.print("<input type='radio' name='speed5' value='254'
onclick='this.form.submit()'>FULL!</input>");
client.print("<input type='hidden' name='direction4' value='0'>");
client.print("</form>");
client.print("</br>");
client.print("<form action='/' method='GET'>");
client.print("<h1>Backward Speed</h1>");
client.print("<input type='radio' name='speed5' value='254'
onclick='this.form.submit()'>Stopped</input>");
client.print("<input type='radio' name='speed5' value='184'
onclick='this.form.submit()'>1/4</input>");
client.print("<input type='radio' name='speed5' value='127'
onclick='this.form.submit()'>1/2</input>");
client.print("<input type='radio' name='speed5' value='63'
onclick='this.form.submit()'>3/4</input>");
client.print("<input type='radio' name='speed5' value='0'
onclick='this.form.submit()'>FULL!</input>");
client.print("<input type='hidden' name='direction4' value='1'>");
client.print("</form>");
}

5
Peter Dalmaris Lecture 40 Arduino Step by Step

void end_page(EthernetClient &client)


{
client.print("</body>");
client.print("</html>");
}
void parseGetRequest(String &str) {
//We need to parse something like this: "?speed1=50&direction1=0"
Serial.print(" Parsing this string:");
Serial.println(str);
//We need to get the speed and the direction.
//Speed will have a value made of 1 to 3 digits.
//Notice the value-pair delimiter character: "&"
int delimiter_index = str.indexOf("&");
//Get the speed
int speed_index = str.indexOf("speed");
int motor_number = str[speed_index + 5] - '0';
//Here's, I am trying to avoid using the substring function because I have been
//having problems with it and it seems unstable.
//Instead, I just just an array of chars and copying the speed value from the
//str variable into the array of chars.
char speed_value_array[4];
for(int i = speed_index + 7; i < delimiter_index; i++){
speed_value_array[i - 8] = str[i];
}
int motor_speed_value = atoi(speed_value_array);
//Get the direction
int direction_number = str[delimiter_index + 10] - '0';
int direction_value = str[delimiter_index + 12] - '0';
executeInstruction(motor_number, motor_speed_value, direction_number, direction_value);
}
void executeInstruction(int motor_number, int motor_speed_value, int dir_pin, int direction_value)
{
pinMode(dir_pin, OUTPUT);
pinMode(motor_number, OUTPUT);
digitalWrite(dir_pin,direction_value);
analogWrite(motor_number, motor_speed_value); //PWM Speed Control
delay(30);
}

In the printform function, the HTML form is constructed. I am using radio buttons instead
of regular buttons enhanced with an “onClick” Javascript event so that the form is
submitted when the user clicks on any of the radio buttons. Each radio input tag has a
name that is made up of a keyword (either “speed” or “direction”), and the number of the
pin it is meant to control. It also has a value attribute that contains a pre-determined value
that we want send to the Arduino when the radio is clicked.

The parseGetRequest function is rewritten. The parameter is a pointer (&) to the memory
location where the char array that contains the instruction is stored. The first thing that
happens here is to find the index position in that array where the key-value pair delimiter is

6
Peter Dalmaris Lecture 40 Arduino Step by Step

stored (“&”)1, and keeps that value handy in the delimeter_index integer variable. To do
 

this, we use the indexOf function that is available to strings.

Then, in the same way, it looks for the location of the string “speed” in the char array “str”
and stores that value in the speed_index variable. The motor pin is 5 characters to the right
of the speed index, so we add 5 to the speed index to extract that value from the char
array. This gives us the motor pin value, and it gets stored in the motor_number variable. Up
to now, all this is identical to what we did in the previous lecture.

The next bit is slightly more challenging, because the value we need to extract, the motor
speed value, may be made up of 1, 2, or 3 characters. So, we don’t know before hand the
beginning and end of the segment in the char array that contains this value. What we do
know, are the location of the first character (right after the “=“ character), and the location of
the last character (right before the “&” character - delimiter). Here, I could have used the
substring function that is available to strings, which requires two parameters, the start and
end index of the substring that I want to extract. However, in my IDE version 1.0.5, this
function seems to have a bug in its implementation and I was not able to get it to work
reliably. So, I had to resort to a more basic (lower-level) solution, which involves looping
through the char array, picking one character at a time between the two index limits (after
“=“ and before “&”), and storing each char in a temporary char array of size 4.

This array, speed_value_array, has a size 4 because the max number of chars I expect to
store in it is 3, and I need an extra char to the null character (“\0”). The null character
signifies the end of the string stored in the array, and is a C-language requirement.
Remember here, that you only need to provide enough space for this character, you don’t
actually have to set the last cell of the array to null as this is done automatically at run time.

Also remember that in C (and all C-style languages that I know about), arrays are 0-
indexed. This means that the first cell index is 0, not 1. For this reason, the extracted value
is stored in speed_value_array like this:

speed_value_array[i - 8] = str[i];
!
Notice the “i-8”? Because the speed_index is always 1 (unless you change the order by
which the key-value pairs are encoded in the URL - don’t do that yet!), I need to subtract 8
in order to store the first character extracted from the char array to index position 0 in
speed_value_array. If you wanted to make this code able to deal with the case of the
speed_index order being different to first, then you could write this:

speed_value_array[i - (speed_index + 1)] = str[i];


!
… and it would work just fine.

1it is only a coincidence that the C-language memory reference operator “&” is the same as the HTTP key-value
pair delimeter “&”.

7
Peter Dalmaris Lecture 40 Arduino Step by Step

Last important point of discussion here is the “atoi” function: what we have now is a string
stored in an array of chars that contains the speed value. We need to convert this to an
integer, and the “atoi” is a C-language function that does just that. You give it a pointer to
an array of chars, and it gives you back an integer.

A similar method is used to extract the direction pin number and direction value from the
2nd key-value pair.

We know have all the necessary information, and the sketch goes ahead to apply the
instruction to the motor by calling the executeInstruction function and passing the
extracted values as parameters.

Feel free to read this a few more times in combination with the video. It will become clear
with a bit of experimentation. Feel free to ask questions if you get stuck anywhere.

Conclusion
In this lecture you learned about sending two key-value pairs that contain information for
updating the state of a connected device, a motor in our case. From here onwards,
complexity can, of course increase, but it can be managed with a bit of planning.

Exercises
I have two exercises to recommend here. The first one I rate as “easy” because you can
deal with it without having to expand on what you learned here.

The seconds one is harder because you have to go beyond what you learned here. You can
use the principles regarding designing a flexible URL structure, but after that you are on
your own.

Here’s te exercises:

1. Adjust the web form segment of the sketch so that you can also control a second
motor. Imagine you had a toy car with two motors: one motor for moving forward and
backward, and one for left and right. Can you create a new version of the sketch so that
you can control the car from the web browser?

2. Create a sketch so that the parser can deal with 3 key-value pairs. For example,
imagine a URL like this: GET /?var1=10&var2=20&var3=30. How can you adapt the
parser we saw in the demo to extract all the information from this URL?

8
Peter Dalmaris Lecture 40 Arduino Step by Step

Lecture 40
Logging on the web
!
You now know how to create a web server in order to monitor activity on your Arduino. This
is quite useful for “real-time” monitoring, where you want to know what is happening right
now with your sensors. But what if you wish to keep historical records of your sensor
readings so you can inspect an analyse later?

In that case you will need to somehow record these readings. Broadly speaking, there are
two ways to do this: you can record readings on-board the Arduino, by using an SD card
writer. Or, you can use an online service to which your Arduino can send its readings
periodically. From there, you can use your web browser to monitor in real time, plot
historical values on a chart, or download the data to your computer.

There are a few really nice services that allow you to do that, and in this lecture we will look
at Nimbits. Nimbits is a cloud service that allows you to log and retrieve data from all kinds
of devices, from Arduinos and Raspberry Pi’s to web server. Anything that generates data
needing logging can use Nimbits. Did I mention that Nimbits is open-source and free to use
by the community?

Another popular service is Xively, formerly known as Pachube. Xively provides a variety of
services, of which logging is just one. It has a different business model to Nimbits, and
while it allows free use by developers, it does have limits that an active Arduino hacker
could reach in no time.

In the second part of this lecture we will also look at logging your sensor data to Twitter.
Twitter is often useful not so much as a logging service (this would be a bit awkward), but
for its social broadcasting and direct communication capabilities. If you would like to
expose environmental data to the whole world to access, then Twitter is for you. Or, if you
want to receive a direct message as an alert when a sensor value exceeds a set limit, again,
you can use Twitter.

1
Peter Dalmaris Lecture 40 Arduino Step by Step

Demo 1: Logging on
Nimbits
The hardware for this demo requires the
Arduino, the Arduino Ethernet shield, a photo-
resistor to use as the sensor, and a 10KΩ
resistor to use as a voltage divider with the
photo-resistor. Feel free to use any other analog
sensor you have handy.

!
!
!
!
!
!
As a logging service, Nimbits provides several benefits:

1. It’s managed, so you don’t have to worry about maintaining it.

2. It’s free, supported by ads, with an option to purchase an account in exchange for an
ad-free experience.

3. You can download the software and host your own Nimbits server should your project
requirements need a privately hosted logging service. This is an important future-
proofing “feature” that significantly safeguards your time investment to this technology.

4. Every new record is timestamped, which means that your Arduino does not need to
maintain a clock.

5. It utilises a simple HTTP (REST) interface, which means that your Arduino can talk to
Nimbits without any special libraries.

So, let’s get started.

!
… continues next page …


2
Peter Dalmaris Lecture 40 Arduino Step by Step

First, get your account on Nimbits:

Click on the Login link. Nimbits uses Google for authentication and account creation, so if
you already have a Google account, you can go straight ahead and use it to logon.

Now you have an account, let’s create a new Data Point to which you will be sending your
data, and a new Read/Write key to use for authenticating your Arduino’s access to this data
point.

3
Peter Dalmaris Lecture 40 Arduino Step by Step

Here’s the starting point for the process that will follow: the Admin Console.

When you start fresh, the console will be blank.


Let’s create a Data Point first:

1. The user interface can be a bit quirky. When you add a new element, it must be
attached to an existing element in the hierarchy. Since this is the first element/data
point to add, click first on your email address to select it, and then right click to get a
list of properties. Then, select New Data Point:

2. Give it a name and click Ok:

4
Peter Dalmaris Lecture 40 Arduino Step by Step

3. Create one more data point in the same way. The sketch we will look at later will be
posting data to two data points.

4. Your Data Point is now ready to receive data once your setup your read/write key. You
can also edit its properties if you want to change its privacy settings, alert trigger levels, etc.
Highly recommended spending a bit of time to play with these.

!
Let’s create a new read/write key and assign it to the newly created Data Point.

1. Right click on your newly created Data Point and click on New Read/Write Key:

2. Type some random text in the Key field, and leave to the default settings as they are:

5
Peter Dalmaris Lecture 40 Arduino Step by Step

!
Keep the Key handy because you will need to use it in your Arduino sketch.

You are done! If you double click on the new Data Point, you will get a pop-up window with
your Data Point chart, which for now is empty.

Let’s proceed with the Arduino side now. The sketch we will use is a slightly edited sketch
written by StewieT.

… continues next page …

6
Peter Dalmaris Lecture 40 Arduino Step by Step

#include <SPI.h>
#include <Ethernet.h>
#include <PString.h> // from http://arduiniana.org/libraries/pstring/
// allows 'printing' to a string buffer
char buffer[400]; // larger than required for this example, resize to suit
your application
char content[200]; // larger than required for this example, resize to suit
your application
PString str(buffer, sizeof(buffer));
PString cont(content, sizeof(content));
!
int ana_A ; // variables to store analog samples
int ana_B ;
!
!
/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0x45, 0xEF, 0xFE, 0xED };
!
// adjust these to suit your local setup.
byte ip[] = {192,168,111,177 }; // ethernet cards address
byte nameserver[] = {192,168,111,1 };
byte gateway[] = {192,168,111,1 };
byte subnet[] = {255,255,255,0 };
!
EthernetClient nimbitsServiceClient;
//***************************************
!
unsigned long lastConnectionTime = 0; // last time you connected to the server,
in milliseconds
const unsigned long postingInterval = 120000; // 120-sec delay between updates to
logging service, 720 per 24hrs to keep within the 1000 quota
// and leave room for other types of API
access
!
// these are for your nimbits account
char mailaddr [] = “your email address"; // your email address for the logging account
char key [] = “your key"; // your KEY you created for the account. Not the UUID.
!
!
void setup() {
Serial.begin(9600); // serial debug
Ethernet.begin(mac, ip, nameserver, gateway, subnet); // initialise the
ethernet system
Serial.println("up and running....");
Serial.print("POST interval is ");
Serial.print(postingInterval/1000);
Serial.println(" seconds");
}
!
// =========================================================================

!
7
Peter Dalmaris Lecture 40 Arduino Step by Step

// =========================================================================
// very simple main loop. Just constantly reads two ADC channels and then if its time to
log again, do_weblog() sends in the latest values
// of A8 and A9
void loop()
{
ana_A = analogRead(8); // read some voltage and save it
ana_B = analogRead(9); // read some voltage and save it
do_weblog();
}
!
// =========================================================================
/*
This is where it all happens.
If the posting interval is reached then a new POST is done with the latest data
If not time yet, we simply exit
*/
void do_weblog() {
// if you're not connected, and 'postinginterval' secs have passed since
// your last connection, then connect again and send data:
if(!nimbitsServiceClient.connected() && (millis() - lastConnectionTime >
postingInterval)) {
str.begin(); // reset the into-string pointer. This is the 'final' composite
string being assembled.
cont.begin(); // and for the actual content ie payload string
!
sendData(); // the POST gets created and sent here
!
delay(1);
nimbitsServiceClient.stop(); // stop the client
nimbitsServiceClient.flush(); // and tidy up
}
}
!
!

8
Peter Dalmaris Lecture 40 Arduino Step by Step

void sendData() {
// Create the 'content' string to send.
cont.print("email=");
cont.print(mailaddr);
cont.print("&key=");
cont.print(key);
// next get the data and store it in the 'cont' string
cont.print("&p1=Test+DP2&v1="); // test123 is the name of a data point you created
cont.print(ana_A,DEC); // latest analog value. Replace this with whatever
// you are logging
// now get the length of the assembled content string.
// email addr, access key, sensor data (two analog vales in this case)
int contlen = (cont.length());
// now try and connect to the web-site
Serial.println("connecting...");
if (nimbitsServiceClient.connect("cloud.nimbits.com", 80)) {
// the format of the POST section below seems to be fairly critical.
str.print("POST /service/batch HTTP/1.1\r\n");
str.print("Host: cloud.nimbits.com\r\n");
str.print("Connection: close\r\n");
str.print("Cache-Control: max-age=0\r\n");
str.print("Content-Length: ");
str.print(contlen,DEC);
str.print("\r\n");
str.print("Content-Type: application/x-www-form-urlencoded\r\n");
str.print("\r\n"); // this empty line is REQUIRED
str.print(cont); // the actual content string 'cont' (access details, data
points)
str.print("\r\n"); // and a terminating newline
// the total string (post headers and content) is now sent to the ethernet connection in
one hit
nimbitsServiceClient.print(str); // ethernet send to nimbits
Serial.println();
Serial.print(str);
Serial.println(); // for debug
Serial.println(); // for debug
}
else {
// if you couldn't make a connection:
Serial.println();
Serial.println("Connection failed");
Serial.println("disconnecting.");
Serial.println();
}
// note the time that the connection was made
lastConnectionTime = millis();
}

9
Peter Dalmaris Lecture 40 Arduino Step by Step

Sketch discussion
This code looks long and convoluted, but it’s not as bad as it seems. Apart from the SPI
and Ethernet libraries needed for the actual communication, the only dependency is the
PString class which help a lot with the construction of strings. To read about the details, go
to the source at http://arduiniana.org/libraries/pstring/. By using the PString class, in this
sketch we can put together a string of characters that contain the complete HTTP request.
This request, which uses the POST method, contains the headers and the data that we
want to write to the Nimbits datapoint. Once the string has been assembled, the sketch
makes a single connection to the remote service (Nimbits) and completes the request.

The method of installing this class is the same as what we have done so far with third-party
Arduino-specific libraries. PString is a class that is implemented in C++. The Arduino IDE
can compile code written in C++ just like it can do with C code. To make the code that
implements this class available to your sketch, you need to copy the folder that contains
the class’s files (“PString.cpp” and “PString.h”) in the folder that contains the Arduino third-
party libraries. Then, rename the folder that contains the PString files to “PString”.

With PString, you can construct a string by appending partial strings into a buffer. In this
sketch, we use two buffers, one for the POST HTTP header, and one for the body of the
request which contains the data. Then these two parts are added together to create the full
content of the HTTP request. It looks like this:

POST /service/batch HTTP/1.1



Request buffer
Host: cloud.nimbits.com

(“buffer”)
Connection: close

Cache-Control: max-age=0

Content-Length: 400

Content-Type: application/x-www-form-urlencoded

[email protected]&key=13jhad982jdh&p1=Test&v1=123
Content buffer
(“content”)

Here is the part of the code that set’s up the buffers and the PString objects that operate on
them:

char buffer[400]; 

char content[200]; 

PString str(buffer, sizeof(buffer));

PString cont(content, sizeof(content));

This code declares two arrays of chars, and initialises them with 400 and 200 cells
respectively. These sizes are large enough to contain the complete HTTP request (for the
buffer array) and the data part (for the content array). Then, it points the str PString object

10
Peter Dalmaris Lecture 40 Arduino Step by Step

to manipulate the buffer buffer, and the cont PString object to manipulate the content
buffer.

There are four more variables being declared:

• lastConnectionTime, contains an unsigned long integer, which means a positive integer


of 32 bits total length. This variable contains a timestamp of the time that the Arduino last
communicated with Nimbits. This time is reported via the millis() function.

• postingInterval, also an unsigned long integer, which contains the frequency (in
milliseconds) by which we want the sketch to communicate with Nimbits. By default, we
set this variable to 120000, which means that data will be send to Nimbits every 120
seconds.

• mailaddr, an array of char which contains the email address you used to create your
Nimbits account. This is the first element used in the authentication process.

• key, also an array of char, which contains the access key. This is the second element
used in the authentication process

In the setup() function, all the code should be recognisable, so let’s move to loop().

In loop(), we take to measurements from analog ports 8 and 9. Add whatever sampling
code you want in here, being digital or analog. Once you have the values you want to post,
call the do_weblog() function to attempt a post to Nimbits.

In do_weblog(), the sketch checks to determine that it is time to post a new request. It just
subtracts the time now (by calling millis()) from the time that the last post was made
(stored in the lastConnectionTime variable). If that is greater that postingInterval, then it is
time to post. This check happens with this statement:

if(!nimbitsServiceClient.connected() && (millis() - lastConnectionTime >


postingInterval))

Take note that this statement also checks that there is no active connection to Nimbits at
the moment. It uses the “&&” boolean operator to join this check with the time check. With
this operator, if the operant on the left of the operator returns false, then the second operant
will not be evaluated and the whole expression will be false.

If it is time to POST new data, the sketch resets the two PString objects by calling their
begin() function. Then, it calls the sendData() function where the bulk of the work is done.

In sendData(), the sketch first constructs the body of the HTTP request by calling cont.print.
Each call to the print function of the cont object appends any string passed to the content
buffer. The first two key-value pairs added to the buffer contain the account email address
and the data point authentication key. These are used as the credentials for authentication.

11
Peter Dalmaris Lecture 40 Arduino Step by Step

Any subsequent key-value pairs will contain the data you want to post. The pattern is the
px and vx represent a point and a value, where “x” is an integer starting from 1 and
incrementing depending on how many data points you want to access.

You need two key-value pairs for each data point. In this example sketch, 2 data points are
being written to, so the content string looks like this (omitting the authentication part for
clarity):

p1=Test&v1=100&p2=Test2&v2=200

This means that the data point name for p1 is Test, and its value is 100. And the data point
name for p2 is Test2, and its value is 200.

Once all the key-value pairs are in the buffer, the sketch moves on to the headers. It first
attempts to connect to Nimbits (since there’s no point continuing if a connection is not
possible), and then constructs the header fields line by line by calling the print function of
the str PString object.

For the content-length field, the sketch needs to calculate the actual size in bytes of the
request body. This is done by calling the length() function of the cont PString object.

After the empty line of the header is printed (which identifies the end of the header), the
sketch prints the contents of the cont buffer (which contains the body data). Add a
terminating line after that, the the string the makes up the HTTP request is complete.

To finally transmit it to Nimbits, the sketch calls the print function on the
nimbitsServiceClient EthernetClient object.

Now, you should be able to double click on the datapoint row in your Nimbits console and
see the value that was just posted plotted in the chart.

After a few data point have been recorded, you will have a plotted chart similar to this:

!
Exercise
Now that you know how to post sensor values to Nimbits, go ahead and make some use of
it. Add a DHT sensor to your circuit, extract humidity and temperature values from it and
post them to your Nimbits data points. Record values for a few days and see how they
fluctuate over time. Add a barometric pressure sensor and a photo-resistor and record all
four values for a week.

Nimbits has a facility that allows you to export your data for local processing. This facility
can be invoked by clicking on “Schedule a data dump” option available from the right-click
menu of each data point. Get the data and plot the all together in a spreadsheet. Can you
see a correlation between the four measurements? For example, can you confirm that
humidity in your area is higher at night than it is during the day?

12
Peter Dalmaris Lecture 41 Arduino Step by Step

Lecture 42
Social logging to Twitter
!
In lecture 40, we played with logging sensor data to Nimbits, a cloud service dedicated to
the task. Nimbits will collect the data from your sensors and plot them in a chart, or you can
download them in a data dump and process them on your computer.

What if you’d like to post your data for anyone to see on the Internet? Well, just like people
can post their holiday adventures on Facebook, gadgets can post their worldly
observations on Twitter!

In this lecture, I’ll show you a very easy way to do just this.

About Tweeting from your Arduino


Twitter is a private messaging service, owned and controlled by a corporation, Twitter Inc..
It is one of the most popular micro-blogging services in the world, if not the most popular.

To post a message to Twitter, you need an account and a Twitter client. Because Twitter has
an interest in protecting it’s infrastructure and users from un-authorised use, it requires that
any tweet is authorised. This makes the tweet legitimate.

Twitter, like many other web sites and services, uses an open-source authorisation protocol
called OAuth. This protocol allows a third-party application, like a tweeting Arduino board,
to gain access to Twitter’s application programming interface (API). So it is quite possible
for you to include code in your Arduino that implements OAuth as a client and use Twitter’s
API to tweet sensor data.

But there is a situation here to consider: If Twitter decides to make changes to the way it
authorises tweets, you will have to update the code on the Arduino. If the Arduino is on your
desk, that is no big deal, but if you have deployed an Arduino-based product and can no
longer access it, then you have a problem. Although changes like this are very infrequent,
they are possible, and because you have no control at all over Twitter’s API changes, there
is a small, but existing, possibility that this will be a problem one day.

The alternative is to use an authorisation proxy service. This is also my favourite solution to
this problem. Your Arduino will send a tweet to the proxy, with authorisation credentials that
the proxy supports, and from there the proxy will relay the message to Twitter. As long as
you have control over the proxy, you will be safe from changes to Twitter’s API because any
changes you will have to make are in the single proxy only.

In the demo for this Lecture, I will show you how to setup an open source proxy called
Arduino-tweet, authorise this proxy for posting tweets to Twitter, and getting the Arduino to
send tweets to the proxy. This architecture is depicted graphically like this:

1
Peter Dalmaris Lecture 41 Arduino Step by Step

!
Arduino-
tweet
 !
proxy !
!
!
The Arduino-tweet proxy
The proxy component is an open-source piece of software that you can download from
Github (https://github.com/NeoCat/ArduinoTweetLib-server) and install on your own server.
But for convenience, you can just use a public, free and managed instance running at
http://arduino-tweet.appspot.com. You don’t even need to create an account, just to get an
authentication token. This is what we’ll do next.

I assume that you already have a Twitter account, or that you have created one specifically
for your Arduino to use. That’s probably best, because at least in the beginning your
Arduino will be posting a lot of annoying test tweets which you do not want in your “official”
timeline.

Go to arduino-tweet.appspot.com. The home page shows the three things that need to be
done:

2
Peter Dalmaris Lecture 41 Arduino Step by Step

Click on the link for step one. This is direct you to Twitter, where you will need to authorise
the proxy to post on Twitter on your (or your Arduino’s) behalf. This page also contains a list
of things that the proxy will be able to do with your Twitter account.

Click on the “Authorize app” button. This will register the proxy with authority to post
tweets, and generate a token that your Arduino will use to authenticate itself to the proxy.
Copy it and store it somewhere safe, since you will need to use it in your Arduino sketch:

Keep this secret, because any client with this token will be able to post messages to Twitter
via the proxy.

Go back to arduino-tweet.appspot.com and click on the step 2 link. You will now see
instructions on how to download and import the required library to your Arduino IDE:

3
Peter Dalmaris Lecture 41 Arduino Step by Step

Click on the link in the first bullet point. Once the download is complete, extract the
contents of the ZIP file, and copy the folder to your Arduino IDE libraries folder. Rename the
folder that contains the Twitter library to “Twitter”. You should have something like this in
your Arduino IDE libraries folder:

Restart your IDE, and make sure that the new library shows up. You know that the library
has been imported successfully if you can see the example sketches (File —> Examples —
> Twitter):

4
Peter Dalmaris Lecture 41 Arduino Step by Step

Finally, the next step is to try out the example sketch. Click on the link in Step 3, and the
sketch will show up.

To try this out, change the IP address to one that matches your network (blue arrow), and
copy/paste the proxy token in the twitter constructor (red arrow). You can get this sketch by
clicking on File —> Examples —> Twitter —> Sample Post. Here it is for completeness:

… continues next page …


5
Peter Dalmaris Lecture 41 Arduino Step by Step

#include <SPI.h>!
#include <Ethernet.h>!
#include <Twitter.h>!
!
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };!
byte ip[] = { 10, 0, 0, 177 };!
Twitter twitter("<<< your token here >>>");!
char msg[] = "Hello, World! I'm Arduino!";!
!
void setup()!
{!
delay(1000);!
Ethernet.begin(mac, ip);!
Serial.begin(9600);!
Serial.println("connecting ...");!
if (twitter.post(msg)) {!
int status = twitter.wait();!
if (status == 200) {!
Serial.println("OK.");!
} else {!
Serial.print("failed : code ");!
Serial.println(status);!
}!
} else {!
Serial.println("connection failed.");!
}!
}!
void loop()!
{!
}

If this goes well, your Arduino will introduce itself to the world with a greeting: “Hello, World!
I’m Arduino!”!

… continues next page …

6
Peter Dalmaris Lecture 41 Arduino Step by Step

Custom tweets
Now that we know that the Arduino can tweet via the proxy, let’s customise the message
that is posted. Let’s make it so that it reports a value from one of the analog inputs. I would
like the Arduino to tweet regularly, say once every hour, so I must move the code
responsible for tweeting from the setup() function to the loop() function. Have a look at
this code:

#include <SPI.h>!
#include <Ethernet.h>!
#include <Twitter.h>!
#include <PString.h> !
!
unsigned long lastConnectionTime = 0;!
const unsigned long postingInterval = 3600000;!
!
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };!
byte ip[] = { 192, 168, 111, 167 };!
Twitter twitter("2282862504-
Hae3j7Ysr6F5k8OvTA6HL0xxgJVQEBgBaaQcUNG");!
char tweet[200];!
PString tweet_pstring(tweet, sizeof(tweet));!
!
void setup()!
{!
Ethernet.begin(mac, ip);!
Serial.begin(9600);!
}!
!
void loop()!
{!
if((millis() - lastConnectionTime > postingInterval)) {!
tweet_pstring.begin();!
int ana_A = analogRead(8);!
Serial.println("connecting ...");!
tweet_pstring.print("Light intensity:");!
tweet_pstring.print(ana_A);!
if (twitter.post(tweet_pstring)) {!
int status = twitter.wait(&Serial);!
if (status == 200) {!
Serial.println("OK.");!
} else {!
Serial.print("failed : code ");!
Serial.println(status);!
}!
} else {!
Serial.println("connection failed.");!
}!
lastConnectionTime = millis();!
}!
}

7
Peter Dalmaris Lecture 41 Arduino Step by Step

The Ethernet part of the sketch is familiar. Just like in Lecture 40, I am using the PString
library to help me assemble text strings.

After adjusting the IP address, and setting your proxy token, the sketch defines an array of
chars with 200 character cells in it. Twitter only allows 140 characters, so 200 is a bit of an
overkill. Finally, it declares and initialises the tweet_pstring object that will be used to
construct the tweet post string.

Inside the loop() function, we check that one hour has passed since the last tweet using
almost the same code we used in Lecture 40. You want to keep a low posting frequency
because both the proxy and Twitter have limits on how many posts they can process per
minute. If it is time to tweet, we take a measurement from analog pin 8 and store it in a local
integer variable. Then we construct the tweet using the tweet_pstring object
(tweet_pstring.print).

The actual posting happens with this command:

twitter.post(tweet_pstring)!
!This attempts to post the string to which tweet_pstring is pointing to. This command will
return a boolean, and if that boolean is true, then the sketch will go inside the if block and
check for a response from Twitter. This happens with this command:

int status = twitter.wait(&Serial);!


!The wait function of the twitter object can receive one parameter, which in this case is a
reference to the Serial port, the one that outputs text to the IDE monitor. This way, we can
see the actual text that Twitter sends back to the Arduino. If you don’t need to see this text,
you can just call twitter.wait();

The wait() function eventually returns a status code. If that is “200”, that we know that the
post was successful.

Before finishing the loop, the sketch gets the correct time in milliseconds since the Arduino
was booted with the millis() function and stores it in a variable so that it can later check if
it is time to post again.

Exercise
You can see that with a proxy managing the communication with Twitter, posting tweets
with the Arduino could not be any simpler. With the code for both the Arduino library and
the proxy being open source, you have peace of mind that your tweeting infrastructure can
be built on your own hardware and be in your total control if you ever need to.

As an exercise, make the necessary changes to the custom sketch so that your Arduino
tweets data from multiple sensors. Please message me at @futurshocked with your
Arduino’s Twitter handle so I can check out your tweets!

8
Peter Dalmaris Lecture 45 Arduino Step by Step

SD card storage
Local file storage
!
The Arduino has a tiny amount of memory in which a sketch can store data, or where the
sketch itself is being kept.

The ATmega micro-controllers in the Arduino contain 3 types of memory: SRAM, flash, and
EEPROM.

Static RAM (static random-access memory) is volatile, and is where your sketches store
values that belong to variables from things like sensor readings. Volatile memory is cheap
and fast, but as soon as power is lost, it is erased. Therefore, it is only used as a temporary
place to store data.

In an expression like int ledPin = 13, you are storing the number “13” in static RAM. In
the Arduino Uno where the ATmega 328 is used, there are only two thousand bytes
available in the static RAM. It sounds like its a lot, but it isn’t. Your computer probably has a
million times more RAM available to the programs that run on it.

Flash memory is non-volatile, so when power is turned off, its contents remain safe. Flash is
where your sketches and the Arduino bootloader (a special program that helps the Arduino
start executing the sketch when power is applied, or with uploading a new sketch) are
stored. The ATmega 328 has 32k bytes of this memory. You don’t normally use this memory
to store data, but you can if you want to (this is a topic for another lecture, but for the very
curious of you, have a look at the PROGMEM keyword).

Finally, EEPROM (Electrically Erasable Programmable Read-Only Memory), like flash, is also
non-volatile. It is a good place to store data permanently that should not be erased in case
a new sketch is uploaded. Things like serial numbers, ids and the like can be stored here.
The ATmega 328 has only 1k byte of EEPROM available, so it is definitely not mass storage.

On the Arduino, on-board storage is very limited. For applications like data logging, or
running a web server with multiple pages and images, the build-in memory is not enough,
so we turn to SD cards for help.

SD cards
SD cards have matured over the years. Their sizes have expanded
to many giga-bytes, and their prices have dropped to a few cents
per gigabyte. Compared to build-in memory, SD cards offer a really
good mass storage solution. On the Arduino, an SD card can be
used with the appropriate hardware extension and with an easy to
use library that comes with the IDE. Your Arduino Ethernet shield
comes with a micro-SD card slot, but you can also get them as a
separate breakout board.

1
Peter Dalmaris Lecture 45 Arduino Step by Step

In this lecture, I will show you how to take


advantage of SD card mass storage using
a cheap (less than $2 on eBay) breakout.

You will need a breakout like the one in this


image, and an SD card. I’m using an
ancient 256MB card in my demos, which
works just fine.

You could also use a micro-SD card


breakout like this one; the instructions to
get it working are identical.

Before getting into the demo, there’s one


thing I need to discuss: the SPI buss.

The SPI bus


The SPI (Serial Peripheral Interface) bus is a way of connecting multiple slave devices to a
master. Unlike I2C, which we played with back in lecture 9 where we learned about the
BMP08 barometric sensor, the SPI bus provides full duplex (two-way) communication
between master and slave using two wires. The I2C interface supports half-duplex, so that
data can flow only one way at a time. There is also a wire that provides a clock signal to the
slave so that both devices are synchronised, and a fourth wire that is used for selecting one
of the many slave devices that may be available.

In summary, this table shows the pins used by the SPI bus, which we will be using to
connect the breakout board to the Arduino:

Pin Stands for… Purpose…

CS or SS Chip Select OR Slave Select Selects a slave device

MOSI Master Out Slave In The master device uses it to transmit data to the
slave device
SCLK Shared/Serial Clock Used to syncronise the master and slave devices

MISO Master In Slave Out The slave device uses it to transmit data to the
master device

The SPI bus offers itself as a topic for a full lecture, so I will not go into more details now.
For now, simply keep in mind the functions of each of the SPI bus pins.

2
Peter Dalmaris Lecture 45 Arduino Step by Step

Demo 1: Connect and get card info


Here is what we’ll do in the first Demo:

1. We will connect the SD card breakout to the Arduino.

2. We will prepare an SD card for use with the breakout.

3. We will upload a sketch that prints out information about the card and confirm that it
works.

Connection
The pins which we should use to connect
the breakout depend on the Arduino you
are using. On an Arduino Uno, these pins
are:

• MOSI on digital pin 11

• MISO on digital pin 12

• CLK on digital pin 13

• CS can vary, but to keep things tidy I use


digital pin 10.

• Power: some boards work with either


3.3V or 5V, or both. The one I use in this
demo works with both, and I connected
it to the 5V pin on the Arduino. Be careful
in case yours only accepts 3.3V to not
connect it to the 5V pin on the Arduino!

• Ground: connect to a GND pin on the


Arduino.

Done with the wirings, so let’s move on to the sketch.

Prepare an SD card
The Arduino SD card library works with SD cards that contains FAT16 or FAT32 partitions.

Most SD cards will work out of the box. However, if you are having any issues that prevent
you from using it with the Arduino, it is a good idea to format it. On a Mac, you can do this
by using the Disk Utility, and on Windows by right-clicking on the SD Card icon and clicking
on the Format option.

Once your SD card is formatted and ready, insert it into the SD card slot and plug the
Arduino to your computer. Let’s have a look at the first sketch.

3
Peter Dalmaris Lecture 45 Arduino Step by Step

Sketch
Let’s try something simple first: Get information about our SD card.

The sketch we’ll look at makes use of un-documented classes in the SD library. Typically a
vendor does not provide documentation for certain features because they either had no
time to write it up, or because they don’t want users to know about them. In this case, this
library has been out for some time now, so it is more likely that Arduino (the company) does
not want you to use certain features as they are probably subject to change. But since they
are used in some of the examples that come with the IDE, we can try them out and see
what they do!

Open the CardInfo sketch by clicking on File —> Examples —> SD —> CardInfo. Here’s
what you get (slightly edited from the original):

#include <SD.h> Sd2Card, SdVolume and SdFile are classes in the SD


Sd2Card card; library that not documented. We use them here as a way to
SdVolume volume; access information about the SD card, volumes in the card,
SdFile root; and the root. Because they are not documented, they
const int chipSelect = 10; could change at any time so you should avoid using them
! in your sketches.
void setup()
We’ll use digital pin 10 as Slave Select for the SD breakout.
{
Serial.begin(9600); This tries to initialise the card object.
!
Serial.print("\nInitializing SD card...");
pinMode(10, OUTPUT); // change this to 53 on a mega
!
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.println("initialization failed. Things to check:");
Serial.println("* is a card is inserted?");
Serial.println("* Is your wiring correct?");
Serial.println("* did you change the chipSelect pin to match your shield or
module?");
return;
} else {
Serial.println("Wiring is correct and a card is present.");
}
!
// print the type of card
Serial.print("\nCard type: ");
switch(card.type()) { Retrieve the type of SD you are using.
case SD_CARD_TYPE_SD1:
Serial.println("SD1");
break;
case SD_CARD_TYPE_SD2:
Serial.println("SD2");
break;
case SD_CARD_TYPE_SDHC:
Serial.println("SDHC");
break;
default:
Serial.println("Unknown");
}
4
Peter Dalmaris Lecture 45 Arduino Step by Step

!
… continues from previous page …

// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32


if (!volume.init(card)) {
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted
the card");
Tries to get a handle on a valid partition
return;
} If there is no valid partition, exit this function (program
! ends)
// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("\nVolume type is FAT");
Serial.println(volume.fatType(), DEC);
Serial.println();

volumesize = volume.blocksPerCluster(); // clusters are collections of blocks


volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize *= 512; // SD card blocks are always 512 bytes
Serial.print("Volume size (bytes): ");
Serial.println(volumesize);
Serial.print("Volume size (Kbytes): ");
volumesize /= 1024; Gets and prints out statistics about the SD
Serial.println(volumesize); card.
Serial.print("Volume size (Mbytes): ");
volumesize /= 1024;
Serial.println(volumesize);

Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);

// list all files in the card with date and size


root.ls(LS_R | LS_DATE | LS_SIZE);
}
!
void loop(void) {

!
!
!
!
!

5
Peter Dalmaris Lecture 45 Arduino Step by Step

When you run this sketch on your Arduino, you will see something like this, assuming that
your SD card is properly formatted:

6
Peter Dalmaris Lecture 45 Arduino Step by Step

Demo 2
Demo 1 was about getting the SD card
breakout working. Now, let’s make use of
it. Let’s start logging sensor data onto our
card, and then use the card on the
computer to do some basic data analysis
ad plotting.

We’ll use another slightly modified example


that comes with the IDE.

For this demo, use the hardware from


Demo 1 with the addition of a photo-
resistor, a thermistor, and a 1kΩ resistor
used as voltage dividers for the sensors.

A thermistor is an analog sensor that


changes its resistance depending on the
temperature. Electrically, it works like the
photo-resistor.

Here’s is the sketch. My changes are


highlighted in red, and commends are in
bubbles.

This sketch represents the recommended


way to access and use an SD card.

… continues next page …

7
Peter Dalmaris Lecture 45 Arduino Step by Step

#include <SD.h>
 Include the SD library.


const int chipSelect = 10;

Use digital pin 10 as the slave select pin (SPI bus).
void setup()

{

Serial.begin(9600);

Serial.print("Initializing SD card...");

pinMode(10, OUTPUT);

if (!SD.begin(chipSelect)) {
 Attempt to initialise the SD device.


Serial.println("Card failed, or not present");

return;
 If the device can’t be initialised, exit the setup function
}
 and end execution of this program.
Serial.println("card initialized.");

}
 Initialise the string use to construct the record that
void loop()
 eventually will be stored in a file on the SD card.
{
 Instead of a String, you could use a PString as was
shown in the Ethernet lectures.
String dataString = "";

for (int analogPin = 0; analogPin < 2; analogPin++) {

int sensor = analogRead(analogPin);
 Connect analog sensors
to pins 0 and 1, and loop
dataString += String(sensor);
 through them. Take a
if (analogPin < 1) {
 reading from each one,
dataString += ","; 
 convert to a String and
add it to the dataString,
}

then append a comma
}
 so that values are
File dataFile = SD.open("datalog.txt", FILE_WRITE);
 separated.
if (dataFile) {

dataFile.println(dataString);
 SD.open attempts to open the file, with write
dataFile.close();
 permissions. If a file cannot be opened, the
Serial.println(dataString);
 function will return FALSE. If it can, it will
return an object of type File.
} 

else {
 You can save text to a file like
Serial.println("error opening datalog.txt");
 you do with a serial connection:
just call the print or println
} 
 Remember to call the close function on the File
function on the file object
} object in order to commit any changes. (datafile, in this example).

Other than the comments in the code box above, it is worth mentioning that with the
print(data) function you can write ASCII text to the SD card. If you want to write numbers,
you can use print(data, BASE), where BASE can be BIN for binary, DEC for decimal, HEX
for hexadecimal and OCT for octal.

You can also write bytes or arrays of bytes by using the write(data) or write(buffer, length)
function. This way of writing to the card may have a better performance and it is something
worth while remembering if you are building a higher-speed data logger.

8
Peter Dalmaris Lecture 45 Arduino Step by Step

Another point worth remembering is that the write speed


depends on several conditions: the actual speed of the SD
card (although modern SD cards are much faster than the
Arduino’s ability to write on them), the speed of the SPI
bus, the sampling rate of your project, the type of data you
are writing (ASCII is slower than bytes). If you hit a
performance block, try to determine the slowest
component of the system and try to find a way to optimise
it.

Here’s the monitor output as sensor data are being


captured (right):

!
Remove the SD card from the Arduino and insert it in your
computer’s card reader.

!
You’ll see something like this (below):

!
The time stamp for the DATALOG.TXT file is 1 Jan 2000
because the Arduino does not have a real time clock, so
time will initialise to this date every time it is reset. I will
show you how to use a real time clock in another lecture.

!
Finally, open the DATALOG.TXT file. You will see something
like this: multiple lines containing the sensor readings,
delimited by a comma. It’s a standard text file that you can
import to a spreadsheeting program for analysis and
charting.


9
Peter Dalmaris Lecture 45 Arduino Step by Step

Demo 3
In this last demo, we’ll look at how we can browse directories and files stored on your SD
card. This is useful in order to create and maintain a hierarchical file system in which files
are stored. Even though it is unusual for an Arduino sketch to be managing too many files,
basic file management can be setup by creating folders and putting files in them, instead of
placing everything in the root (which is still a folder).

Looking at the SD class documentation, you see functions like mkdir() and rmdir() which
create or remove a directory, and exists() which checks for the existence of a file or
directory.

This example sketch comes with the IDE and browses the file system on the SD card and
prints out the directories and their contents.

The sketch in this Demo contains a recursive structure, which simply means a function
that calls itself. It sounds fancy, but it is merely a convenient way to code operations that
repeat themselves.

In the sketch that follows, I have provided annotations for only those parts that we haven’t
already seen in Demos 1 and 2.

… see next page …

!
!
!
!
!
!
!
!
!
!
!
!
!
10
Peter Dalmaris Lecture 45 Arduino Step by Step

#include <SD.h>
 Include the SD library.


File root;

void setup()
 Declare an object of type File, that will be used as a handle
{
 to the root directory.
Serial.begin(9600);

Serial.print("Initializing SD card...");

Declare an object named root which is of class File. Looking
pinMode(10, OUTPUT);
 at the documentation, you learn that this kind of object can
if (!SD.begin(10)) {
 represent both normal files and directories (a directory is
just a special kind of file).
Serial.println("initialization failed!”);

return;

}

Serial.println("initialization done.");

root = SD.open("/");
 SD.open() tries to open the file or directory named in the
printDirectory(root, 0); 
 parameter. In this case it is the root directory “/“. The function
open returns a reference to a File object, so we store this
Serial.println("done!");
 reference to variable root.
}
Calls the printDirectory function and passes two parameters: a
void loop()
 reference to the File object root (which now contains information
about the root directory), and an integer number that is used by
{ }
the function to nicely format its output (more about this below).

void printDirectory(File dir, int numTabs) {



while(true) {

This is an interesting control structure. It is a
File entry = dir.openNextFile();
 loop that never ends (“while(true)”) but from
Calls a new instance of his function.

if (! entry) {
 which the sketch exist (“break”) when the File


break;
 openNextFile() returns false. This happens when
there is no regular file or directory left to return.
}

for (uint8_t i=0; i<numTabs; i++) {
 Prints out tab characters depending on the level of
Serial.print('\t');
 the current directory. Each time a new directory is
found, numTabs is increased by one.
}

Serial.print(entry.name());
 Print out the name of the current file (which may be
if (entry.isDirectory()) {
 a directory. “entry” is the name of the File object
Serial.println("/");
 that contains this information, and “name” is one of
its attributes. Hence, entry.name prints out the
printDirectory(entry, numTabs+1);

name of the file.
} else {

Serial.print("\t\t");
 If variable “entry” is pointing to a directory, then
Serial.println(entry.size(), DEC);
print a “/“ and call (recursive operation) the function
printDirectory, so we can have a look inside. Pass
}
 the entry object and increase the tabs number by
entry.close();
 one to intent the file names in this directory.
}

} Close the file. If this is a regular file, add two tabs and print out
the size of the file in bytes, as a decimal.
!
!
11
Peter Dalmaris Lecture 45 Arduino Step by Step

This is what the monitor output looks like:

!
!
!
!
!
!
!
!
! Directory

!
! Directory

!
Size
! (bytes)

!
!
!
!
!
An exercise
You now know how to write text data to your SD card!

!
But what about reading? I did not show you how to read text from the card because I’d like you to
work this function out your self. Have a look at the documentation page for the read function, and a
sample sketch that shows you how to read text from a text file.

12
Peter Dalmaris Lecture 47 Arduino Step by Step

Real time clock


The Arduino, even though it can interact with its environment, can’t do anything at all
without a access to sensors and all kinds of components. And unlike most computers you
are used to, it cannot tell the time. Although knowing the time is not needed in many
applications (and indeed, we have not really needed it up to now), sooner or later you will
come across a project where knowing the time is a requirement.

It is true that the Arduino has a build-in sense for time. It knows how much time has passed
since it started executing a program. You can use the millis() function to get a number that
represents this time in milliseconds. A similar function is micros(), and it does the same
thing as millis() except that it reports the elapsed time in microseconds instead of
milliseconds. There are also the time-related functions delay() and delaymicroseconds()
which add a delay in your program, the fist in milliseconds and the second in
microseconds.

Still, your sketch cannot ask the Arduino for the time. You could use an Internet time server
and poll it occasionally for the time, but this method requires Internet connectivity, a
dependency that maybe an overkill for some projects.

A real-time clock break out board is a PCB that contains a time-keeping integrated circuit.
It’s like the watch you wear on your wrist. You glance at it to get the time. The Arduino will
be able to ask the real-time clock for the time too.

A simple application for a real-time clock is for time-stamping log entries recorded on an
SD card. We will look at this problem in this lecture. You can also consider applications
where certain events must be scheduled, like turning an illuminated sign on and off, or
taking sensor readings at predetermined times.

1
Peter Dalmaris Lecture 47 Arduino Step by Step

Demo 1: Setting and reading the clock


In this demo, I’ll show you how to use a
typical real time clock with your Arduino. I will
be using the DFRobot DS1307 RTC breakout,
EEPROM Clock
which I purchased on eBay for around $4.
This device, like many others, is based on the
popular DS1307 clock IC, and it can do
anything you would expect a good clock can
do. It counts seconds, minutes, hours, days,
years, goes up to 2100 and compensates for
leap years.

It also consumes very little power, 500nAmps,


which when using the on-board battery gives
the device a life of around 5 years (although I
have not tested this claim!).

The breakout also features an additional IC in


which you can store up to 4kbytes of data
(EEPROM 24C32), and an integrated
temperature sensor. Not bad at all for such a low cost device!

Let’s do the wirings and connect the


breakout to the Arduino. The RTC uses the
IC2 serial bus for communication.
Therefore, we only need two wires for Vcc
and Gnd, one wire for data (SDA), and one
for the synchronisation clock (SCL). On the
Arduino Uno, the SDA pin is analog 2, and
the SCL pin is 1. In you have any other
board, you may want to check the location
of the SDA and SCL pins against your
board’s documentation before you do the
connections.

Before looking at the sketch, let’s install the


library for the device. If you are using the
TinyRTC breakout, you can download the
library from the manufacturer’s web site.
This clone from Adafruit also seems to be
working (thank you to Matt Hill for letting
me know about this).

2
Peter Dalmaris Lecture 47 Arduino Step by Step

Download it, copy the library folder to the Arduino libraries folder, and restart the IDE. Then,
load the sketch from File —> RTClib —> ds1307.

This is what you will see (slightly edited to improve readability):

#include <Wire.h>
 Import the Wire library so that we can use the IC2 bus.
#include "RTClib.h"
Import the RTClib library so that we can use the clock.
RTC_DS1307 rtc; Declare an RTC_DS103 object, name it “rtc”.

void setup () {

Serial.begin(9600);
 Initialise the IC2 bus.
Wire.begin();

Initialise the real time clock device.
rtc.begin();

if (! rtc.isrunning()) {
 This will get the time from your
Serial.println("RTC is NOT running!");
 computer during compilation
rtc.adjust(DateTime(2014,01,16,14,45,00));
 and automatically set the time.
// following line sets the RTC to the date & time this sketch was compiled

//RTC.adjust(DateTime(__DATE__, __TIME__));

}
 This will adjust the time with the
} help of the C-language DateTime Check to determine is the device is on. Since the
object initialiser. device is powered by a battery when the Arduino is
off, it will continue to keep track of time and be in a
void loop () {

“running” state. As long as a time has been set and
DateTime now = rtc.now();
 the battery can power it, the “rtc.isrunning()”
Serial.print(now.year(), DEC);
 function will return true. The only time you will
Serial.print('/');
 probably see a “false” returned is when you run this
sketch for the very first time.
Serial.print(now.month(), DEC);

Serial.print('/');
 Get the time now, and store it in the “now” variable,
Serial.print(now.day(), DEC);
 which is of time DateTime.
Serial.print(' ');

Print time attributes to the Serial port.
Serial.print(now.hour(), DEC);

Serial.print(':');

Serial.print(now.minute(), DEC);

Serial.print(':');

Serial.print(now.second(), DEC);

Serial.println();

Serial.print(" since midnight 1/1/1970 = ");

Serial.print(now.unixtime());
 Get the number of seconds elapsed since 1/1/1970,
Serial.print("s = ");
 when Unix time begins.
Serial.print(now.unixtime() / 86400L);

… and convert that to days, since 1 day
Serial.println("d");
 contains 86400 seconds.

… sketch continues in next page…

3
Peter Dalmaris Lecture 47 Arduino Step by Step

// calculate a date which is 7 days and 30 seconds into the future



DateTime future (now.unixtime() + 7 * 86400L + 30);

Serial.print(" now + 7d + 30s: ");

Serial.print(future.year(), DEC);
 Create a new object of type DateTime,
Serial.print('/');
 name it future and initialise it with a
date that is 7 days and 30 second into
Serial.print(future.month(), DEC);

the future.
Serial.print('/');

Serial.print(future.day(), DEC);

Serial.print(' ');
 Print future attributes to the Serial port.
Serial.print(future.hour(), DEC);

Serial.print(':');

Serial.print(future.minute(), DEC);

Serial.print(':');

Serial.print(future.second(), DEC);

Serial.println();

Serial.println();

delay(3000);

}

Once the clock has been set, it will keep the time independently of the Arduino,
compensating for leap years and the like until its onboard battery fails. All you have to do in
order to get a reading of the time is to call the now() function, which returns a DateTime
object.

Upload this sketch, and open


the monitor. You should see
something like this:

! Current time reported by the RTC

!
Results of time/date calculations

4
Peter Dalmaris Lecture 47 Arduino Step by Step

Demo 2: Logging with time stamps


Back in Lecture 39, you learn about how to
use an SD card for logging sensor
readings. Let’s go ahead and improve the
design from Demo 2 so that the time of
data capture is also stored in your SD card.

Here’s the new and improved circuit. It is a


merge between Lecture 39 Demo 2 and
this lecture’s Demo 1.

If you guessed that the sketch is also


mostly a merge between these two, you
guessed correctly.

For the SD card module connections, I


remind you the pins for the Arduino Uno:

• MOSI on digital pin 11

• MISO on digital pin 12

• CLK on digital pin 13

• CS can vary, but to keep things tidy I use


digital pin 10.

• Power: some boards work with either


3.3V or 5V, or both. The one I use in this demo works with both, and I connected it to the
5V pin on the Arduino. Be careful in case yours only accepts 3.3V to not connect it to the
5V pin on the Arduino!

• Ground: connect to a GND pin on the Arduino.

In the next page, I provide the merged sketch, and comments to the interesting segments.

…please see next page…


5
Peter Dalmaris Lecture 47 Arduino Step by Step

#include <SD.h>
 Include the SD card library.


#include <Wire.h>

#include "RTClib.h" Include the IC2 library for the real time clock.

RTC_DS1307 rtc;
 Import the RTClib library so that we can use the
const int chipSelect = 10; clock breakout library.

void setup() { 
 Instead of manually setting the time like in Demo


1, this syntax will get the date and time from
Serial.begin(9600);
 your computer during compilation time, and
Wire.begin();
 reset the RTC every time the sketch is uploaded.
rtc.begin(); 

rtc.adjust(DateTime(__DATE__, __TIME__));

Serial.print("Initializing SD card...");

pinMode(10, OUTPUT);

if (!SD.begin(chipSelect)) {

Serial.println("Card failed, or not present");

return;

}

Serial.println("card initialized.");

}

void loop(){

DateTime now = rtc.now();
 Get the sensor readings.
String dataString = "";

for (int analogPin = 0; analogPin < 2; analogPin++) {

int sensor = analogRead(analogPin);

dataString += String(sensor);

if (analogPin < 1) {

dataString += ","; 

}

}

File dataFile = SD.open("datalog.txt", FILE_WRITE); 

if (dataFile) { 

print_time(now, dataFile);
 Get a handle to the datalog file.
dataFile.println(dataString);

Call the print_time function which will
dataFile.close();
 produce the timestamp. Pass a reference
Serial.println(dataString);
 to the now object that contains the
} 
 current time, and the datafile object
which contains a handle to the data file.
else {

Serial.println("error opening datalog.txt”)

} 

Print the sensor readings to the data file.
delay(3000);

}

… continues next page …

6
Peter Dalmaris Lecture 47 Arduino Step by Step

void print_time(DateTime capture_time, File file)



{

file.print(capture_time.year(), DEC);
 This function accepts a DateTime
object which contains the current date
file.print('/');
 and time, and a File object with
file.print(capture_time.month(), DEC);
 contains a handle to the file we want
file.print('/');
 to print the timestamp.
file.print(capture_time.day(), DEC);

file.print(' ');
 Print the current date and time one
file.print(capture_time.hour(), DEC);
 element at a time, to the data file.
file.print(':');

file.print(capture_time.minute(), DEC);

file.print(':');

file.print(capture_time.second(), DEC);

file.print(',');

}

There is nothing new in this sketch, just a recombination of known elements. You now have
a way to create a data-logger, which can work in remote locations, on a battery which can
be charged by a small solar panel.

An exercise
With the right hardware, keeping time is easy. Try out this exercise:

!
Create an LCD clock. Use a real time clock like the one in this lecture, combine it with an LCD
screen, and display the date and time on it.

!
For the adventurous, here’s another exercise: Extend the LCD clock so that it has these features:

!
1. A toggle switch

2. One rotary potentiometer

3. A buzzer

4. Only keeps track of time (don’t worry about the date for now)

!
The toggle switch will set the mode of the clock to Time Set or Alarm set. When the toggle switch is
on, then turning the potentiometer will change the time. When the switch is off, then turning the
potentiometer will change the alarm time.

!
Assuming the clock keeps time in 24 hour format, make your gadget so that when the alarm time is
reached, a sound will be generated by the buzzer for 10 seconds.

7
Peter Dalmaris Arduino Step by Step Lecture 50

Lecture 50
Wifi
In Lecture 33 and 34, you learned about the Arduino Ethernet shield, and connected your
Arduino to the Internet. In this lecture, we’ll again connect the Arduino to the Internet, but
we’ll do that using Wifi, and go completely wireless!

There are a lot of shields and breakout boards that provide Wifi functionality, with varying
prices. Shields that provide 802.11n capability can sell for over $100 with bells and whistles
like external antennas and on-board SD card modules.

I personally go for breakout boards whenever possible, because usually they offer a lower
price point, a modular and smaller package, and a single function per board which makes it
easier to learn and integrate into to my projects.

For this lecture, I chose the Adafruit


CC3000 breakout board, with an on-board
ceramic antenna. This product also is It
comes as a shield, and with a connector
for an external antenna if you need
extended range. At around $35, it offers
802.11a/g connectivity, very small size, a
nice library, and lots of documentation.

I will go through 3 demos in this lecture. In


the first one, we’ll connect the CC3000 to
the Arduino and run one of the library’s
examples to make sure that it works and
that it can connect to our Wifi router. In the second one, I’ll show you how to create a Wifi
web client, whereby the Arduino will be polling a URL, and fetching a file contains
instructions for turning an LED on or off. The polling method has an advantage over the
web server method because it is not affected by firewall or NAT restrictions. This means
that by polling an external URL to your local network, you will be able to control your
Arduino from anywhere in the Internet without having to configure your router to allow
access to the Arduino from the outside world.

In the last one I will show you an adapted version of Demo 2 from lecture 38, where we had
a web server running on the Arduino, showing us a simple user interface through which we
could turn an LED on and off.

1
Peter Dalmaris Arduino Step by Step Lecture 50

Demo 1: Connect the Wifi module and access the


LAN
Once you receive your CC3000, you will need to first
solder the header pins to it. Once you have that, your
module will look like this:

!
Adafruit maintains a Github repository with the latest
version of the library and examples. Go ahead and get it,
then copy the library into your Arduino IDE’s libraries
folder as we have done before. Remember to restart the
IDE once the new library has been installed.

The CC3000 Wifi module, made by Texas Instruments, uses the SPI communications
interface to talk to the Arduino. On the PCB, notice the familiar pin markings CLK, MISO,
MOSI, and CS. We saw the exact same pins on the SD card module in lecture 45. There’s
two additional pins on the CC3000: IRQ and VBAT_EN (the actual marking is VBEN on the
PCB).

In the SD card module, the Arduino is responsible for initiating communication. The Arduino
will ask for a read or write, and the SD card module will execute it. The SD card module
never initiates communication. With the wifi module, however, it is just as likely for the
module to initiate communication as it is for the Arduino. The IRQ pin (for “Interrupt
ReQuest”) is used by the Wifi module to grab the attention of the Arduino when it has data
to sent. The Arduino Uno has a special pin, digital pin 3, which can detect an interrupt
request. When an interrupt is requested, the Arduino will stop whatever it is doing at that
moment and start executing a special function (part of the CC3000 library) that will deal

2
Peter Dalmaris Arduino Step by Step Lecture 50

with the interrupt. When the function is done dealing with the interrupt, the Arduino
continues doing whatever it was doing before the interrupt.

The VBAT_EN is used to start the module properly. Think of it as a reset switch.

Here’s the schematic and a pinout table:

Arduino CC3000

13 SCK

12 MISO

11 MOSI

10 CS

5 VBEN

3 IRQ

GND GND

5V VIN

!
!
!
!
!
!
!
Double-check the connections, and the plug the Arduino to your computer via the USB
port. A surface-mounted green LED will light up on the wifi board, that’s means you’re good
to go!

3
Peter Dalmaris Arduino Step by Step Lecture 50

Sketch
Let’s look at the sketch now. The one we’ll use for this demo is one of the many samples
that come with the CC3000 library. Fire up the IDE and load the example: File —> Examples
—> Adafruit_CC3000_Library —> buildtest

Here is the sketch (edited to make it fit), I am highlighting the interesting parts:

#include <Adafruit_CC3000.h>
 Import the Adafruit library so that we can use the Wifi module.

#include <ccspi.h>
 Contains SPI helper functions for the CC3000.


#include <SPI.h>

#include <string.h>
 Import that standard SPI and String libraries.

#include "utility/debug.h" Implements the useful foreach() and sign() functions, used in this
sketch.
#define ADAFRUIT_CC3000_IRQ 3

#define ADAFRUIT_CC3000_VBAT 5
 Set pins for IRQ (fixed) and VBAT, CS (can change).
#define ADAFRUIT_CC3000_CS 10

// Use hardware SPI. On an UNO, SCK = 13, MISO = 12, and MOSI = 11

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS,
ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER);
Initialise the CC300 object with the defined pins as parameters.
#define WLAN_SSID "myNetwork"
 SPI_CLOCK_DIVIDER sets the module clock speed based on the
#define WLAN_PASS "myPassword"
 type of the micro-controller used.
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2

#define WLAN_SECURITY WLAN_SEC_WPA2

void setup(void)
 Set the Wifi credentials and security type.


{

Serial.begin(115200);

Serial.println(F("Hello, CC3000!\n")); Call
 a function that displays the type of driver used (tiny or
displayDriverMode();
 normal).
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);

/* Initialise the module */

Serial.println(F("\nInitialising the CC3000 ..."));

if (!cc3000.begin())
 Gets RAM remaining, great for debugging memory issues.
{

Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));

while(1);
 Try to start the device. Assuming wiring is correct, this should work.
}

uint16_t firmware = checkFirmwareVersion();

if ((firmware != 0x113) && (firmware != 0x118)) {

Serial.println(F("Wrong firmware version!"));

for(;;);
 Call a function that displays the firmware running in the module.
}

displayMACAddress(); Call a function that displays the MAC address assigned to the
module.

… continues next page …

4
Peter Dalmaris Arduino Step by Step Lecture 50

#ifndef CC3000_TINY_DRIVER
 You can load a small-footprint driver for the Wifi module. The tiny
listSSIDResults();
 driver will only load the essential API functions and save a lot of
RAM. See http://processors.wiki.ti.com/index.php/
#endif

Tiny_Driver_Support. Enable tiny mode by adding this definition in

 your code: #define CC3000_TINY_DRIVER.
Serial.println(F("\nDeleting old connection profiles"));

if (!cc3000.deleteProfiles()) {
 Unless running in tiny mode, call the listSSIDResults function
Serial.println(F("Failed!"));
 and show detected WiFi networks.
while(1);

A profile is a wifi network of which the device remembers its
}
 credentials. Calling deleteProfiles() deletes such networks.

 More info: http://processors.wiki.ti.com/index.php/
char *ssid = WLAN_SSID; /* Max 32 chars */

Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid);

/* NOTE: Secure connections are not available in 'Tiny' mode! */

if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {

Serial.println(F("Failed!"));

while(1);
 Attempt to connect to the Wifi access point with the security
credentials as parameters.
}

Serial.println(F("Connected!"));

/* Wait for DHCP to complete */

Serial.println(F("Request DHCP"));

while (!cc3000.checkDHCP())
 Go in a loop, until DHCP assigns network settings. If DHCP
{
 has not responded yet, wait for 100msec before trying again.
delay(100);

} 

/* Display the IP address DNS, Gateway, etc. */ 

while (! displayConnectionDetails()) {

delay(1000);

}
 Show assigned IP and other connection details.
#ifndef CC3000_TINY_DRIVER

Resolve the IP address of the host
/* Try looking up www.adafruit.com */

www.adafruit.com. The IP address will be stored
uint32_t ip = 0;
 to the memory address passed as the second
Serial.print(F("www.adafruit.com -> "));
 parameter (“&ip”). This is a DNS request.
while (ip == 0) {

if (! cc3000.getHostByName("www.adafruit.com", &ip)) {

Serial.println(F("Couldn't resolve!"));

}
 The ip variable was declared of type uint32_t, which is a
delay(500);
 4-byte integer. This function will convert this integer into
} 
 a dot-delimited nice looking IP address like this:
207.58.139.247
cc3000.printIPdotsRev(ip);

/* Do a quick ping test on adafruit.com */ 

Ping this host and store the response in a 1-
Serial.print(F("\n\rPinging ")); 
 byte (8 bit) unsigned integer. The response

cc3000.printIPdotsRev(ip); Serial.print("..."); contains the number of packets received.
uint8_t replies = cc3000.ping(ip, 5);

Serial.print(replies); Serial.println(F(" replies"));

if (replies)

Serial.println(F("Ping successful!"));

#endif

5
Peter Dalmaris Arduino Step by Step Lecture 50

Serial.println(F("\n\nClosing the connection"));



cc3000.disconnect(); } Disconnect the device from the Wi-fi network.

void loop(void){

delay(1000); } Start of a pre-processor conditional group.
What follows (until the #endif directive) will be
void displayDriverMode(void){
 compiled only if the tiny driver is used.
#ifdef CC3000_TINY_DRIVER

Serial.println(F("CC3000 is configure in 'Tiny' mode"));

#else
 Print out various driver parameters. The F()
Serial.print(F("RX Buffer : "));
 function enforces storage of these static
Serial.print(CC3000_RX_BUFFER_SIZE);
 (unchanging) Strings in flash memory instead
of SRAM, therefore preserving SRAM for the
Serial.println(F(" bytes"));
 dynamic segments of the sketch. Reminder:
Serial.print(F("TX Buffer : "));
 flash memory is where the sketch is actually
Serial.print(CC3000_TX_BUFFER_SIZE);
 stored when you upload it.
Serial.println(F(" bytes"));

#endif
 End of the pre-processor conditional group.
}
Retrieve the firmware version running in the
uint16_t checkFirmwareVersion(void)

device, and store the major and minor versions
{
 in the memory locations provided as
uint8_t major, minor;
 parameters.
uint16_t version;

#ifndef CC3000_TINY_DRIVER 

if(!cc3000.getFirmwareVersion(&major, &minor)) {

Serial.println(F("Unable to retrieve the firmware version!\r\n"));

version = 0;

}

else

{

Serial.print(F("Firmware V. : "));

Serial.print(major); Serial.print(F(".")); Serial.println(minor);

version = major; version <<= 8; version |= minor;

}

#endif

return version;

}

!
!
!
!
6
Peter Dalmaris Arduino Step by Step Lecture 50

void displayMACAddress(void){

uint8_t macAddress[6];

if(!cc3000.getMacAddress(macAddress))

{

Serial.println(F("Unable to retrieve MAC Address!\r\n"));

}

else
 Get the device’s MAC address. It contains 6
{
 bytes, and those bytes are stored in the
macAddress array of bytes.
Serial.print(F("MAC Address : "));

cc3000.printHex((byte*)&macAddress, 6);
 Print the MAC address in hexadecimal
}
 notation, as is common.
}

bool displayConnectionDetails(void){

uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))

{

Serial.println(F("Unable to retrieve the IP Address!\r\n"));

return false;
 Get the Wifi connection parameters. The
}
 parameters will be stored in the memory
else
 locations passed as parameters to the
function.
{

Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);

Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);

Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);

Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);

Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);

Serial.println();

return true;

}

} Print out the Wifi connection parameters.

!
!
!
!
!
!
!

7
Peter Dalmaris Arduino Step by Step Lecture 50

void listSSIDResults(void)

Search for Wifi networks. The 8-byte integer
{
 index will contain the total number of networks
uint8_t valid, rssi, sec, index;
 found.
char ssidname[33]; 

index = cc3000.startSSIDscan();

Serial.print(F("Networks found: ")); Serial.println(index);

Serial.println(F("================================================"));

while (index) {

index--;

valid = cc3000.getNextSSID(&rssi, &sec, ssidname);

Serial.print(F("SSID Name : ")); Serial.print(ssidname);

Serial.println();

Serial.print(F("RSSI : "));

Serial.println(rssi);

Serial.print(F("Security Mode: "));

Print out the parameters for the networks
Serial.println(sec);
 found, starting with the last one.
Serial.println();

}

Serial.println(F(“================================================"));

cc3000.stopSSIDscan();
 Stop scanning.
}

!
Here is an example
output of this sketch:

8
Peter Dalmaris Arduino Step by Step Lecture 50

Demo 2: Web client LED control by polling a URL


Great, the Wifi module works, so let’s go ahead and do something useful with it.
Automation and remote control fits well in that category. You may remember back in
Lecture 38 that you learned how to control an LED by setting up a simple web server on the
Arduino. You used your web browser to access this web server and click on buttons to turn
the LED on and off. We will adapt that sketch to use the Wifi module instead of the Ethernet
shield in Demo 3, but in this demo we’ll try something different: polling-based control.

In summary, we will use instructions contained in a text file, hosted by a web server
somewhere on the Internet. The Arduino will use the Wifi module to get this file, read it’s
contents, and turn an LED on and off accordingly. Schematically, this is what is going to
happen:

!
1
!
!
!
! 4
! 3

There is a blank
line after the
instruction line.

!
!
Instruction: Turn LED in pin 8 ON
!

9
Peter Dalmaris Arduino Step by Step Lecture 50

There’s an LED connected to digital Pin 8 via a protective 1kΩ resistor. The Arduino will use
the Wifi module to request a copy of the file titled “cc3000.txt” from the web server that is
hosting it. In my demo, I am using an Amazon S3 bucket, but you can use any service at all
as long as you can access it with a HTTP URL like “http://myserver.com/cc3000.txt”. You
may remember that the instruction contained in the first line of this file is identical to the one
that we learned about how to parse back in lecture 38. We are not learning again how to
parse this instruction, we just store it on the web instead of on the Arduino!

The nice thing about this architecture is that is is scalable. Once you stop thinking of
cc3000.txt as a text file but instead as a web resource, then you have many options to
manipulate it. You can get the Arduino to poll a URL that is controlled by a web application
which creates the LED instruction based on some user entry, a schedule, environmental
conditions somewhere else etc.

I also mentioned in the introduction of this lecture that polling, as opposed to a web server
running on the Arduino, has the additional benefit of not having to worry about local
network restrictions, especially firewalls and NAT. You Arduino will be able to get it’s
instructions by accessing a public URL, and you will be able to control your Arduino by
manipulating the resource at that URL.

Let’s have a look at the sketch, comments are embedded:

#include <Adafruit_CC3000.h>

#include <ccspi.h>

#include <SPI.h>
 No change compared to Demo 1, except…
#include <string.h>

#include "utility/debug.h"
 Import the Watchdog library. See further down
#include <avr/wdt.h>
 for details.
#define ADAFRUIT_CC3000_IRQ 3

#define ADAFRUIT_CC3000_VBAT 5

#define ADAFRUIT_CC3000_CS 10

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ,
ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER);

Set the host and path to the file that contains
boolean reading = false; 
 the LED instruction. Also set a timeout
String get_request = "";
 constant. We expect the server to respond
#define WLAN_SSID "mynetworkid"
 within 3 seconds.
#define WLAN_PASS "mynetworkpassword"

#define WLAN_SECURITY WLAN_SEC_WPA2

#define IDLE_TIMEOUT_MS 3000

#define WEBSITE "arduinosbs.com.s3.amazonaws.com"

#define WEBPAGE "/cc3000.txt"

uint32_t ip; uint32_t t; int port = 80;
 No change compared to Demo 1
int connectTimeout = 5000;

Adafruit_CC3000_Client www;
 Counter keeps track of how many times the
int repeat_counter = 0; file has been polled.

10
Peter Dalmaris Arduino Step by Step Lecture 50

void setup(void){

Serial.begin(115200);

Serial.println(F("Hello, CC3000!\n")); 

Serial.print(F("Free RAM: ")); Serial.println(getFreeRam(), DEC);

Serial.println(F("\nInitializing..."));

if (!cc3000.begin()) {

Serial.println(F("Couldn't begin()! Check your wiring?"));

while(1); }

connect_wifi();
 Broken down the functionality from the setup
function in Demo 1 to individual functions in
get_dhcp();
 order to improve readability.
lookup_ip(); 

}

void loop(void){ 

repeat_counter++;

Serial.print(F("Free RAM: ")); Serial.println(getFreeRam(), DEC);

Serial.print(F("Repeat counter: ")); Serial.println(repeat_counter);

Serial.print(F("starting connection to "));

Serial.println(ip);
 Enable watch dog timer (“WDT”). See detailed
wdt_enable(WDTO_8S);
 discussion at the end of this sketch.
connect_tcp();

Call the connect_tcp() function. This function
wdt_disable();
 will attempt to connect to the remote web
Serial.println(F("Connecting"));
 server.
if (www.connected()) {

Disable watch dog timer (“WDT”). It is not
Serial.println(F("Connected"));
 likely that anything else may cause the sketch
make_get_request();
 to freeze.
Serial.println(F("Request sent"));

Connection to the remote web server was
} else {
 successful.
Serial.println(F("Connection failed")); 

return; }
 Call the make_get_request function which will
construct and apply the HTTP GET request.
Serial.println(F("-------------------------------------"));

unsigned long lastRead = millis();

Confused? Consider revising Lecture 38!

while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {



boolean currentLineIsBlank = true;

get_request = ""; 

boolean sentContent = false;
 Keeps track of the time when the
last GET request was made.
while (www.available()) { 

char c = www.read();

Serial.print(c);
 A response from the server is expected within
3 seconds. The IDLE_TIMEOUT_MS constant
if(reading && c == '\n') 

was set at the start of the sketch.
{ reading = false; 

parseGetRequest(get_request);

break;
 The server has started sending its response,
} let’s start parsing it.

!
Grab a character
from the response.
If we are currently reading, and this char is a new line, then reading is
finished, so lets parse the instruction. Nothing else to do here.

11
Peter Dalmaris Arduino Step by Step Lecture 50

if(reading){ 

The HTTP response parser, continues.
get_request += c; } 

It is essentially identical to the one
if (reading && c==‘\n') {
 from Lecture 38 except for the green
break; } 
 segment. The content the parser is
if (c == '\n' && currentLineIsBlank) {
 looking for is in the body of the HTTP
response (not the query string like in
reading = true;
 Lecture 38). The HTTP response is
}
 found after the response header, and
if (c == '\n') {
 is detected by looking for a new line
(“\n”) after a blank line.
currentLineIsBlank = true;

} else if (c != '\r') {

currentLineIsBlank = false;

}

}

Close the connection to the web
}
 server.
www.close();

Serial.println(F("-------------------------------------"));

delay(10000); }
Instruction parser, identical to the one
void parseGetRequest(String &str) {
 in Lecture 38.
Serial.print(F("Parsing this string:"));

Serial.println(str);

int led_index = str.indexOf("led");

int led_pin = str[led_index + 3] - '0';

int led_val = str[led_index + 5] - '0';

executeInstruction(led_pin, led_val); }
Execute instruction function, identical
void executeInstruction(int pin, int val){ 

to the one in Lecture 38.
Serial.println(F("Executing instruction"));

pinMode(pin, OUTPUT);

digitalWrite(pin, val);

Serial.println(F(“Done!"));}

bool displayConnectionDetails(void){

uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv)){

Serial.println(F("Unable to retrieve the IP Address!\r\n"));

return false; } else {

Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);

Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);

Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);

Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);

Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);

Serial.println();

return true;

}

}


12
Peter Dalmaris Arduino Step by Step Lecture 50

void make_get_request(){

www.fastrprint(F("GET "));
 Get request is assembled by “printing” to the
remote server represented by the www object.
www.fastrprint(WEBPAGE);

www.fastrprint(F(" HTTP/1.1\r\n"));

www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r
\n"));

www.fastrprint(F("\r\n"));

www.println(); }

void connect_tcp(){

t = millis();
 Attempt to connect to the remote server if at
do {
 least 5 seconds (set in the connectTimeout
variable) have elapsed since the last connection.
www = cc3000.connectTCP(ip, port); } 

while((!www.connected()) && ((millis() - t) < connectTimeout));

}

void connect_wifi(){

if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {

Serial.println(F("Failed!"));

while(1); }

Serial.println(F(“Connected!")); 

}

void get_dhcp(){
 Attempt to connect to the Wifi access point.


Serial.println(F("Request DHCP"));

while (!cc3000.checkDHCP())

{ delay(100); } 
 Get network settings from the DHCP server.
while (! displayConnectionDetails()) {

delay(1000);

Lookup the IP address of the remote server by
}

making a DNS request.
}

void lookup_ip(){

ip = 0;

Serial.print(WEBSITE); Serial.print(F(" -> "));

while (ip == 0) {

if (! cc3000.getHostByName(WEBSITE, &ip)) {

Serial.println(F("Couldn't resolve!"));

}

delay(500);

}

cc3000.printIPdotsRev(ip); 

}

13
Peter Dalmaris Arduino Step by Step Lecture 50

About the WatchDog Timer


The Arduino, just like a “normal” computer, occasionally may “hung” or, in other words,
become unresponsive. This can be a result of hardware issues, like faulty sensors or
communications devices, or bugs in a sketch. As I was playing around with the CC3000
Wifi module while preparing this demo, I noticed that the Arduino would hung after a few
(around 20) loops. Each loop represents a poll of the control text file from the web server. I
discovered that the most likely cause of this behaviour was memory fragmentation. Memory
fragmentation occurs when data in RAM is erased and saved in a way that over some
period of time even though there is a lot of memory available, it is only available in small
chunks; this makes it almost usefulness unless you only want to store a byte or so at a
time. Have a look at this screenshot from the Microsoft Windows Disk Defragmenter utility:

http://i.stack.imgur.com/00nX7.jpg

The hard disk that is visualised in this map contains free space (shown in white), but that
space is not contiguous, so you can only store small files in it. A normal computer has the
resources to “defrag”, that is to re-arange the contents of the memory (or hard disk) in order
to create larger and more useful contiguous segments of free memory.

Working on this demo, I realised that the connectTCP function would, over time, fragment
the SRAM until the free space available could not be used, and then the ATMega would
freeze.

On the Arduino, there is no practical way to achieve defragmentation other than reseting the
micro-controller. To make this work, I used a feature build-in to ATMegas called Advanced
Watchdog Timer (http://www.atmel.com/Images/doc2551.pdf). This feature makes it
possible to set a timer so that if by the time the timer reaches a set limit the watchdog has

14
Peter Dalmaris Arduino Step by Step Lecture 50

not detected any activity ((heart beat”) it assumes that the micro-controller has become
unresponsive. The watchdog will then reset the micro-controller, and the sketch will start
executing with a clear slate - and a de-fragmented memory.

The way I set the watchdog timer is this:

1. I identified the segment of the sketch that seems to be causing fragmentation and/or is
affected by it. I used lots of Serial.print statements to figure out where the sketch
hangs. In the Demo 2 sketch, this was the call to the connect_tcp() function.

2. Just before the offending call, add the call to wdt_enable(WDTO_8S). This enables the
WatchDog Timer and sets a timer for 8 seconds. This time I think was enough for
nothing to happen. In other words “if 8 seconds pass with no activity, reset the device”.

3. After the offending call, add the call to wdt_disable(). This disables the WatchDog Timer.
If anything outside this block causes my sketch to hung, I want to know about, so I
don’t want the WDT
to reset the device
and mask such
behaviour.

Yes, I could potentially


dig into the source code Connecting to Wifi access point.
of the CC3000 that
causes this problem
(the connectTCP
function), and I might Device and network details.
actually do this once I
can allocate some time IP of remote web server resolved.
to it, however the WDT
offers a simple and
cheap solution.

Connect and transmit HTTP request to


remote web server.
Output
Execute this sketch, and
you will get something like
this:

! Receive HTTP response and find


the string that contains the
instruction.

Parse the instruction and then


execute it.

Re-start the HTTP GET/response


process.

15
Peter Dalmaris Arduino Step by Step Lecture 50

Demo 3: Control an LED via Wifi and a web server


running on the Arduino
For this last demo, we will modify the sketch from Lecture 38 Demo 2 so that instead of
working with an Ethernet shield, it will work with the CC3000 Wifi breakout.

We will use the exact same circuit as in Demo 2. Let’s go straight to the sketch and see
what’s different…

Sketch
!
This sketch is a hybrid between the sketch in Demo 2 and that of Lecture 38 Demo 2.
Comments are embedded.

#include <Adafruit_CC3000.h>

#include <ccspi.h>

#include <SPI.h>

Inclusions and definitions as in the previous
#include <string.h>
 examples, with the addition of LISTEN_PORT
#include "utility/debug.h"
 which defines the TCP port on which the web
#include <stdlib.h>
 server will listen for connections.
#define ADAFRUIT_CC3000_IRQ 3

#define ADAFRUIT_CC3000_VBAT 5

#define ADAFRUIT_CC3000_CS 10

define WLAN_SSID "yournetworkssid"

define WLAN_PASS “yournetworkpassword"

#define WLAN_SECURITY WLAN_SEC_WPA2
 Create the device object.
#define LISTEN_PORT 80

Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS,


ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,SPI_CLOCK_DIV2);
// Create server

Adafruit_CC3000_Server ledServer(LISTEN_PORT);
 In Lecture 38, we used the
EthernetServer class to create the
String get_request = "";
 server. Here, we use the custom
boolean reading = false; Adafruit_CC3000_Server class.

… continues next page…

16
Peter Dalmaris Arduino Step by Step Lecture 50

void setup() {

Serial.begin(115200);

Start the device.
Serial.println(F("\nInitializing..."));

if (!cc3000.begin()) {

Serial.println(F("Couldn't begin()! Check your wiring?"));

while(1); }

if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {

Serial.println(F("Failed!"));

while(1); }

Connect to the Wifi access point.
Serial.println(F("Connected!"));

Serial.println(F("Request DHCP"));

while (!cc3000.checkDHCP()) {
 Get network parameters from the
DHCP server.
delay(100); // ToDo: Insert a DHCP timeout!

} 

while (! displayConnectionDetails()) {
 Show network parameters leased
from the DHCP server.
delay(1000); }

ledServer.begin();

Serial.println(F("Listening for connections..."));

}
Start the web server

void loop() {

Adafruit_CC3000_ClientRef client = ledServer.available();

String return_message; 

if (client) {
 The contents of the loop() function are
boolean currentLineIsBlank = true;
 virtually identical to that from Lecture
get_request = "";
 38, Demo 2, with the exception of the
client object. Here we use the
boolean sentContent = false;

Adafruit_CC_3000_ClientRef class
while (client.available()) { 
 instead of EthernetClient.
char c = client.read();

if(reading && c == ' ') 

{ reading = false; 

return_message = parseGetRequest(get_request);

break; }

if(c == '?'){

reading = true; } 

if(reading){ 

get_request += c; }

if (reading && c=='\n') { 

break; }

if (c == '\n' && currentLineIsBlank) {

break; }

}

17
Peter Dalmaris Arduino Step by Step Lecture 50

if (!sentContent){

construct_page(client, return_message); 

sentContent = true; }

delay(5);

client.close();

Serial.println("client disconnected");

result = "";

}

}

void construct_page(Adafruit_CC3000_ClientRef &client, String &rmessage)



{

print_header(client);

print_form(client);

print_confirmation(rmessage, client);

end_page(client); }

void print_header(Adafruit_CC3000_ClientRef &client)



{

These functions are identical to the
client.println("HTTP/1.1 200 OK");
 ones from Lecture 38, Demo 2 with
client.println("Content-Type: text/html");
 one exception only: instead of
client.println();
 passing a reference to a
EthernetClient object, here we pass a
client.print("<html><head><title>"); 

reference to an
client.print("GET request example");
 Adafruit_CC3000_ClientRef object.
client.println("</title><body>");

}

void print_confirmation(String &confirmation_message, Adafruit_CC3000_ClientRef


&client)

{

client.print("Action(s) performed: <b>");

client.print(confirmation_message);

client.print("</b>");

}

void print_form(Adafruit_CC3000_ClientRef &client)



{

client.println("<h2>Click buttons to turn pin 8 on or off</h2>");

client.print("<form action='/' method='GET'><p><input type='hidden'
name='led8'");

client.println(" value='0'><input type='submit' value='Off'/></form>");

client.print("<form action='/' method='GET'><p><input type='hidden'
name='led8'");

client.print(" value='1'><input type='submit' value='On'/></form>");

}

18
Peter Dalmaris Arduino Step by Step Lecture 50

String parseGetRequest(String &str) {



Serial.print(" Parsing this string:");

Serial.println(str);

int led_index = str.indexOf("led");

int led_pin = str[led_index + 3] - '0';

int led_val = str[led_index + 5] - '0';
 These functions are identical to the
String return_message = "";
 ones from Lecture 38, Demo 2.

return_message = "Setting LED ";



return_message += led_pin;

return_message += " to ";

return_message += led_val;

executeInstruction(led_pin, led_val);

return return_message; }

void executeInstruction(int pin, int val){ 



pinMode(pin, OUTPUT);

digitalWrite(pin, val);}

bool displayConnectionDetails(void){

uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{

Serial.println(F("Unable to retrieve the IP Address!\r\n"));

return false; }

else {

Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);

Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);

Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);

Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);

Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);

Serial.println();

return true;

}

}

19
Peter Dalmaris Arduino Step by Step Lecture 50

Using the sketch from Demo 2 in Lecture 38 as a building block, we now have the same
capability to control the state of an LED using a web browser but wirelessly. Running this
sketch generates this output in the monitor:

!
!
!
!
! The Arduino is listening at this IP
! address.

!
A connection from a web client was
! made, an instruction was parsed.

!
!
!
!
!
Use a web browser and go to your Arduino’s IP address, you should see the same user
interface as in Lecture 38, Demo 2:

!
!
!
!
!
!
!
!

20
Peter Dalmaris Arduino Step by Step Lecture 50

An exercise
In this lecture, we covered a lot of ground in regards to using the Adafruit CC3000 wifi
module to control our Arduino wirelessly. The module we used still has it’s supporting
library under development, so I expect that its features and stability will improve over time.
The module comes in two types, one with a build-in ceramic antenna, and one with a
connector for an external antenna. An external antenna can be used for projects where
range is important, like when you want to control your quad-copter outdoors.

As an exercise for this lecture, how about you try to extend the Demo 2 and Demo 3
examples with the ability to control more devices? For example, for Demo 2, add a couple
of lines in the instructions file so that you can control additional LED, or motors (you may
want to review Lecture 39 for this). Because polling takes place every few minutes, you
would use the Demo 2 sample in a project like home automation and control, where “real-
time” is not necessary.

21
Peter Dalmaris Lecture 54 Arduino Step by Step

Lecture 54
Single Wire LCD screen
!
In Lecture 24, you learned how to display text in a LCD screen. Although this was a simple
way to show useful information to the user, the sheer number of wires required to make the
LCD screen work makes this solution far from elegant.

In this lecture, I will show you a much improved solution to the same problem, one that
involves a single data wire (plus power).

The difference is stark. Have a look at the “before” (left) and “after” (right) images for the
exact same result.

To achieve this reduction in total number of wires we have to switch the type of interface we
use to connect the screen to the Arduino. Natively, the screen uses a parallel interface,
where each of the 8 bits that make up a character encoding uses up a wire. You may
remember that in Lecture 24, use used a 4-bit parallel mode instead of the full 8-bits in
order to save 4 wires. Still, even 4 wires are too many for transferring data. We also needed
wires for power, and for the screen backlit.

To improve the design, we’ll use an adaptor that allows us to connect the parallel LCD
screen to the Arduino using the I2C serial bus. We have used I2C before, but here is a quick
recap:

• Uses 1 wire for data (SDA - pin A4 on the Arduino Uno)

• Uses 1 wire for clock (SCL - pin A5 on the Arduino Uno)

• Uses 1 wire for +5V power and 1 for ground

• Can be shared amongst multiple I2C devices, which means that you can connect multiple
compatible devices to your Arduino without increasing the wire count.

1
Peter Dalmaris Lecture 54 Arduino Step by Step

The adaptor I’ll use in the demos is the 1602LCD


Display I2C board, like the one in this image.

It contains two rows of connectors: the long one


that connects to the 16x2 LCD screen, and the
short one that implements the I2C interface and
connects to the Arduino. On the board there is also
a potentiometer that you can use to adjust the
brightness of the screen, and the micro-controller
that handles that conversion and communications
workload.

In Demo 1, I’ll show you how to connect the


1602LCD to the screen and the Arduino. In Demo 2, I will add a second I2C device to the
circuit, a real-time clock, and show you how the same I2C wires can be used to drive both
devices by displaying the time from the clock to the LCD screen.

Demo 1: Connect the 16x2 LCD screen via I2C


!
When you purchase the
1602LCD adaptor, it typically
arrives without the headers
attached, so you will have to
the soldering your self. The
spacing and configuration of
the 16 pins in the long row
match exactly that of the pins
on the LCD screen PCB.

Use a mini breadboard if you


have one, and line up the
LCD screen and the adaptor
like in this image.

On the adaptor, check the markings of the 4 pins. Connect the GND to GND on the
Arduino, VCC to 5V. Then, connect SDA (“DAta”) to analog pin 4 on the Arduino Uno, and
DCL (“CLock”) to analog pin 5. You are not done with the wirings!

You now need to install an LCD I2C library that will replace the original LiquidCrystal library
that comes with the IDE. There are several options that you could use, but the one that I
found easy to use and tested for this lecture is the LiquidCrystal_I2C available here.
Download the ZIP archive from this page and install it in your IDE’s Libraries folder. Don’t
forget to restart the IDE for the install process to complete!

!
2
Peter Dalmaris Lecture 54 Arduino Step by Step

Sketch
Here’s the sketch, with annotations embedded.

#include <Wire.h>
 This library implements the I2C protocol.


#include <LCD.h>
 This library allows you to use various LCD displays.
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void setup(){

This library allows you to use the functionality offered
lcd.begin(16,2);
 by the standard LCD library via the I2C bus.
lcd.backlight();

lcd.setCursor(0, 0);

Initialise the lcd object that we’ll use to write to the
lcd.print("Hello world!");

screen. The first parameter “0x27” is the I2C address
lcd.setCursor(0, 1);
 of the adaptor (more about this further down). The
lcd.print("Row number: ");
 rest of the parameters are:
lcd.setCursor(12, 1);
 !
1: Device address
lcd.print("2");
 2: LCD screen enable (“En”) pin
} 3: LCD screen read/write (“R/W”) pin
4: LCD screen reset (“Rs”) pin
void loop(){
 5: LCD screen data 0 pin
} 6: LCD screen data 1 pin
7: LCD screen data 2 pin
8: LCD screen data 3 pin
Same use of LCD functions 9: LCD screen backlight pin
as we saw in lecture 24. 10: LCD screen backlight polarity (POSITIVE or
NEGATIVE)

About I2C addresses


Because I2C is a shared serial bus, we need a way for each connected device to be able to
detect which of the messages that are flowing through the common wires is meant to be
read by them. On the flip side, the Arduino (or any master device) needs to be able to
determine which of the connected devices transmitted a message.

This is achieved by setting an address for each connected device. This address needs to
be unique within the group of the devices that are sharing the bus. Most devices, like the
LCD adaptor in this demo, come with an I2C address preset from factory that, in my
experience, does not conflict with addresses from other devices as long as they are not of
the same type. For example, if you connect an LCD screen adaptor and a real-time clock to
the same I2C bus, chances are that there will be no conflict with their preset addresses and
they will work out of the box.

But let’s say you wanted to attach two LCD screens to the same I2C bus, using two
separate, but of the same type, LCD adaptors. In this case, you will need to change the
address of one of the two adaptors. Most I2C devices provide a way to do this, usually by
changing the configuration of jumpers or soldering address pins.

3
Peter Dalmaris Lecture 54 Arduino Step by Step

If you take a look at the front side


of the 1602LCD board, you will
notice 3 pads. By bridging those
pads vertically (a bit of solder will
do), you can change the I2C
address of the device. The
1602LCD provides 3 pairs of
pads, so you can have a total of 7
possible addresses.

Demo 2: I2C bus sharing by a LCD screen and a


real-time clock
In the second demo, we’ll combine 2 devices on the same I2C bus. We’ll use the LCD
adaptor from Demo 1, and the real-time clock from Lecture 48.

Here is what we are going to build:

1. Plug the DS1307 real-time clock at


the left end of the mini breadboard.

2. Plug the 16x2 LCD screen at the


right bottom end of the
breadboard.

3. Plug the LCD adaptor so that its


pins are aligned correctly with the
7 4
LCD screen, like we did in Demo 1.

3
4. Plug the Arduino GND and 5V pins
to the power strip at the top of the 5,6
1
breadboard.

5. Using the breadboard socket 2


column where the real-time clock
PCB is connected, connect the
SDA and SCL pins of the LCD adaptor to the corresponding pins of the real-time clock.

6. Using the same columns as in step 5, connect the SDA wire to Arduino Uno analog pin
4 and the SCL wire to the Arduino Uno analog pin 5.

7. Connect the power wires from the LCD adaptor and the real-time clock to the
breadboard’s top power power strip.

By default, the DS1307 is listening to I2C address 0x68 while the LCD adaptor to address
0x27 so there is no conflict.

4
Peter Dalmaris Lecture 54 Arduino Step by Step

Sketch
Let’s have a look at the sketch. Comments are embedded.

#include <Wire.h>

#include "RTClib.h"

#include <LCD.h>

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

RTC_DS1307 rtc;
Same as in Demo 1
void setup () {

Add the real-time clock library
Serial.begin(9600);

Wire.begin();
 Start the I2C bus.
lcd.begin(16,2);

Start the LCD screen with 16 columns, 2 rows, and
lcd.backlight();
 turn backlight on.
rtc.begin();

rtc.adjust(DateTime(__DATE__, __TIME__)); Start

 the real-time clock module, and set the time
and date to the system time and date during
}
compilation.

void loop () {

DateTime now = rtc.now();
 Get the time from the real-time
Serial.print(now.year(), DEC); Serial.print('/');
 clock and print it to the Serial
Serial.print(now.month(), DEC); Serial.print('/');
 monitor.

Serial.print(now.day(), DEC); Serial.print(' ');



Serial.print(now.hour(), DEC); Serial.print(':');

Serial.print(now.minute(), DEC); Serial.print(':');

Serial.print(now.second(), DEC); Serial.println();

lcd.setCursor(0, 0);

lcd.print(now.year(), DEC); lcd.print('/');
 Set the LCD cursor to column 0,
row 0, and print the year in
if (now.month()<10)
 decimal notation, followed by a
{ lcd.print("0"); }
 “/“.
lcd.print(now.month(), DEC); lcd.print('/');
 If the month is single digit, then
if (now.day()<10)
 add a “0” in before printing the
{ lcd.print("0"); }
 month digit so that the month
segment always aligns well.
lcd.print(now.day(), DEC);

lcd.setCursor(0, 1);
 Print the month, followed by a “/“.
if (now.hour()<10)

Similarly to printing out the month,
{ lcd.print("0"); }
 add a “0” in front of single digit
lcd.print(now.hour(), DEC); lcd.print(':');
 days, hours, minutes and seconds.
if (now.minute()<10)

{ lcd.print("0"); }

lcd.print(now.minute(), DEC); lcd.print(':');

if (now.second()<10)

{ lcd.print("0"); }

lcd.print(now.second(), DEC); 

delay(100);

}
5
Peter Dalmaris Lecture 54 Arduino Step by Step

Conclusion and exercise


You now know how to connect an LCD screen to your Arduino using a single data wire, and
how to combine multiple devices on a single I2C bus.

In this lecture, we used a real-time clock with an LCD parallel to serial adaptor. As an
exercise, try to add one or two additional IC2 devices. Here’s some recommendations:

* Add a BMP085 temperature and barometric sensor. We saw this device in lecture 9.
Display the temperature and humidity in the LCD screen.

* Add an SD card module. We saw this device in lecture 45. Store BMP085 readings in a
log file.

* A total of 127 can be attached to an I2C bus. Here is a sketch that can detect and report
all connected devices, try it out: http://playground.arduino.cc/Main/I2cScanner

* Although we have not yet discussed adding external EEPROM modules to your Arduino,
understanding how they work easy based on your existing knowledge. You can consider
the AT24C256 Serial EEPROM device, an inexpensive way to add memory to your
project. It uses the I2C interface, and is easy to use with the appropriate library.

6
Peter Dalmaris Interrupts Arduino Step by Step

Interrupts
!
Up to now in our examples, we have been using the loop() function to periodically poll
things like sensors and buttons for their values. For example, in the push button lecture we
used this sketch to check on whether the button was pressed or not and light up an LED if
it was (only showing the loop() function and the code that is relevant here):

void loop()

{

int val = digitalRead(inputPin); // read input value

… Turn an LED on if the inputPin is HIGH …

}

The Arduino checks (digitalRead) the voltage level in the inputPin and then does some
processing depending on the value that was read. The digitalRead will execute regardless
of whether the button was actually pressed or not. If we execute this code on an
Atmega328 which typically runs at 8MhZ will roughly poll the inputPin 8 million times per
second, and every one of these measurements will come out false since most of the time
the button is not pressed. This is a great waste of resources.

But it can get worse. If the Arduino needs to do other work within the loop, like check on
other sensors or communicate with a web service, it is possible that when the user presses
on the button, the Arduino will never notice because it had not yet reached the digitalRead
instruction at the time of the button press. The Arduino was busy doing something else.

This problem can be solved with an Atmega 328 feature called Hardware Interrupt. This
lecture will show you how to use the hardware interrupt. In the this lecture, I will also show
you how to use a relevant feature called the Time Interrupt.

Hardware Interrupt
A hardware interrupt provides the ability to tie a special pin with a function in your sketch
that will be executed with priority when the state of the pin changes in a particular way.

You can configure the pin and the kind of signal you want to generate an interrupt request,
and tie this to a small interrupt request function. This function is meant to handle the
interrupt. I will give you an example in a minute.

Each Atmega micro-controller has a specific set of pins that can be used as interrupt pins.
For the Atmega328p (which you find in the Arduino Uno) these are digital pins 2 and 3. The
Arduino Mega, which is based on the Atmega2560, provides interrupts in pins 2, 3, 18, 19,
20, and 21.

Each interrupt is identified by a interrupt number, like 0, 1, 3, etc.

1
Peter Dalmaris Interrupts Arduino Step by Step

This table contains the interrupt numbers and associated pins for the more popular
Arduinos:

Table 1: Interrup IDs and pins for some popular Arduinos


Board int.0 int.1 int.2 int.3 int.4 int.5

Uno, 2 3        
Ethernet
Mega2560 2 3 21 20 19 18

Leonardo 3 2 0 1 7  

Let’s have a look at our first hardware interrupt example and discuss some of the
implementation details.

Demo 1
In this first demo, we’ll take the circuit from Lecture 16 and only modify the sketch it so that
the LED is lit as a response to an interrupt generated by the button, instead of by polling the
state of the button a few million times per second.

We’ll use the same circuit as in Lecture 16. We


have a push button and a pull-up resistor
connected to digital pin 2, and an LED with its
protective resistor connected to digital pin 13.
You can skip this LED if you prefer and just use
the build LED on the Arduino itself.

Here’s the list of parts:

• A standard push button

• A pull-up resistor, around 40kΩ.

• A 5mm LED

• A 1kΩ resistor for the LED.

That’s simple enough, let’s move to the sketch.


Comments are embedded.

2
Peter Dalmaris Interrupts Arduino Step by Step

const int ledPin = 13; 
 We’ll connect the button to digital pin 2. This pin
const int inputPin = 2; corresponds to interrupt number 0 for the Uno.

void setup() { 
 Set the LED pin to 13.


pinMode(ledPin, OUTPUT);

attachInterrupt(0,buttonPressed,FALLING);

}
Setup the interrupt handler. Here are the parameters:

void loop()
 Nothing - 0: Interrupt ID 0, which is digital pin 2

{ 
 happening - buttonPressed: the name of the interrupt handler
here! function
}
- FALLING: an interrupt is captured when the signal
level in pin 2 goes from HIGH to LOW
void buttonPressed()

{

if (digitalRead(ledPin))
 The interrupt handler function. You can’t pass any
digitalWrite(ledPin,LOW); 
 parameters of return any data. Keep processing to
else
 a minimum.

digitalWrite(ledPin,HIGH); 

}

In this small sketch, notice how the loop() function is empty. We are going to handle the
button presses in a separate function, buttonPressed(). The name of the function is not
important, you can choose an valid identifier.

In the setup() function, we create the interrupt by calling the attachInterrupt function. This
function requires three parameters:

1. The interrupt ID. This is an integer that corresponds to the ping where we attach the
interrupt device. The IDs for some of the popular Arduinos are shown in Table 1. In the
sketch, we use ID 0, which corresponds to digital pin 2.

2. The interrupt handler function name. This function contains a small amount of code,
just enough to handle the interrupt and then allow the Arduino to continue with
whatever it was doing before the interrupt.

3. Interrupt mode, which is the kind of event that should trigger an interrupt. With this
parameter you are telling the Arduino the type of electrical event it should be monitoring
which would be perceived as an interrupt. In the example sketch, the literal “FALLING”
tells the Arduino to look out for voltage that goes from HIGH to LOW, and when it
detects that to interpret it as an interrupt. Table 2 (below) contains a list of valid
interrupt modes.

3
Peter Dalmaris Interrupts Arduino Step by Step

Table 2: Interrupt modes


Mode Description

LOW Trigger the interrupt whenever the pin is LOW


CHANGE Trigger the interrupt whenever the pin changes value

RISING Trigger when the pin goes from LOW to HIGH

FALLING Trigger the interrupt when the pin goes from HIGH to LOW

HIGH Trigger the interrupt whenever the pin is HIGH (only available in the
Arduino Due)

In the sketch’s present form, the LED will light up when you press and release the button,
then light down when you press and release again. Try this small variation: change the line

attachInterrupt(0,buttonPressed,FALLING);

to

attachInterrupt(0,buttonPressed,CHANGE);

… then compile and upload the sketch. Press the button a few times and observe the
behaviour of the LED. What do you see? (Hint: The LED now lights-up when you press the
button, and remains lit until you release the button).

Things to remember about hardware interrupts


Hardware interrupts have certain constraints that you need to keep in mind when you
design your app. Here they are in a nutshell.

1. You cannot pass a parameter to the interrupt handler function.

Hardware interrupts are designed to capture simple events from the outside world. As a
result, parameters like those passed to functions make no sense.

2. The interrupt handler function cannot return any data (a way around this problem is
suggested in Demo 2), and their return type should always be void.

Same thinking goes here. The interrupt originated from the outside world, something like a
button. It makes no sense to return a value to a button. However, there is a use case where
we need the interrupt handler to update the value of a variable in our sketch, like a counter.
This is possible, and I’ll show you how in Demo 2.

3. Interrupt request handlers should be as small as possible.

While the interrupt request handler is running, all interrupts on the micro-controller are
disabled. If you have attached a second button to the second interruptible pin on the
Arduino Uno and you press it while the micro-controller is in the handler of the first button,

4
Peter Dalmaris Interrupts Arduino Step by Step

then the second button press will be ignored. In fact, anything that uses interrupts will not
work while an interrupt request is being serviced. This includes things like the delay() and
millis() functions, and the loop() function also will be stuck to the line it was at when the
interrupt happened.

4. It is possible to disable hardware interrupts anywhere in your sketch. To do this, use the
interrupts() and noInterrupts() functions. The former one will enable interrupts, while the
second one will disable them. You may want to do something like this in cases where you
are timing an event and you want your measurement to be accurate, when you are writing
serial data to an external device like an SD card or similar. Your code could look a bit like
this:

void loop()

Turn off hardware interrupts.
{

noInterrupts();

Here’s the code that should not be interrupted.
// critical, time-sensitive code here

interrupts();

Turn on hardware interrupts.
// other code here

}

The critical code that should not be interrupted can simply be code that modifies a variable
that may also be modified from inside a interrupt handler function. More about such
variables is discussed in Demo 2.

5
Peter Dalmaris Interrupts Arduino Step by Step

Demo 2: Use a volatile variable


In the second demo, we’ll add a volatile variable which the code in the interrupt request
function will be able to access and update.

This variable will keep track of the number of times that we have pressed on the button.

Here’s the sketch with comments embedded, a discussion follows.

const int ledPin = 13; 



We declare a byte (8 bits) variable named “counter”
const int inputPin = 2;

and initialize it to zero. We mark it with the “volatile”
volatile byte counter = 0; keyword to indicate to the compiler that this variable
may change at any time and should not be cached in
void setup() { 
 a CPU register but instead should be always loaded
pinMode(ledPin, OUTPUT);
 from the RAM.
attachInterrupt(0,buttonPressed,FALLING);

Serial.begin(9600);

}

void loop()

{ 

}

void buttonPressed()

{
 Increase the counter by 1.
counter++;

Serial.println(counter, DEC);
 Print the value stored in “counter”, format it as a
decimal.
if (digitalRead(ledPin))

digitalWrite(ledPin,LOW); 

else

digitalWrite(ledPin,HIGH); 

}

In this sketch, the only difference is the addition of the volatile byte variable “counter” and
the increment operator on this counter in the interrupt handler function. We also print the
value of this counter every time it gets updated.

So what exactly is the purpose of the “volatile” keyword? If the keyword is not used, then
the compiler will generate machine code that optimises the use of this variable by caching it
in a CPU register whenever possible. For example, if the counter variable is used inside a
loop, then it is possible that instead of storing the value of the variable in RAM, it will be
stored in one of the available registers. A CPU register is several times faster than the RAM,
and therefore this caching represents a gain in performance. By indicating to the compiler
that “counter” is volatile, the compiler mark it so that it will never be cached in a register.
Instead, it will be always stored and fetched from the RAM, meaning that it will be always

6
Peter Dalmaris Interrupts Arduino Step by Step

current, regardless of whether it is manipulated by code in the loop() function or in an


interrupt handler function.

Before finishing the Demo, consider the case where you would like to print (or just access)
the value stored in the counter variable inside the loop function. You can add the code for
this inside the loop function like this:

loop(){

Serial.println(counter);

}

The problem with this is that the println instruction may try to access the counter variable at
the precise moment when an interrupt request is generated by the button. In this case, the
value that is printed is not possible to determine. to guard against such situation, we
enclose the instruction that accesses the volatile variable within a noInterrupts() and
interrupts() block, like this:

loop(){

noInterupts();

Serial.println(counter);

interrupts();

}

With this guard in place, a button press during the time that the Serial.println instruction is
being executed will be ignored. The chances of this happening while an actual button press
are few, as long as you keep the processing that is happening within the noInterupts() and
interrupts() block to a minimum.

7
Peter Dalmaris Interrupts Arduino Step by Step

Demo 3: Timer interrupts


A timer interrupt is an interrupt that the Atmega generates using an internal timer, rather
than an external event.

You could create, for example, a sketch that checks on a sensor every 5 seconds without
using the delay function. A timer interrupt can be easily set with the help of the TimerOne
library and can be use to create timers from 1ms to 8,388,480 or around 8.4 seconds.

In this demo, we’ll make an LED blink by setting a timer to trigger an interrupt once every
second. The sketch follows, with embedded comments:

#include <TimerOne.h> A library that makes it easy to use timer interrupts,


written by Simon Monk.
int ledPin = 13;

volatile int ledState = HIGH;

void setup()
 Initialize the timer and set the period duration. The
{
 parameter is in microseconds. One second is one
million microseconds.
pinMode(13, OUTPUT);

Timer1.initialize(1000000);

Timer1.attachInterrupt(toggleLED); 

}
Attach the timer interrupt to a handler function.
void loop(){ }

void toggleLED()

{
 The interrupt handler simply toggles that state
digitalWrite(ledPin, ledState);
 of the LED.
ledState = !ledState; 

}

First, include the TimerOne library in the sketch. The one I used is a newer and enhanced
fork of the original TimerOne, and you can download it from https://github.com/
PaulStoffregen/TimerOne.

In the setup() function, we initialize the timer with a value that represents the period duration
in microseconds. So, 1 second is equal to 1 million microseconds. Then, we attach the
timer interrupt to a function that will handle it, by name.

In the interrupt handler, we set the LED state, which is updated every time the function is
called. The instruction ledState = !ledState takes whatever value is currently stored in
ledState, flips it, and stores the new value to itself.

!
!
8
Peter Dalmaris Interrupts Arduino Step by Step

Demo 4: High-definition PWM


The TimerOne library also contains several other useful functions that you can explore. One
of them provides that ability to create very accurate PWM output. Normally, using the
analogWrite function, you can create PWM output on a scale from 0 to 255.

Calling this:

analogWrite(127);

… will create a PWM waveform with a duty cycle of 49.80% (since 255 -> 100%).

Calling this:

analogWrite(128);

… (notice that we just went from 127 to 128), will create a PWM waveform with duty cycle
of 50.19%.

If you are trying to generate more accurate waveforms, you can do it using the TimeOne
library like this:

Timer1.pwm(pin, duty);

… where “pin” is a digital pin that the library supports, and “duty” is an integer from 0 to
1024.

In the Arduino Uno, we can use pins 9 and 10. See the library’s documentation for
information on pin support in other models.

So, this:

Timer1.pwm(9,300);

… would have a duty cycle of 29.29% (since 1024 -> 100%), and

Timer1.pwm(9,301);

… would have a duty cycle of 29.39%. You can see how with TimeOne you have much finer
control over the waveform that your PWM pin is able to produce.

9
Peter Dalmaris Interrupts Arduino Step by Step

Connect the LED to digital pin 9, and try out this sketch:

#include <TimerOne.h>
Set the overall period to 1000 microseconds. Playing
int ledPin = 9; around with this value does not produce any
dramatic effect, so don’t worry too much about it.
void setup()

{
 Initialise the initial PWM duty cycle to 0 out of 1024.
Timer1.initialize(1000);
 We need to use the pwm function at least once
Timer1.pwm(ledPin,0);
 before using the setPwmDuty to change the duty
cycle later.
pinMode(ledPin, OUTPUT);

}

void loop(){

Timer1.setPwmDuty(ledPin, 250);

delay(1000);

Timer1.setPwmDuty(ledPin, 500);

delay(1000);
 Change the PWM duty cycle to a new level, then
Timer1.setPwmDuty(ledPin, 800);
 wait for a second.
delay(1000);

Timer1.setPwmDuty(ledPin, 1024);

delay(1000);

}

You should see that the LED lights up very gradually and finely, the effect of the small
increase in the PWM duty cycle will every loop cycle.

Conclusion
In this lecture you learned about hardware and timer interrupts, how to handle them, where
they might be useful, and some of their limitations.

Often, interrupts are the ideal solution to getting the Arduino to respond to events that are
infrequent without unnecessary waste of resources. But think carefully before you make use
of them, they can often be difficult to debug, especially when you have implemented more
than trivial functionality.

10
Peter Dalmaris Shift Registers Arduino Step by Step

Shift registers
The Arduino only has a relatively small number of digital outputs. While there are enough of
them to get us through the examples in this course, in most real life projects they will be not
enough.

Take, for example, the the case of a gadget that contains a character LCD screen, a couple
of status LED, a couple of buttons, and a couple of sensors and a Wifi breakout. You will
need 2 pins for the screen (using the serial to parallel adaptor), 2 for the LEDs, 2 for the
buttons, at least 2 for the sensors, and 6 for the Wifi breakout. That more or less exhausts
the available ports.

Sooner or later you will need a way to multiply the available inputs and outputs so that you
can connect a larger variety of peripherals.

In this lecture, I’ll show you how to use shift registers to multiply the available digital
outputs. In a later lecture I will also introduce you to I2C-driven port expanders. These
technologies make it possible to design ever larger and realistic gadgets using a single low
cost micro-controller.

Before getting into it, I should highlight that more available ports do not automatically
guarantee that you will be able to create larger gadgets. Once the input/output port
availability is dealt with, the next potential show stopper is memory. At 32Kbytes of flash
memory, it becomes difficult to create sketches that match the ever growing hardware they
are supposed to drive. So, also in a later lecture I will talk about ways to manage and
optimise memory use.

1
Peter Dalmaris Shift Registers Arduino Step by Step

What is a shift register?


Think of a shift register as a single-byte memory. Each of the bits in this memory is
connected to the outside world via a pin on the package of the chip that contains the
memory. You use a single data pin from the Arduino to write each bit, one at a time.

Because each bit is written individually, and all bits can be read all at once, we say that a
shift-register is a device that supports serial in and parallel out.

To support the serial transfer of bits from the Arduino to the shift register chip, we need a
second pin that provides a clock signal. Every time the clock ticks, one bit is transmitted
from the Arduino to the shift register. Once the new bit is received by the shift register, all
existing bits are shifter by one bit to make room for the new one. This shifting process is
what gave the name “shift register” to this device. Here’s a graphical way to look at this
process:

Let’s say that we’d like to store the byte 11001101 in the shift register represented by this
table. At start, the shift register has an undeterminable state, so I’ll represent this with a
question mark.

This is Step 0:
? ? ? ? ? ? ? ?

In Step 1, we’ll take the least significant bit (first from the right - 11001101), wait for the
clock to tick, and shift it in the register. We could have chosen to start with the most
significant bit just the same.

This is Step 1:
1 ? ? ? ? ? ? ? ?

Notice the grey box at the end of the register. This is an additional “overflow” bit memory
that stores the bit that was shifted into it from the bit on its left. We will be using this
overflow bit in Demo 2 when we create a circuit that uses two shift registers connected in
series.

In Step 2, we’ll take the next least significant bit (second from the right - 11001101), wait for
the clock to tick, and shift it in the register. Notice that the original first most significant bit
(“1”) is greyed out to show that it has already been transmitted to the register. We now also
have the first bit that shifts out of the overflow bit and is lost for all eternity. I’m only
including it here outside the register to emphasise the outcome of the shift function.

This is Step 2:
0 1 ? ? ? ? ? ? ? ?

In Step 3, the same process continues: clock ticks, next bit in “11001101” is sent to the
shift register, and all existing bit in the register are shifted one position to the right to make
room for the new bit.

1 0 1 ? ? ? ? ? ? ??
This is Step 3:

I will speed up the rest of the sequence:


2
Peter Dalmaris Shift Registers Arduino Step by Step

This is Step 4 “11001101”:

! 1 1 0 1 ? ? ? ? ? ???

!
This is Step 5 “11001101”:

! 0 1 1 0 1 ? ? ? ? ????
!
This is Step 6 “11001101”:

!
0 0 1 1 0 1 ? ? ?
! ?????

This is Step 7 “11001101”:

!
1 0 0 1 1 0 1 ? ? ??????
!
This is Step 8 “11001101”:

!
1 1 0 0 1 1 0 1 ? ???????
!
And finally, the complete byte has been shifted into the shift register. You can sent single
bits to the register, its not necessary to do so for a whole byte (though most libraries make
the latter easier than the former). For example, let’s say that you wanted to sent a “0” to the
register, which already contains the values from the previous experiment. You would end up
with these new contents in the register:

! 0 1 1 0 0 1 1 0 1 ????????
!
The original least significant bit from the first experiment has now been shifted into the
overflow bit cell to make room for the new value at the left end of the register.

Another way to think about the way that this register operates is “FIFO”: First bit in is First
bit out.

I hope you have a solid understanding of this process now, it will make it easy to
understand what is happening with Demo 1 which follows. If you feel unclear about
something, read this section again or ask a question in the forum.


3
Peter Dalmaris Shift Registers Arduino Step by Step

Demo 1: Drive 8 LEDs with a single data wire


Normally, to drive an LED you need to connect it to one of the Arduino’s outputs. If you
need to drive two LEDs, then you need 2 outputs. Etc. Etc.

In this demo, we’ll drive LEDs by using a single data wire, with the help of a shift register.
Shift register chips are very cheap and made by many different companies. A typical one is
the 74HC595N. This device provides 8-bit storage, plus one for the overflow. The particular
one I used is made by NXP, and you can find it’s datasheet here. The first thing you want to
look at in the datasheet is the pin out diagram so that you can see the functionality of each
pin. I have grabbed this from the datasheet. I define the pin functions in the table next to
the diagram.

Pin # Symbol Description

1-7 Q1-Q7 Data out pins 1 to 7. Notice that Q0 is


on pin 15
8 GND Ground

9 Q7S This is the overflow bit. It will store the


bit shifted out of Q7.
10 MR Master reset. If this pin is grounded,
inverted the chip is reset. We’ll keep it
connected to 5V.
11 SHCP Clock input. This pin will receive the
clock pulses from the Arduino. With
each clock pulse, the bits are shifted.
12 STCP Latch. Make this LOW while the bits
are shifting to prevent devices
connected to the outputs from
reading transient values (values are
“frozen” to those before shifting
begun). Once the bit shifting is
complete, make this HIGH to allow
the connected devices to read the
new values.
! 13 OE Enable or disable output pins. We will
inverted keep it always connected to GND so
that outputs are always enabled.
14 DS The data pin. The Arduino will use this
pin to sent the bit values to the shift
register.
15 Q0 Data out for bit 0.

16 Vcc Power in (5V)

4
Peter Dalmaris Shift Registers Arduino Step by Step

The circuit for this demo is this:

!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
We’ll use 220Ω or close resistors for each LED. Start with the 74HC595N chip on one side
of the breadboard, then connect the LEDs and their resistors. Then, do the wiring between
the LEDs and the D0-D7 pins on the chip.

Then, connect the chip to the Arduino like this:

• Chip Pin 11 to Arduino Pin 12

• Chip Pin 12 to Arduino Pin 8

• Chip Pin 14 to Arduino Pin 11

5
Peter Dalmaris Shift Registers Arduino Step by Step

Connect the 5V breadboard rail to Pins 16 and 10 on the chip, and ground to Pin 8 on the
chip. Chip pins 9 and 13 are not connected to anything at the moment.

If everything is connected properly, then once you apply power for the first time, the LEDs
will light up at a random pattern. They will show whatever is stored in the shift register. Let’s
have a look at the sketch and see how we can change the pattern.


const int latchPin = 9;

Set the Data, Clock and Latch pins. These are
const int clockPin = 10;

pins 14, 9, and 10 respectively on the chip.
const int dataPin = 8;

void setup() {
 All three pins are outputs, so configure them as


pinMode(latchPin, OUTPUT);
 such.
pinMode(dataPin, OUTPUT); 

pinMode(clockPin, OUTPUT);
 We’ll use an Arduino function that generates
pseudorandom numbers. Here, we use
Serial.begin(9600);
 randomSeed to initialize the generator with a
randomSeed(analogRead(0));
 random value obtained from pin 0. When this pin
} is not connected to anything, its value is as
random as it can get, so it is a good seed for the
generator.
void loop() {

byte randNumber1 = random(255);
 Create a new random number, from 0 to 255.
writeLeds(randNumber1);
 Store this as a byte. Because the maximum
delay(100); 
 decimal is 255, which in binary is “11111111”, we
} ensure that a full random byte is generated. Then,
pass this random byte as a parameter to the
writeLeds function, which will pass it to the shift
void writeLeds(byte pattern)
 register, and wait for 100 milliseconds.
{

digitalWrite(latchPin, LOW);
 We are about to shift bits into
Serial.println(pattern,BIN);
 the register, so take the Latch
LOW to hide the new values
shiftOut(dataPin, clockPin, MSBFIRST, pattern);
 until we are ready to reveal
digitalWrite(latchPin, HIGH);
 them (the full byte has been
} shifted in).

! With the shifting process


completed, we can now
Use the shiftOut function to handle the shifting of the byte, so
we don’t have to worry about clock timing and bit manipulation.
! restore the Latch value to
HIGH so that the new
Pass the data and clock pin numbers, indicate which bit should
be shifted first (we choose Most Significant bit First here, i.e.
values are revealed to the the first bit from the left), and the byte to be shifted out.
! LEDs.

Plug in your Arduino and upload the sketch. You should see the LEDs blinking in random
patterns, like this (next page):

!
!
!
6
Peter Dalmaris Shift Registers Arduino Step by Step

!
!

!
Perhaps now you can see how a shift register can be used to allow your sketch to control
an arbitrary number of external devices. Instead of LEDs, you could be controlling relays or
transistors as switches for higher loads (that is, devices that require a lot of power to run). It
is even possible to use shift registers as an input, whereby the shift register reads all inputs
in parallel, and then shifts them out in a serial manner to a reading device (like the Arduino).
An example of such a parallel-in serial-out register is the SN74ALS164A (link will open it’s
data sheet).

Another consideration is power. The 74HC595N can provide less than 20mA for each
output pin, and in our circuit it draws this power from the Arduino’s power supply. If the
load placed on it exceeds a certain limit, the circuit will either not work or it will be damaged
if it is forced to exceed its specifications. In such situations, you can consider providing a
separate power supply for the 74HC595N and for it’s loads (like the LEDs). You can do this
with a simple transistor amplifier circuit, or by segmenting the driver circuit (the 74HC595N
and the Arduino) from its load with relays. 


7
Peter Dalmaris Shift Registers Arduino Step by Step

Demo 2: upgrade to 16 LEDs


In demo 2, we’ll add a second 74HC595N to our circuit and drive an impressive 16-LED
array, all lighting up in random patterns, while still only using a single data wire on the
Arduino (plus latch and clock). Here’s the circuit, it really is simpler than what it looks:

The circuit from Demo 1 is on the left of the breadboard. The new part on the right is made
of the same arrangement of LEDs and resistors, plus the second 74HC595N. Because
there’s so many LEDs drawing a few mA of power each at random times, there will be a
strain on the Arduino’s power supply. To smooth out spikes in consumption, I have added
an electrolytic capacitor directly on the power rails of the breadboards. The one I used in
my circuit is 220μF. Be careful of the polarity, it is clearly marked on the package of the
capacitor. If you remember, we used a capacitor in the exact same way in the servo motor
lecture.

Let’s concentrate on the second 74HC59N (Chip 2) for a moment. The first 74HC59N is
Chip 1. Connect it like this:

• Chip 2 Pin 11 to Chip 1 Pin 11

• Chip 2 Pin 12 to Chip 1 Pin 12

• Chip 2 Pin 14 to Chip 1 Pin 9 Q7S (this establishes the daisy chaining of the two chips)

8
Peter Dalmaris Shift Registers Arduino Step by Step

Connect the 5V breadboard rail to Pins 16 and 10 on Chip 2, and ground to Pin 8 on Chip 2.
Chip 2 pins 9 and 13 are not connected to anything.

This is the sketch. It’s almost identical to the sketch in demo 1. The only differences are
highlighted below.

const int latchPin = 9;



const int clockPin = 10;

const int dataPin = 8;

void setup() {

pinMode(latchPin, OUTPUT);

pinMode(dataPin, OUTPUT); 

pinMode(clockPin, OUTPUT);

Serial.begin(9600);

randomSeed(analogRead(0));

}

void loop() {

byte randNumber1 = random(255);

byte randNumber2 = random(255);
 Generate a second random byte, just like in Demo
1. Write the second random byte to the 16-bit
writeLeds(randNumber1);
 shift register by calling writeLeds twice.
writeLeds(randNumber2);

delay(100); 

}

void writeLeds(byte pattern)



{

digitalWrite(latchPin, LOW);

Serial.println(pattern,BIN);

shiftOut(dataPin, clockPin, MSBFIRST, pattern);

digitalWrite(latchPin, HIGH);

}

!
The only change to the sketch is the addition of a second random byte, and a second call
to the writeLeds function. The first call will transmit the first random byte, and the second
call will transmit the second random byte.

This is what is happening: as the bits stored in the first 74HC59N are shifted out by the bits
of the second byte, one by one they are pushed into the overflow bit cell. This is Pin 9 Q7S
on Chip 1. As Chip 2 has its Pin 14 (Data pin) connected to Chip 1 Pin 9, it will pick the
overflow bit and start shifting it in its own cells. Since Chip 1 and 2 share the same latch
and clock signals, they will be synchronised and work together as a single 16-bit shift
register. You can daisy chain as many 74HC59N units you like like this, the concept is the
same.

9
Peter Dalmaris Shift Registers Arduino Step by Step

The Demo 2 circuit in operation.

Conclusion
Shift registers operate on a very simple principle, however from experience I know it is a topic that
tends to confuse new makers. Hang in there, read again, experiment with the circuits, and ask if you
run into trouble. Once you understand the basics, you will be able to use them without much effort.

!
I will come back to shift registers in an upcoming lecture on 7-segment displays.

!
As an exercise, try this: modify the sketch for Demo 1 so that you can type in a number from 0 to 255
and have the binary representation of that number show in on the LEDs. You will need to figure out
how to enter text in the console (I have shown you how to do this in a previous lecture).

!
You can also try this: modify the sketch from Demo 1 so that the number of LEDs lit depends on the
value coming out of a potentiometer. When the potentiometer is turn all the way to one direction, you
will have no LEDs lit, when it’s all the way to the other direction you will have all of the LEDs lit, and
accordingly for all other positions.

10
Peter Dalmaris Arduino Step by Step EEPROM

EEPROM
The Atmega microcontroller, as we have seen already, contains 3 types of memory: There’s
flash (where the sketch is stored), SRAM (where temporary data are stored), and EEPROM.

SRAM (Static RAM) can store data for as long as power is provided. Turn off the power, and
everything is the SRAM is lost.

Both flash and EEPROM memories persist after the power is cut, so you could use either
one for long term data storage, a bit like a hard disk works. But here’s the difference: flash
memory can only be changed when a new program is uploaded to the Arduino. People
often refer to this process as “flashing”. Once flashing is completed and the newly
uploaded sketch is in place, you cannot change anything in the flash memory.

That’s where EEPROM comes in. EEPROM stands for “Electrically Erasable Programmable
Read-Only Memory”, and you can use it to store data that must be preserved even after
power is lost. You could use EEPROM to store configuration values for your sketch that the
user can modify, passwords, sensor logs and things of that sort.

In this lecture, you will learn how to use internal and external EEPROM. As a bonus, I will
show you how to create a small library so that you can simplify your sketch organisation
and reuse utility code.

Demo 1: Using the Internal EERPOM


The Atmega328 contains 1KByte of internal EEPROM. That means that you can store and
persist 1024 words, where each word is made up of 8 bits in your Arduino Uno. For this
demo, we will not use any external hardware, just plug your Arduino to your computer and
you’re good to go.

In this first demo, we’ll use two sketches to write and read a pin number for a basic security
system. The writing sketch will write the default pin in a specific internal EEPROM memory
location, and the reading sketch will simply go to that location and read back the pin.
Keeping things simple, we are not going to worry about LCD screens, a keypad for the pin
entry, or encryption for storing the pin securely.

The pin we’ll write and read is an integer. On the Atmega, integers consume two bytes, and
we will need to take this into account in our sketch since EEPROMs are byte-addressable.
This means that each byte has its own address, and we can’t simple store an integer like
we do with the RAM, where the compiler knows how to deal with integer (and other data-
type) addressing. With the EEPROM, while using the basic facilities that come with the IDE,
we have to split an integer to two bytes, store each byte individually, and then again
separately retrieve the two bytes and concatenate them so that we end up with the original
integer. Bear with me for now, in Demo 2 we’ll simplify this process a lot.

!
1
Peter Dalmaris Arduino Step by Step EEPROM

Here’s the writing sketch (Demo1_writer), let’s execute it and then go through it to explain
how it works.

A very basic library that comes with the IDE,


#include <EEPROM.h> allows your to read or write one byte at a time.

int addr = 0; The internal EEPROM address of the byte where


the sketch will write the first byte of the pin.
void setup()

{

Here’s the Pin, its an integer that needs to bytes
Serial.begin(9600);
 of storage.
int myPin=1234;

EEPROM.write(addr, highByte(myPin));
 highByte is a build-in function that
extracts the left-most byte (high-order) of
EEPROM.write(addr+1, lowByte(myPin));

an integer, or the second-lowest byte of
Serial.print("My pin recorded:");
 a multi-byte data type like a double
Serial.print(myPin);
 (which occupies four bytes).
Serial.println(".");

Similarly to highByte, lowByte is a build-
}
in function that extracts the right-most
byte (low-order) of an integer, or the any
void loop()
 multi-byte data type.
{ }

If we only wanted to store a byte, we would be able to just use EEPROM.write, pass an
address (from 0 to 1023), and the byte, and that would be all.

Unfortunately, the basic EEPROM library that comes with the IDE and we use in this sketch,
can only understand bytes, not integers or other multi-byte data types, so we have to take
care of some basic binary arithmetic.

The pin we selected, 1234, converted in binary format, looks like this:

high byte low byte


00000100 11010010
The byte on the right is the low byte, and the byte on the left is the high byte. We need to
store each one individually, so we call EEPROM.write, twice:

1. EEPROM.write(addr, highByte(myPin));

2. EEPROM.write(addr+1, lowByte(myPin));

First, take the high byte of the pin and store it in address 0, then take the low byte of the pin
and store it in address 0+1 = 1.

That’s all, the pin is now stored in the internal EEPROM. You would do the exact same thing
if you wanted to store a user setting. For example, if you had built an alarm clock, the user
could enter an alarm time, and you would store the time components in the EEPROM to
safe guard against power loss.

Now lets have a look at how to retrieve the pin.

2
Peter Dalmaris Arduino Step by Step EEPROM

In this sketch (Demo1_reader), we read the two bytes we stored earlier from the EEPROM,
and then we concatenate them so that we can recreate the original pin.

!
#include <EEPROM.h>

int addr = 0;
Declare the byte variables that will eventually
void setup()
 contain the two bytes of the original pin.
{

Serial.begin(9600);

byte retrievePinHigh;
 Retrieve the bytes from addresses 0 and
byte retrievePinLow;
 1, and store them in RAM.
retrievePinHigh = EEPROM.read(addr);

retrievePinLow = EEPROM.read(addr+1);
 Do some binary arithmetic (“<<“ bit shift
left) to assemble the pin from its two
Serial.println(retrievePinHigh);

parts.
Serial.println(retrievePinLow);

Serial.print("My pin is:");

Serial.print((retrievePinHigh << 8) + retrievePinLow);

Serial.println(".");

}

void loop()

{ }

!
Fetching the two bytes from the EEPROM is straight-forward. We use EEPROM.read, pass
the address of the byte we want to fetch, and store what is retrieved in a variable in RAM.

But how do we re-assemble the pin correctly? For that, we use the bitshift left operator.
There is also bitshift right.

Bitshift operators to exactly what their name says, they take a byte and move its bits left or
right by as many positions as we request.

For example, take this byte, and lets bitshift it to the left by 3 positions:

original 11001101
shifted 11001101000
Notice how all this operator did was to add three zeros to the right side of the byte, and
push everything to the left. We now have a binary number with 11 bits. That’s 8 original bits,
and 3 inserted bits.

3
Peter Dalmaris Arduino Step by Step EEPROM

If you do the opposite, i.e. bitshift to the right by 3 positions, you will end up with this
number:

11001
Notice how the bitshift right operator pushed the byte to the right, and this resulted to the
first three bits disappearing into the binary ether, and ending up with a 5 bit number.

So, this expression:

(retrievePinHigh << 8) + retrievePinLow


…first shifts the high byte by 8 positions to the left, effectively creating a 16 bit word, and
then adds the low byte. As a result, we have the original pin reconstructed. Here is the
whole thing:

High byte
00000100

High byte shifted to
the left by 8 bits.
00000100 00000000
Low byte
11010010
Shifted high byte and
low byte added. 00000100 11010010

!
And there you have it, your pin has been retrieved!

!
!

4
Peter Dalmaris Arduino Step by Step EEPROM

Demo 2: Gaining data type flexibility with the


EEPROM
Dealing with raw bytes may seem daunting at first, but with a bit of practice thinking in
bytes becomes almost second nature. Still, I find that often such low-level implementation
details slow us down. You really want to build a prototype quick, not to be caught up in
binary arithmetic, even when it’s as simple as what we saw in Demo 1. Personally, I find it
more efficient for my own productivity to work at a high-level (logical) rather than having to
worry about the hardware too much. If your gadget qualifies the prototyping phase, you can
always go back for a round of optimisations. So, in this demo, I’ll show you a way to
abstract the way that data is written to and read from the EEPROM in a bid to speed up
your personal productivity.

We will make use of the EEPROMex library, or EEPROM Extended. This library extends the
one that comes with the IDE so that it knows about all the common datatypes that we are
likely to use in Arduino sketches, not just the byte.

With EEPROMex, if you want to store or fetch an integer or a double, you just call the
appropriate method and the job is done. No need to think about bits, bytes, and bitshifting.

This abstraction and flexibility comes at the cost of flash memory - adding the library adds
a couple of kilobytes to your project sketch.

Get the library from its Github repository, install it in the Libraries folder, and restart the IDE.

The library is a drop-in replacement of the default EEPROM library, meaning that you can
just replace one for the other, and your sketch will still work. The extended library adds
functions for longs, ints, floats and doubles. You can also manipulate single bits (great for
better managing storage resources), arrays, strings, C structs, and it even provides an
update function that checks if a new value already exists in the EERPOM before saving it
again, thus extending its life span.

Here’s the updated write sketch (Demo2_write):

Replace EEPROM.h with EEPROMex.h


#include <EEPROMex.h>

int addr = 0;

void setup()

{
 Use EEPROM.writeInt to write an integer. No need
Serial.begin(9600);
 to worry about high and low bytes, and addresses
for each byte. Just pass the EEPROM address
int myPin=1234;
 where the integer should be store, and the
EEPROM.writeInt(addr, myPin);
 integer.
Serial.print("My pin recorded:");

Serial.print(myPin);

Serial.println(".");

}

5
Peter Dalmaris Arduino Step by Step EEPROM

void loop()

{ }

Once the original library has been replaced with EEPROMex.h, all we need to do is to use
the appropriate function depending on the data type we are working with. In the example,
EEPROM.writeInt will write the integer myPin to address addr.

Reading is just as easy:

#include <EEPROMex.h>

int addr = 0;

void setup()
 Used EEPROM.writeInt to write and integer? then


use EEPROM.readInt to read it back from the
{
 EEPROM.
Serial.begin(9600);

int retrievePin;

retrievePin = EEPROM.readInt(addr);

Serial.println(retrievePin);

Serial.print("My pin is:");

Serial.print(retrievePin);

Serial.println(".");

}

void loop()

{ }

You only need to use the corresponding read function for whichever write function you used
to write a value.

6
Peter Dalmaris Arduino Step by Step EEPROM

Demo 3: Using an external EEPROM


You now know how to use the internal EEPROM, but since it’s only 1KByte in size, you may
wonder what you can do in order to store more data. You may remember from the SD card
lecture, that SD cards is a good way to store lots of data persistently. However the SD card
module is a bit pricey (you can get one for $2-$10 depending on its bells and whistles), and
then you still need to add the cost and the size of the SD card itself (over $5), and the
complexity of using the card itself.

An external EEPROM is a good alternative. You can get a 256KByte external EEPROM for
around $1.5, store a lot more data in it as compared to the internal capacity, and you only
need a tiny amount of space on your printed circuit board. So let’s check this out.

I am using the Atmel


24C256 chip, which
provides 256KBytes of
EEPROM memory. It
communicates with the
Arduino via I2C, which is
great, you can connect
several chips if your
memory needs grow. The
module I purchased on
eBay also makes it easy
to change the device
address by bridging the
pins marked A0, A1, and
A2.

Here are the connections:

!
Arduino EEPROM module
!
5V VCC
!
GND GND

!
A4 SDA

!
A5 SCL

!
!

7
Peter Dalmaris Arduino Step by Step EEPROM

To communicate with an I2C device, we need to know its I2C address. I had no idea what
my EEPROM’s address was, so I used an I2C device scanner sketch to find it out.

I have the sketch in the course’s Github account. It isn’t too important to discuss how the
scanner works, we’ll cover that in a lecture dedicated to I2C. But for now it is enough to say
that the scanner loops through the 127 possible I2C addresses, send a message to each
one, and if the message is acknowledged then we assume that a device is connected and
listening at that address.

With my I2C EEPROM device only connected, I uploaded the scanner sketch, and this
output came out:

!
!
!
!
!
!
!
!
!
So, we now know that the EEPROM device is listening at address 50. We’ll use this
information in the sketches that follow.

To demonstrate how to use the external EEPROM, we’ll follow the pattern from Demos 1
and 2: there will be a sketch that writes a pin in the ROM, and one that reads it back.
Because the external EEPROM communicates via I2C, we will need to use the I2C protocol
to communicate with it. We’ll combine the two into one sketch, where the writing will take
place in the setup() function, and the reading in the loop() function.

Because I don’t want to deal with the low-level implementation details of the I2C interface
and its EEPROM protocol for the chip I am using (the 24C256), I decided to use some code
that adds a layer of abstraction. This means that instead of having to worry about the actual
I2C commands required to store or retrieve an integer or a byte, I can just call a function
like “i2c_eeprom_write_byte” with some parameters and be done with it.

Such code exists in the Arduino Playground, but unfortunately it is not available as a library.
Instead of just including it into your project, you have to copy and paste the code into your

8
Peter Dalmaris Arduino Step by Step EEPROM

sketch. This adds baulk, makes it harder to debug, and fails in the principle of reusing utility
code.

Creating a simple library


I took this as an opportunity to show you how to create a small Arduino library. The code
that follows is the code that I want to convert into a library so that I can reuse it in my
sketches by simply including the name of the library.

You can choose to not read the next section and jump straight to the external
EEPROM demo. There will be a separate lecture which will be a more gentle
introduction to Arduino libraries.

Here it is:

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )


{

int rdata = data;

Wire.beginTransmission(deviceaddress);

Wire.send((int)(eeaddress >> 8)); // MSB

Wire.send((int)(eeaddress & 0xFF)); // LSB

Wire.send(rdata);

Wire.endTransmission();

}

void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte*


data, byte length ) {

Wire.beginTransmission(deviceaddress);

Wire.send((int)(eeaddresspage >> 8)); // MSB

Wire.send((int)(eeaddresspage & 0xFF)); // LSB

byte c;

for ( c = 0; c < length; c++)

Wire.send(data[c]);

Wire.endTransmission();

}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {



byte rdata = 0xFF;

Wire.beginTransmission(deviceaddress);

Wire.send((int)(eeaddress >> 8)); // MSB

Wire.send((int)(eeaddress & 0xFF)); // LSB

Wire.endTransmission();

Wire.requestFrom(deviceaddress,1);

if (Wire.available()) rdata = Wire.receive();

return rdata;

}

9
Peter Dalmaris Arduino Step by Step EEPROM


void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte
*buffer, int length ) {

Wire.beginTransmission(deviceaddress);

Wire.send((int)(eeaddress >> 8)); // MSB

Wire.send((int)(eeaddress & 0xFF)); // LSB

Wire.endTransmission();

Wire.requestFrom(deviceaddress,length);

int c = 0;

for ( c = 0; c < length; c++ )

if (Wire.available()) buffer[c] = Wire.receive();

}

Again, don’t worry too much about the details in this code, I am including it here for the
sake of completeness. I am only highlighting the names of the functions (in blue) since we
will be calling them from our sketch later. These names make up the user interface of our
new library.

An Arduino library is made up of two files: the header file, and the implementation file.

The header file contains a list of functions and variables that are publicly available. The
implementation file contains the actual code that implements the functions. Let’s create the
header first. Just choose a name, I went with EEEPROM, short for External EEPROM.

10
Peter Dalmaris Arduino Step by Step EEPROM

Create a new folder, name it EEEPROM, and in it create a new file named EEEPROM.h:

#ifndef EEEPROM_h
 ifndef is a compiler directive. If by any chance our


sketch has already included this library, then don’t
#define EEEPROM_h

include it again and save some flash memory
#include <Arduino.h>
 space.
#include <Wire.h> //I2C library
Define the name of this library.
class EEEPROM
 This library will make
{
 use of Wire.h, so The Arduino library provides access to all Arduino
include it. data types and constants.
private:

public:

EEEPROM();

void i2c_eeprom_write_byte( int deviceaddress, unsigned int
eeaddress, byte data );

void i2c_eeprom_write_page( int deviceaddress, unsigned int
eeaddresspage, byte* data, byte length );

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress
);

void i2c_eeprom_read_buffer( int deviceaddress, unsigned int
eeaddress, byte *buffer, int length );

};

#endif

!
These are markers for the private Here are the function definitions. The first one, EEEPROM()
and public variables of functions. is a constructor. Its implementation is empty at the
!
We don’t have anything in private,
and the public section is populated
moment, but I plan to add some initialisation code in it
later. The rest of the definitions are fully implemented in the
!
with the function definitions for our
library.
.cpp file.

!
Think of the header file as the skeleton of our library. It’s just a declaration of what the
outside world should know about it, without any internal details.

11
Peter Dalmaris Arduino Step by Step EEPROM

Let’s have a look at the implementation. Create a new file named EEEPROM.cpp and add
this code in it:

The Arduino library provides access to all Arduino


#include <Arduino.h>
 data types and constants.
#include <Wire.h> //I2C library

#include <EEEPROM.h> A blank constructor - I will add some initialisation
code here later.
EEEPROM::EEEPROM(){ }

void EEEPROM::i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress,


byte data ) {

int rdata = data;

Wire.beginTransmission(deviceaddress);

Wire.write((int)(eeaddress >> 8)); // MSB

Wire.write((int)(eeaddress & 0xFF)); // LSB

Wire.write(rdata);

Wire.endTransmission();

}

// WARNING: address is a page address, 6-bit end will wrap around



// also, data can be maximum of about 30 bytes, because the Wire library has a
buffer of 32 bytes

void EEEPROM::i2c_eeprom_write_page( int deviceaddress, unsigned int
eeaddresspage, byte* data, byte length ) {

Wire.beginTransmission(deviceaddress);

Wire.write((int)(eeaddresspage >> 8)); // MSB

Wire.write((int)(eeaddresspage & 0xFF)); // LSB

byte c;

for ( c = 0; c < length; c++)

Wire.write(data[c]);

Wire.endTransmission();

}

byte EEEPROM::i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {



byte rdata = 0xFF;

Wire.beginTransmission(deviceaddress);

Wire.write((int)(eeaddress >> 8)); // MSB

Wire.write((int)(eeaddress & 0xFF)); // LSB

Wire.endTransmission();

Wire.requestFrom(deviceaddress,1);

if (Wire.available()) rdata = Wire.read();

return rdata;

}

! Implementation of the first three functions. Notice the “EEEPROM::”,


this just declares that the function that follows is part of the EEEPROM
… continues …
class.

12
Peter Dalmaris Arduino Step by Step EEPROM

// maybe let's not read more than 30 or 32 bytes at a time!



void EEEPROM::i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress,
byte *buffer, int length ) {

Wire.beginTransmission(deviceaddress);

Wire.write((int)(eeaddress >> 8)); // MSB

Wire.write((int)(eeaddress & 0xFF)); // LSB

Wire.endTransmission();

Wire.requestFrom(deviceaddress,length);

int c = 0;

for ( c = 0; c < length; c++ )

if (Wire.available()) buffer[c] = Wire.read();

}

!
! Completes the implementation.

There is one more file we need to create, it is called “keywords.txt” and it contains a list of
keywords that the Arduino IDE should be able to recognise and highlight in the text editor.
Inside the EEEPROM folder, create a new file named “keywords.txt” with these contents:

i2c_eeprom_write_byte KEYWORD2
 These keywords (the function names from the


i2c_eeprom_write_page KEYWORD2
 header file) will be highlighted by the Arduino
i2c_eeprom_read_byte KEYWORD2
 IDE syntax highlighter. The convention is this:
i2c_eeprom_read_buffer KEYWORD2 !
• KEYWORD1 Classes, datatypes, and C++

! •
keywords
KEYWORD2 Methods and functions
KEYWORD3 setup and loop functions, as
! These keywords (the function
names from the header file) will •
well as the Serial keywords
LITERAL1 Constants
! be highlighted by the Arduino
IDE syntax highlighter.
• LITERAL2 Built-in variables (unused by
default)
I am using KEYWORD2 to highlight the function names, as per the convention. Here’s what
the result is like in the IDE:

!
!
!
!

You can find the latest version of this library on Github. Copy the EEEPROM folder into the
Arduino IDE libraries folder and restart to complete the import process.

!
13
Peter Dalmaris Arduino Step by Step EEPROM

Using the EEEPROM library with the 24C256 EEPROM


Finally, let’s use the new library so that we can read and write some data from the external
EEPROM chip. Instead of an integer, let’s deal with a string. Here’s the sketch:

#include <Wire.h> //I2C library
 Include the EEEPROM library we just created.
#include <EEEPROM.h>
Create an EERPROM object, call it “eeeprom”.
EEEPROM eeeprom = EEEPROM();

void setup() 
 We will write this string (array of char) to the EEPROM.
{

char somedata[] = "this is data from the eeprom";

Wire.begin();

Serial.begin(9600);

eeeprom.i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata));

delay(10); //add a small delay

Serial.println("Memory written");
 Call i2c_eeprom_write_page, which writes multiple
} bytes to the EEPROM. Pass the I2C address of the
device (0x50), the address where the first byte of
this string should be stored (0), a pointer to the array
void loop() 

of char that contains our data, and the size of the
{
 array.
int addr=0; 

byte b = eeeprom.i2c_eeprom_read_byte(0x50, 0);

while (b!=0) 

{
 We’ll read the string one byte
Serial.print((char)b);
 (character) at a time. Start with the
first byte at memory location 0. As
addr++;

parameters, pass the I2C address
b = eeeprom.i2c_eeprom_read_byte(0x50, addr);
 of the device and the byte address
}
 we want to retrieve.
Serial.println(" ");

delay(2000);

}

! Repeat this reading block for as


long as there are characters to
Print the character that was previously read in the
console, then increment the byte address by one,
read. and fetch the byte in that address from the
! EEPROM.

The sketch will store the string “this is data from the eeprom” in the external EEPROM, the
retrieve it and print it to the console every two seconds. By including the EEEPROM.h
library, we have simplified the sketch a lot.

There is still room for improvement though. Notice how the I2C address “0x50” has to be
provided as a parameter every time we call one of the library functions? Can you think of a
way to only provide this address once by improving the way that the library is constructed
and used?


14
Peter Dalmaris Arduino Step by Step EEPROM

Conclusion
Try to be as frugal as possible when using EEPROM. These memories have a limited life-
span, usually 100,000 read/write cycles. This is indeed a large number, however if you do
reading and writing in a loop, like when storing sensor log data every few seconds, you
could wear it out before you know it.

In general, it is a really bad idea to put write calls to the EEPROM in a loop as it is possible
to burn out those bytes in a few minutes. That is a big reason behind only playing with the
EERPOM inside the setup loop in the demos of this lecture, never inside the loop function.

15
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Hardware debouncing
In cases where you need to use a push button, relays or switch (or anything mechanical
used to close a circuit), like we saw in Lectures 15 and 28, we have a situation where metal
comes in contact with metal in order to close the circuit. These contacts are never perfect,
and as a result instead of getting one clean connection, you get multiple ones.

Have a look at the oscilloscope screenshot below (I took this from Wikipedia):

The vertical lines in the centre of the measurement shows that this switch made contact
and lost it several times within the space of a couple of milliseconds. If your Arduino was
connected to this switch via a hardware interrupt pin, then the interrupt service routine
would have been called multiple times.

In many cases, like when we just want to switch on an LED, this doesn’t really matter. In
other cases, like when we use a 4x4 keypad to enter a password, it does. Any number key
that you press on the keypad will generate several logical key-presses and this will make it
hard for the Arduino to determine what keys you actually pressed.

This phenomenon is called “bouncing”, as the voltage of the sampling pin of your switch
bounces from one state to the other before it eventually settles.

In this lecture, we will look at how we can achieve “de-bouncing”, which means how to get
contacts to output a clean signal when they are closing or opening.

1
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Software debouncing for the Arduino


It is possible to write a software de-bouncer that will do the job. It is not my preferred
option since it is tying up the Arduino doing house-hold maintenance and adds un-
necessary complexity to your sketch. I am mentioning it here for the sake of completeness
and because the relevant sketch comes with the IDE.

You can find it at File —> Examples —> Digital —> Debounce. It looks like this:

const int buttonPin = 2; 



const int ledPin = 13; 

int ledState = HIGH; 

int buttonState; 

int lastButtonState = LOW;

long lastDebounceTime = 0;

long debounceDelay = 50;

void setup() {

pinMode(buttonPin, INPUT);

pinMode(ledPin, OUTPUT);

digitalWrite(ledPin, ledState);

}

void loop() {

int reading = digitalRead(buttonPin);

if (reading != lastButtonState) {

lastDebounceTime = millis();

} 

if ((millis() - lastDebounceTime) > debounceDelay) {

if (reading != buttonState) {

buttonState = reading;

if (buttonState == HIGH) {

ledState = !ledState;

}

}

}

digitalWrite(ledPin, ledState);

lastButtonState = reading;

}

Inside the loop, there is continuous sampling of the value of pin 2. The sketch waits for a
period of time after the last bounce was detected, and if it exceeds a certain amount of
time (debounceDelay), then the button is interpreted as pressed.

To implement this software solution we had to add four variables and 8 lines of code that
operate in the loop, and this is far less than ideal.

2
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Let’s have a look at a simple hardware solution.

A simple capacitor-based de-bouncer


You can build a simple de-bouncer by inserting a small capacitor in parallel to the button or
switch.

In this example, you can see the switch (S1) in


parallel to a 100nF capacitor. The Vout is connected
to the Arduino sampling digital pin.

The capacitor will start charging as soon as the


switch is closed, and while it is charging Vout will
be LOW (as it is connected to GND via the pull
down resistor). Once the capacitor is finally fully
charged, Vout will be 5V and the Arduino will detect
this as HIGH. The mechanical switch will still be
bouncing, but the capacitor is now shielding Vout
from the effects of this bouncing.

This is a much better solution than the software de-


bouncing we saw already. However, if the button is
connected to digital electronics like a micro-
controller, the smooth transition that the capacitor
creates between LOW and HIGH is problematic.

In digital electronics, such transitions are bad:

!
But sudden, clean transitions are good:

!
This is not to say that you can’t use such a simple debouncing circuit with your Arduino, of
course. You could. But it is possible to improve and create a clean transition between LOW
and HIGH without much extra effort.

What I would like to show you next is a cost-effective solution that takes care of de-
bouncing without adding complexity.

Introducing, the Schmitt Trigger.

3
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Schmitt Trigger as a de-bouncer


A Schmitt Trigger device is designed for removing noise in digital circuits. They are
commonly found in applications where bouncing from mechanical switches is a problem.
Logically, a Schmitt Trigger will invert an input signal.

The following schematic (taken from Wikipedia), shows the function of the Schmitt Trigger.

!
!
!
!
!
!
!
!
!
!
“U” is the original, unconditioned (noisy) signal. “B” is the output of the Schmitt signal, a
nice digital signal without bouncing. In the red boxed area, notice how B is HIGH when U is
above the top dotted green line and stays HIGH until U falls below the bottom green line.

In the green box area, notice how the same happens even though the U waveform bounces
up and down significantly, however it does not fall below the bottom green line. That’s
exactly what the Schmitt trigger does.

These two green dotted lines mark the high and low thresholds levels.

The “A” waveform is the waveform that comes out of a component of the Schmitt trigger
called a comparator. The comparator is very simple, a kind of binary amplifier, that just
outputs HIGH when its input voltage goes above a certain threshold (represented by the red
line) and LOW when it falls below that same threshold. That, on its own, is not very useful.
As you can see from its waveform, it doesn’t do much to debounce the original noisy signal.

4
Peter Dalmaris Hardware Debouncing Arduino Step by Step

To achieve the 2 green threshold levels that we need for a proper de-bouncer, we create a
positive feedback (B - which is also the output of the Schmitt Trigger) which reinforces the
input to the comparator (A), like is shown in the schematic below (also from Wikipedia).

!
To recap, a Schmitt trigger is a device that provides de-bouncing by conditioning the
original noisy signal. The output of the Schmitt Trigger depends on the upper and lower
threshold levels. Usually, the upper threshold level is 66% of the rail voltage (in the case of
the Arduino, that is 66% of 5V) and the lower threshold level is 33% of the rail voltage.

The 74HC14 Schmitt Trigger IC


A commonly used Schmitt Trigger IC is the the 74HC14. It contains 6 Schmitt Triggers. We
will use this IC to debounce a push button in this demo.

!
5
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Demo - Using the 74HC14 to de-bounce a button


In this demo we will de-bounce a push button using one of the 6 Schmitt Triggers in the
74HC14 IC.

The schematic is provided below.

We’ll use the Schmitt Trigger to debounce the push button. When the button is pressed, the
LED will turn on.

Connect the IC like this:

!
IC Pin Connects to…
! 14 5V
! 7 GND

! 1 To button via a 100Ω


resistor (or without the
! resistor)
2 To Arduino pin 2
! All unused Connect unused inputs
! inputs to 5V or GND to avoid
unwanted oscillation
For the button:

! Button pin Connects to…

1 To 74HC14 pin 1 via

! 100Ω resistor (or


without the resistor)

! 1 To 5V via 10kΩ resistor

2 To ground
! 1-2 Optional: a 20uF
! capacitor between the
two pin of the button
Last, connect the red LED to pin 1 to 3 via a
protective 220Ω resistor.

6
Peter Dalmaris Hardware Debouncing Arduino Step by Step

Here is the sketch, it is similar to the one from the lecture on interrupts.

const int ledPin = 13; 



const int inputPin = 2;

volatile boolean ledState = LOW;

void setup() { 

pinMode(ledPin, OUTPUT);

attachInterrupt(0,buttonPressed,FALLING);

}

void loop()

{ }

void buttonPressed()

{

if (ledState==LOW)

{

ledState=HIGH;

digitalWrite(ledPin,HIGH); 

} else

{

ledState=LOW;

digitalWrite(ledPin,LOW); 

}

}

Load the sketch from the Interrupts lecture and press the button. Press the button slowly at
first to make sure it works, then increase your press rate to see if you can reach it’s limit of
reliability.

Try the same things with various buttons and switches that you may have at hand. I find in
my experiments that different buttons behave very differently to one another. The capacitor
and pull up resistor of the button can be tweaked in order to find their optimal values for
each particular button. There is an amazing article in the Ganslee Group blog that analyses
contact de-bouncing in great detail and that I strongly recommend you read at some point.
The article covers the causes and effects of bouncing and provides alternative de-bouncing
techniques that work well in the real world. You will not think of wires and switches the
same way again once you read this article!

7
Peter Dalmaris Hardware Debouncing Arduino Step by Step

In conclusion
De-bouncing switches has an element of art because every switch has its own analog
characteristics and imperfections. Using Schmitt Triggers is one of several techniques
available to us. The Schmitt Trigger is a common way of conditioning (cleaning) the signal
going into a digital circuit. In this lecture, we saw how to use a Schmitt Trigger to de-
bounce a button, without having to make any software changes to our sketches.

I suspect that because of the large variation between the buttons that I use and those that
you will use, your results will be different to mine. Spent a bit of time tweaking your circuit
to get a feel of its behaviour. Start with large changes, like for example, try to remove the
capacitor and see what the effect on the reliability of the switch is. Try to go for a larger or
smaller capacitor, or increase/decrease the value of the pull-up resistor. Those two
components can be used to calibrate the sensitivity of the Schmitt Trigger inside the IC for
the particular characteristics of your button.

8
Peter Dalmaris Arduino Step by Step Internal Pull Up Resistors

Internal Pull Up Resistors


In the lecture on buttons (Lecture 15), we encountered the pull-up and pull-down resistors.
This is an arrangement where in a logic circuit, a large resistor connects a pin from where
we obtain a HIGH or LOW reading to either a (logical) HIGH source, or the ground. If this
resistor was connected to a logical HIGH, then we call it a “pull-up”, and if it was
connected to a logical LOW we call it a “pull-down”. This way, when the button is not
pressed and its measurement pin is “hanging free” or “floating free” (i.e. it’s not connected
to a HIGH or LOW pin) then through the pull-up resistor we can essentially assign it with a
known value.

In Lecture 15, we saw this circuit:

!
!
!
!
!
!
!
!
!
!
!
!
!
The measurement pin of the button is connected to both digital pin 2 on the Arduino and
(via a large 50kΩ resistor) to the GND pin of the Arduino. Therefore, this is a pull-down
resistor. The large resistor ensures that when the button is not pressed, the yellow jumper
wire transmits a LOW reading to digital pin 2. When the sketch detects this, it can safely
conclude that the buttons is not pressed.

Keep in mind that we could just as easily had used a pull-up resistor. Connect the resistor
to 5V, and the other pin of the button to GND. We would just modify our sketch so that a

1
Peter Dalmaris Arduino Step by Step Internal Pull Up Resistors

HIGH means that the buttons was not pressed, and a LOW means that the button was
pressed.

The Atmega micro-controller contains large (between 20kΩ and 50kΩ depending on the
model) that we can enable so that we can remove the external resistor from our circuit. In
the Arduino Due, the pull-up is between 50kΩ and 150kΩ.

Let’s do that now.

Demo: Using an internal pull-up resistor


Update the circuit so that it looks like this:

!
!
!
!
!
!
!
!
!
!
!
The circuit is much the same with the exception that the pull-up/down resistor has been
removed. We just connect the pins of the button to GND and digital pin 2 from where we
will detect the state of the button. The LED is there just to visualise the state of the button.

Now let’s move to the sketch, and see how to enable the pull-up resistor. This resistor is, by
default, disabled.

2
Peter Dalmaris Arduino Step by Step Internal Pull Up Resistors

Any pin that can be configured as input, contains a pull-up resistor in series.


const int buttonPin = 2;

Set the button and LED pin number, and initialize
const int ledPin = 13;
the button state.

int buttonState = 0;
Set the ledPin to be output.
void setup() {

pinMode(ledPin, OUTPUT); 

Set buttonPin to be an input, and enable the pull-

pinMode(buttonPin, INPUT_PULLUP); up resistor. We can now throw away the external
} pull-up.

void loop(){
 Take a measurement from the button


buttonState = digitalRead(buttonPin);
 pin.
if (buttonState == HIGH) { 

We now use a pull-up resistor. So, if
digitalWrite(ledPin, LOW); 
 the state of the button pin is HIGH, we
} else {
 know that the button is not pressed,
digitalWrite(ledPin, HIGH); 
 and we’ll keep the LED to LOW.
}

}

As you can see, enabling the pull-up for an input pin is just a matter of passing the
appropriate configuration constant “INPUT_PULLUP”.

Conclusion
Internal pull-up resistors only apply to pins configured as inputs, and don’t have any effect
in the output behaviour. Notice how the LED has a protective resistance in series? It would
be convenient to be able to replace it with an internal one, but that is technically not a
reasonable thing to do. Each LED or other load needs a current limiting resistor appropriate
for its characteristics, and it would be too expensive to come up with a way to create a
configurable resistance inside the micro-controller.

You can have a look at your micro-controller’s data sheet to find out the exact value of its
pull-up resistors, if this is important for your design. For example, you may want to know
how much current will be flowing through the internal pull-up so you will need the exact
value of the resistor to do the current calculation.

A couple of terms relating to pull-up and down resistors are “strong” and “weak”. A strong
pull-up (or down) is a large resistor that only allows a small amount of current to flow
through it, while a weak pull-up (or down) is a smaller resistor that allows more current to
flow through it.

When you have a choice of a resistor to use for pull-up, you want to choose that that is
large enough to not allow too much current to flow through it (that’s a waste of energy), but
you also don’t want it to be too large as at some point you will end up with the same

3
Peter Dalmaris Arduino Step by Step Internal Pull Up Resistors

problem you had at the very beginning: the voltage when the button is pressed will be hard
to determine if the current is insufficient to raise a voltage.

Large pull-up resistors can also be too slow to respond to quick voltage changes, and in
high-speed circuits, like in USB serial communications. In USB circuits, you will typically
find pull-ups in the range of 1kΩ to 4.7kΩ (in our examples of external pull-ups we typically
use resistors between 50kΩ and 60kΩ).

4
Peter Dalmaris Memory & Memory Management Arduino Step by Step

Memory
In a couple of past lectures, namely lectures 64 on EEPROM, and 45 on the SD Card, we
had a quick look at the memory architecture of the Atmega micro-controller. We learned, for
example, that there are 3 types of memory that we have under our control (this table
contains a summary):

Volatile Use Size (Arduino Life expectancy


Uno)

Flash No Program 32KBytes 100,000 write cycles

SRAM Yes Variable data 2KBytes Very large

EEPROM No Variable/user data 1KByte 100,000 write cycles

There’s not much memory to go


around, so we need to take care
of it. Although we have not
reached the limit of any of these
memories in our lectures, you will
once you start creating projects.
For example, in my DMD
Notification System, the memory
footprint of the sketch dictated
the use of the Ethernet shield
instead of the Wi-fi breakout. The
library required for the Wifi
breakout was simply too large to
fit in the Flash memory without
serious optimisation.

It is worth knowing that the memory architecture that the Atmega and most micro-
controllers use is called “Harvard architecture”. A computer build based on this architecture
has a separate dedicated memory for the instructions (program) and for the program data,
and it looks like this:

Instructions
Data memory CPU
memory

!
!

1
Peter Dalmaris Memory & Memory Management Arduino Step by Step

Your regular PC follows the Von Neumann architecture, where the same physical memory is
used for instructions (program) and data. While Harvard’s architecture can yield better
performance, Von Neumann’s is more flexible for general purpose applications. Since
micro-controller’s are meant to perform a particular task reliably and efficiently, it makes
sense to design them based on the Harvard architecture.

In this lecture, we’ll look at some design and programming principles you can follow to
make better use of your Arduino’s limited memory resources.

Flash
Flash memory is usually our first
consideration since it is the first
memory we consume when we
upload a sketch.

When you hit the upload button, the


Arduino IDE will compile the sketch
into machine code and then attempt
to upload it to the micro-controller. If
all goes well and the sketch is below
the Flash memory limit, you will get
this nice message: “Done uploading”,
followed by the binary sketch size
figure in the console.

In this case, there is plenty of space


left, nothing to worry about.

!
But, if your sketch is at least one byte larger than that 32,256 available flash bytes of the
Arduino Uno, you will get this instead (see next page):

2
Peter Dalmaris Memory & Memory Management Arduino Step by Step

!
To generate this error, I simply found a sketch that required 31KBytes of Flash storage and
included a new library. The compiler will include this library in the machine code that it
produces even though there is not a single call to any of its methods.

So, how can one best manage the size of a sketch so that it only consumes the amount of
Flash memory it really needs, and no more?

Here are some suggestions.

Remove bloat
Just like in my example above, during prototyping it is often true that you will go from one
version of a sketch to another without remembering to clean up in the process. You could,
for example, create a function in version 1, which is not used in version 2. If you don’t
remove it, the compiler will include it in the compiled sketch. Same thing applies to unused
libraries, variables and code in general.

So, try to keep your sketch lean by cleaning regularly as you move through its iterations.

Remove prints
We often use print and println functions to trace the operation of the sketch while we are
debugging it. Each print function consumes around 500 bytes of memory in flash. Often in
my sketches, I find so many references to println or print that removing them frees up 2 or 3
KBytes of flash memory.

3
Peter Dalmaris Memory & Memory Management Arduino Step by Step

Use constants
When you declare a variable and you know that its value is not going to change, you can
declare it as constant. A constant allows the compiler to optimise the way that it labels it
and references it in memory.

So, make this:

int ledPin = 13;

into this:

const int ledPin = 13;

By marking a variable as a constant, you save 2 bytes in the declaration itself, plus 2 bytes
every time it is used in the sketch.

Remove the bootloader


This is a technique for more experienced makers. It enables you to save almost 2.5KBytes
of flash memory.

The bootloader is a component of the Arduino


ecosystem that makes it so easy to use the
Arduino platform. The bootloader is responsible
for working with the Arduino IDE to upload a
new sketch into the Flash memory. Without a
bootloader, you would have to use a special
device called an “AVR programmer”.

You can still use the Arduino IDE to write your


sketches as per normal, but with the bootloader
gone, you will need to use this additional piece of hardware to get it uploaded.

!
!

4
Peter Dalmaris Memory & Memory Management Arduino Step by Step

SRAM
SRAM is much smaller than Flash, only 2KBytes in the Uno, and in real life it tends to cause
more problems. Here’s a couple of examples:

* If you decide to use an SD card in your project, you will immediately dedicate 512 bytes
of SRAM as buffer space required by the SD Card library.

* Want a monochrome LCD display? you need 1 byte for every 8 pixels, so depending on
the resolution of the screen you would be using up a large part of your SRAM capacity.

Let’s have a look at things you can do to make efficient use of your available SRAM.

Know your data types and structures


The Arduino provides several data types, of which most people end up using only 3 or four.
Knowing which one most efficiently fulfils its intending purpose can save you a lot of
wasted space.

This table contains the available data types and the amount of space they consume in the
SRAM.
Type Bytes

boolean 1

char 1

unsigned char 1

byte 1

int 2

unsigned int 2

word 2

long 4

unsigned long 4

short 2

float 4

double 4 (8 bytes on the


Due)
string An array of chars,
so 2 bytes * number
of chars

Let’s pretend that you are creating an array to hold these numbers: 1, 5, 25, 125.

If you declare this array like this:

5
Peter Dalmaris Memory & Memory Management Arduino Step by Step

int myNumbers[] = {1, 5, 25, 125};

…you will consume 4 * 2 bytes = 8 bytes. But if you declare it like this:

const byte myNumbers[] = {1, 5, 25, 125};

… you will only consume 4 * 1 byte = 4 bytes, since each number occupies only 1 byte. The
numbers in the array are all smaller than 255, so it makes absolutely no difference to my
sketch the loss of a byte per number. You even save a bit of space thanks to the const
modifier for each reference of the array in your sketch.

Only use larger size data types like long and float if you have a very good reason. My self, I
rarely use them.

Avoid recursion
Recursion is a programming technique that in certain cases can simplify the programming
effort. Here is a typical example:

unsigned int factorial(unsigned int n) {



if (n == 0) {

return 1;

} else {

return n * factorial(n - 1);

}

}

This code calculates the factorial of a number (n). You can see that the function body
contains a call to itself. This is what recursion is, a segment of code that calls it self.

In PCs and computers with lots of memory, this is a good way of solving a problem that can
be broken down into small identical pieces. The trouble is that every recursion adds a full
copy of the function and its data to the program stack, which is stored in SRAM. The larger
the n is in this example, the deeper the stack will be, bringing the sketch closer to
exhausting its available memory.

The good news is that every recurve problem can be solved with simple iteration. This may
produce slightly messier code, but at least we will not have the memory stack problem.
Here is the factorial problem solved using iteration (see next page):

6
Peter Dalmaris Memory & Memory Management Arduino Step by Step

unsigned int factorial(int n) 



{

int f = 1;

int i;

for(i = 1; i <= n; i++) 

{

f *= i;

}

return f;

}

This code is a bit longer and harder to understand, but it will use the same amount of
memory every time, no matter what the n parameter is.

Variable names don’t matter


Some people believe that shorter variable names, like “i” or “j”, can result in smaller
memory footprint. This is not true, as the compiler will replace these mnemonic names
(meant to be read by the programmer, not the compiler) with labels that it computes
dynamically.

Store strings in Flash


There is a handy macro, F(), that makes the compiler store strings in Flash memory instead
of SRAM. This macro is useful in cases where you have a call to print or println where the
string parameter does not change.

For example, this:

System.println(“Hello world!”);

…can be changed into this:

System.println(F(“Hello world!”));

… so that the string “Hello world!” is stored in Flash.

Use PROGMEM for data


You can use the PROGMEM modifier to instruct the compiler to store data in Flash instead
of RAM. This is similar to the effect that the F() macro has on string.

PROGMEM doesn’t work with all data types, only with those that the “pgmspace” library
supports. To use this modifier, start by including its library:

#include <avr/pgmspace.h>

then declare the variable and mark it with the PROGMEM keyword:

PROGMEM prog_uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};

7
Peter Dalmaris Memory & Memory Management Arduino Step by Step

Notice that the type of the charSet array is prog_uint16_t, not just int. If you wanted to
store a 1-byte number, you would use the prog_int8_t data type, and for a 2-byte number
you would use prog_int16_t.

Reading is also a little tricky. You can’t just say:

charSet[0];

… to access the first item of the array, because this would result in the micro-controller
looking for this data item in SRAM, not Flash. Instead, you need to use one of the functions
that the library provides:

pgm_read_word_near(charSet + 0);

… and this will retrieve the data stored in the 1st item location of the array. If you wanted
the second item, you would say:

pgm_read_word_near(charSet + 1);

… and so on.

Have a look at the documentation for pgmspace for details on all the data types and
functions that it provides.

Report free memory


There is a very useful library that you can include in your sketch so that you can profile its
memory use. It’s called MemoryFree.

Install the library, include it, and use the freeMemory() function to get a reading of your
SRAM available memory. Place freeMemory() at strategic locations throughout your sketch
to get an understanding of how memory is used, and then when your prototype settles you
can remove it. This will release a bit of flash memory.

8
Peter Dalmaris Memory & Memory Management Arduino Step by Step

One thing to note is that freeMemory() will only report the amount of SRAM available that is
continuous. If SRAM is fragmented, it will report a lot less space available.

EEPROM
EEPROM was covered in detail in Lecture 64, please check it out if you haven’t done so
already!

Wrap it up
Memory is a limited resource on the Arduino, and as such it must be managed with care.
Unlike programming PCs, though, memory management on embedded devices comes
down to a few simple rules and habits. This lecture described the bulk of the things that you
can do to get the most out of your Arduino’s memory.

9
Peter Dalmaris Seven segment display Arduino Step by Step

The Seven Segment Display


The Seven Segment Display (SSD from now on), is a device that contains seven LEDs in a
pattern that makes it possible to create a number from 0 to 9 by
enabling or disabling them.

Commonly, SSDs also contain a dot LED at the bottom right corner,
so they should probably be called 7+1 Segment Displays or
something like that.

It is possible to combine multiple SSD to create multi-digit displays.


Although we can use LCD displays as we saw in lecture 25, SSD are
much brighter and easier to read even from a distance.

In this lecture, we will build on our knowledge from Lecture 60, where
you learned how to use a shift register in order to control multiple
LEDs using only three wires: one for data, one for clock, and one for
the latch. Because there are so many SSD out there, I will assume
that you don’t have your particular display’s datasheet and have no idea which pin controls
the pins. I will describe the process of figuring out the correct wiring and then constructing
the numerical symbols in the sketch.

Wiring
In the demo for this lecture, we will end up
constructing a circuit that looks like the one
in this schematic.

You can use this schematic to wire up the


595 shift register to the Arduino, but wiring
the shift register to the SSD depends on how
the SSD is made. There are a couple of main
types, the common cathode and the common
anode. The one that I happen to use is of the
common anode variety, in which the middle
pins of each row is connected to the positive
voltage. I will explain how to figure out which
one you have further down.

Another consideration is power. You will


potentially have up to 8 LEDs lit at one time,
and if you decide to add more SSDs, you will
have multiples of 8. If each LED requires 15mA of current, you will need a total of 120mA,
which the Arduino can’t provide. In the schematic, I have attached a breadboard power
supply from which I power the LED and the shift register. You can also connect a power

1
Peter Dalmaris Seven segment display Arduino Step by Step

supply to the Arduino via its barrel connector, and this can provide power to the breadboard
via the +5 pin.

Common anode or common cathode?


The easiest way I have found to figure out what kind of SSD you
have, is you use a 1.5V button battery to probe that pins on the
SSD. To see how this works, take a 5mm LED and connect it’s
two pins to the battery, like I am showing in this image.

The long leg of the LED is the anode and needs to be connected
to the positive (+) side of the battery. The cathode is connected
to the negative side.

For the SSD, first have a look at the back. There are two rows of
pins. In both rows, the middle pins are either the anode or the
cathode. They are connected to each other, so it doesn’t matter which one you end up
using. You can confirm that by testing for continuity with your multimeter, if you have one.

Now plug the SSD into the breadboard. Connect a red wire in
one of the two middle pins, and another wire to any of the
other pins, it doesn’t matter which one. Test to see if the
middle pin is the anode by
connecting the red wire to the
positive side of the button
battery and the other wire to
the negative.

If any of the LEDs lights up,


then you have established that
you have a common-anode
type of SSD. If nothing happens, try connecting the battery
the other way around. If one of the LEDs lights up, then you
have a common-cathode SSD.

Knowing what kind of SSD you have is important because


it dictates how to connect it to the circuit. I will assume that
you have a common-anode SSD, but if you actually have a common-cathode one just
reverse all the connections for the LEDs: my positives will be your negatives and my
negatives will be your positives.

2
Peter Dalmaris Seven segment display Arduino Step by Step

Notes on wiring
The shift register allows you to control 8 LEDs, since it can store 8
bits. We want to connect each LED to the shift register in an
organised way, because that will help us a lot with the sketch.

Each LED segment on the display is given a letter as a designation,


like in this picture. I will be using these designations later when I am
constructing the numerical symbols in the sketch. I am also including
the pin-out of the 595 shift register IC because I will be referring to its
pin numbers.

I always start by connecting the dot (DP) to pin 15 of the IC


(Q0). How do you know which pin on the SSD activates the
dot LED? Use the method we used to detect the kind of SSD
we have. Leave the red wire connected to the anode pin, and
connect the other wire to the other pins (while still connected
to the batter), until the dot LED lights up. For me, this pin
happens to be the bottom-right one. I suspect that this is true
for most SSDs.

From there, I continue clock-wise, and connect the pin to the


left of the dot pin to pin 1 on the IC (Q1). Continuing
clockwise, skip the next pin because it’s the common anode,
and connect the next one to pin 2 (Q2) on the IC.

Once you finish with the bottom row of the SSD, continue
with the right-most pin of the top row. Connect that to pin 4
(Q4) on the IC. Continue moving towards the left, and connect the rest of the pins (except
for the middle common anode one) to pins 5, 6, and 7 on the IC. You are now finished with
connecting the SSD to the IC. Finish up with the SSD by connecting the common anode pin
to the 5V rail via a single 220Ω protective resistor (I do both top and bottom pins in order to
distribute the current, but you could connect either one or the other without risk).

Next, continue wiring the IC. You can find the details in Lecture 60, but in summary
remember that IC pin 14 goes to Arduino pin 8 (data pin), IC pin 12 goes to Arduino pin 9
(latch pin) and IC pin 13 goes to Arduino pin 10 ( clock pin).

You should now have a circuit that resembles the one in the schematic at the start of the
Wiring section.

3
Peter Dalmaris Seven segment display Arduino Step by Step

Sketch
We will now create a sketch that once loaded, will implement a counter, that uses the SSD
to display numbers from 0 to 9.

This sketch will be based on the one we saw in Lecture 60, Demo 1. The difference is that
in the new sketch we are about to create, we don’t want the LEDs in the SSD to light up
randomly, we want it to show legible numbers.

Let’s start with the skeleton of the sketch and build it up.

const int latchPin = 9;



const int clockPin = 10;

const int dataPin = 8;

void setup() {

pinMode(latchPin, OUTPUT);

pinMode(dataPin, OUTPUT); 

pinMode(clockPin, OUTPUT);

}

void loop() {

}

void writeLeds(byte pattern)



{

digitalWrite(latchPin, LOW);

Serial.println(pattern,BIN);

shiftOut(dataPin, clockPin, MSBFIRST, pattern);

digitalWrite(latchPin, HIGH);

}

This sketch doesn’t do anything at the moment. Our objective is to create a data structure
that associates a numerical symbol, like the zero “0”, with a bit pattern. When we pass this
bit pattern to the writeLeds() function, a zero symbol will appear on the SSD.

We will need ten such patterns, one pattern per numerical symbol (I will not be using the
dod in this sketch). The easiest data structure that I can think of that allows us to store ten
bit patterns is an array. I will start with declaring a “default” array of ten items that holds
bytes, and then tweak each byte separately to get it to display the symbol I want.

4
Peter Dalmaris Seven segment display Arduino Step by Step

So, let’s start with this:

const byte CHAR_COUNT = 10;



const byte symbols[CHAR_COUNT] = {

B11111111, // 0

B11111111, // 1

B11111111, // 2 

B11111111, // 3

B11111111, // 4 

B11111111, // 5

B11111111, // 6 

B11111111, // 7

B11111111, // 8 

B11111111 // 9

};

For the time being, all bytes are 11111111. At the end of the setup function, add this
instruction:

writeLeds(symbols[0]);

… and then run the sketch. The byte in the 0-index position of the array (the first cell) will be
sent to the shift register. Because it’s all 1s, and this is a common-anode SSD, all the LEDs
will be off. Now try to make a change, for example change the first bit of the first byte to 0,
so that you have this pattern:

B01111111

Run the sketch again, and you will see that LED G is now lit.

The first item in the array should represent a zero, so LED G should
be on. We need to find the bits that activate LEDs A, B, C, D, E and
F. Since we now know which bit controls LED G, we know that we
need to activate all others in order to create the zero symbol.

So, now we now that zero is encoded in bit pattern B10000001.

Edit the array so that the first cell contains this bit pattern and upload the sketch again. You
should see a zero symbol appearing on the SSD.

Let’s try for a symbol “1”, which is encoded by the second cell in the array. First, update the
setup function so that the call to writeLeds() is like this:

writeLeds(symbols[1]);

Now, try to find out which bits activate LED segments B and C. With a bit of trial and error,
you will figure it out. The pattern for “1” is “B11101101”. Segment B is controlled by bit 5
and segment C by bit 2.

5
Peter Dalmaris Seven segment display Arduino Step by Step

Update the array and upload the sketch to confirm.

After a few rounds of this method, you will have a table that shows the relation between
SSD segments and bits for each bit pattern. You can use pen and paper to make notes,
and it will eventually look something like this:

Bit # 8 7 6 5 4 3 2 1

Segment G F A B E D C DP

When you have completed this, your symbols array will look like this:

const byte symbols[CHAR_COUNT] = {



B10000001, // 0

B11101101, // 1

B01000011, // 2 

B01001001, // 3

B00101101, // 4 

B00011001, // 5

B00010001, // 6 

B11001101, // 7

B00000001, // 8 

B00001001 // 9

};

With this, getting the count-up effect that we are looking for is simple. Here is the
completed sketch (next page), with comments embedded:


6
Peter Dalmaris Seven segment display Arduino Step by Step

const int latchPin = 9;



const int clockPin = 10;

const int dataPin = 8;

const byte CHAR_COUNT = 10; Each rows contains a bit pattern that is passed
to the shift register in order to activate the
const byte symbols[CHAR_COUNT] = {
 appropriate SSD segments and produce the
symbol we want.
B10000001, // 0

B11101101, // 1

B01000011, // 2 

B01001001, // 3

B00101101, // 4 

B00011001, // 5

B00010001, // 6 

B11001101, // 7

B00000001, // 8 

B00001001 // 9

};

void setup() {

pinMode(latchPin, OUTPUT);

pinMode(dataPin, OUTPUT); 

pinMode(clockPin, OUTPUT);

}
Call to function that creates the count-up
void loop() {
 effect.
pattern1();

}

void pattern1()

{

int i=0;
 The while() block calls the writeLeds() function
while(i<CHAR_COUNT)
 and passes an appropriate symbol bit pattern
from the symbols array. Each time, it
{
 increments the counter by 1. Once it reaches
writeLeds(symbols[i]);
 the last item of the, it ends.
i = i+1; 

delay(500); 

}

}

void writeLeds(byte pattern)



{

digitalWrite(latchPin, LOW);

Serial.println(pattern,BIN);

shiftOut(dataPin, clockPin, MSBFIRST, pattern);

digitalWrite(latchPin, HIGH);

}

7
Peter Dalmaris Seven segment display Arduino Step by Step

!
Multiple seven segment displays
In most real-life applications, a single SSD will not be
enough. Just to display a clock, you need four. You can
use this architecture to daisy-chain multiple SSDs
together, just like you learned in Lecture 60. You can
also purchase components that contain multiple SSDs,
including a controller, usually one or more 595 shift
registers, such as this one.

Still, with most of these components, you will need to


apply the principals you learned in this lecture:

* You need to know whether you have a common-


anode or common-cathode display,

* You will need to at least confirm that your symbol


array contains the correct bit patterns for the symbols you want to display.

Alphanumerical displays
If you need to display letters as well as numbers, then you are
looking for an alphanumerical display. Here’s an example (image
to the right).

These displays are similar to the seven segment displays we just


saw, except that they contain more segments, and therefore more
pins. You can find such displays with 16 or 14 segments, and to
drive them you will need larger general purpose shift registers or
a dedicated controller, like in this example from Sparkfun, or LED IC controllers like the
MM5450.

I will try to create a lecture that will demonstrate how to use the MM5450, although I think
that with a little effort, you will be able to work it out (hint: it really is just a shift register with
35 bits capacity).

Wrap it up
Working with seven segment displays is straight forward once you become familiar with
their principle of operation and the way you can interface them to the Arduino.

As an exercise, add a second SSD to your circuit, controlled by a second shift register. Wire
the second SSD to the second shift register in the same way you did for the first one, and
wire the second shift register to the first in a daisy-chain fashion like you learn in Lecture
60.

8
Peter Dalmaris Seven segment display Arduino Step by Step

Adjust the sketch so that now it can count up from 00 to 99. If you do that, then you have
mastered the seven segment display!

9
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

Multiply your Arduino’s digital I/O


The Arduino Uno has 14 digital I/O pins. That sounds a lot, but it isn’t consider that all these
pins are multi-functional, so that they are used for tasks other than pure input/output, like
Pulse Width Modulation, serial and SPI communications. We saw in an earlier lecture,
number 60, that shift registers can be used to provide us with additional digital outputs.

But what about additional digital inputs? In this lecture, I’ll show you how to use the
MCP23017 IC to easily add a total of 16 digital I/O pins to your Arduino project.

About the MCP23017


The MCP23017 is an integrated circuit that communicates with the outside world using the
I2C interface, and provides 16 pins that can be configured individually as digital inputs or
outputs. Using the I2C interface means that you can potentially add up to 128 of these
devices to your project, for a grand total of 128*16 = 2048 digital I/O pins.

Any kind of simple device that provides a digital input or output can be connected: buttons,
LEDs, relays, keypads, seven segment display, and much more.

Let’s have a quick look at the chip, and get a


basic understanding of its characteristics
before going ahead with the demos.

The I/O pins are arranged in two sets, or


banks. Bank A is on the right taking up pins
21 to 28, and Bank B is on the left taking up
pins 1 to 8.

We will be configuring these pins as input or


output, and reading or writing values on them.

Pins 15, 16, and 17 are used for setting up the I2C device address. You can set one of the
possible 128 I2C addresses by connecting these pins to +5V or Ground.

Pins 12 and 13 are used for the I2C communication. Pin 12 is the clock and 13 the data. On
the Arduino Uno, you connect these to analog pins 5 and 4 respectively.

Pin 18 is the reset. If you take this pin to LOW, it will reset the device. We’ll be keeping it to
HIGH (5V) via a10KΩ pull up resistor.

Pins 19 and 20 are used for hardware interrupts. We will not be using these ports in this
lecture.

Pins 9 and 10 are +5V power and Ground.

Pins 11 and 14 are not connected to anything, just leave them floating.

1
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

Let’s go ahead with the first Demo!

Demo 1: Digital out


For this first demo, we’ll get the port expander connected to the Arduino, and write a simple
sketch that sets one of the expander’s pins as a digital out, connect an LED to it and make
it blink. Instead of an LED, you could use some other kind of digital load, like a small 5V
relay switch.

Here’s the schematic:

Notice that the pull-up resistors for


pins 12 and 13 (I2C clock and data)
are required, and are 10KΩ each.

I am also using a 4.7KΩ pull up


resistor on pin 18 (reset).

The LED is connected to pin 28 on


the port expander via a 220Ω
resistor.

For the sketch, the objective is to


use the I2C protocol and transmit
instructions to the port expander so
that the LED is turned on and off.

For this, we can use the low-level


functions that come with the Wire
library, like this:

(see next page)


2
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

We’ll be using functions from the Wire


#include “Wire.h"
 library (implements the I2C interface).
void setup()

{
 Start I2C
Wire.begin(); 

Start talking to the port expander at its
Wire.beginTransmission(0x20);

default I2C address.
Wire.write(0x00); 

Wire.write(0x00);
 Select the register that controls Bank A.
Wire.endTransmission();

Set all pins for Bank A to be outputs. If
}
you wanted them to be inputs just leave
Send the instructions and this line out since all pins are inputs by
void loop()
 close the connection. default.
{

delay(100);

Select the pins in Bank A. See Table
Wire.beginTransmission(0x20);
 1-4 in the datasheet.
Wire.write(0x12); 

Wire.write(B10000000); 
 Sent a byte to Bank A. Each bit
Wire.endTransmission();
 corresponds to one of the pins. The first
bit controls pin 28 (GPA7), and turns the
delay(100);
 LED on. Nothing is connected to the rest
Wire.beginTransmission(0x20);
 of the pins, so leave them off (0).
Wire.write(0x12); 

Wire.write(B00000000);
 After a 100msec delay, sent a new byte to
Wire.endTransmission(); 
 the pins of Bank A. This time, the first bit
is 0, so the LED is turned off.
}

!
In a way, controlling the pins of the port expander as outputs is similar to using a shift
register. Just sent out a byte that contains the bit pattern that you want your outputs to
have.

In most cases you will only have one or two output devices you’d like to control, and for
that you might not want to deal with bytes, registers and pin banks. Instead, you could this
convenient library from Adafruit. The library is “Adafruit_MCP23017”. Download it from
Github and install it in your IDE.

You can achieve that same output as the sketch above, like this (see next page):

3
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

#include <Wire.h>
 Include the necessary libraries.


#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;
 Create the mcp object, this will be our



 interface to the port expander.
void setup() { 

mcp.begin(); 
 Start the device and set I/O 7 to output.
“7” corresponds to GPA7 from the device
mcp.pinMode(7, OUTPUT);

pinout diagram.
}

void loop() {

delay(100);

Write HIGH to I/O pin 7, turns the LED on.
mcp.digitalWrite(7, HIGH);

delay(100);

Write LOW to I/O pin 7, turns the LED off.
mcp.digitalWrite(7, LOW);

}

Much easier and concise, isn’t it?

How about we try to control two LEDs, one connected to a pin in Bank A, and the other one
to a pin in Bank B?

Demo 2: Digital outs at both Banks


In this demo, I’ll show you how to control output pins in either Bank (A or B), either using
the lower-level Wire library or the Adafruit library.

Adjust your circuit so that it


contains a second LED, connected
to pin 1 of the port expander
(GPB0).

First, let’s get both LEDs to blink


using only the Wire library (see
sketch in next page):


4
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

#include "Wire.h"

void setup()

{

Wire.begin(); 

Wire.beginTransmission(0x20);

Set ports in Bank A (0x00) to be all
Wire.write(0x00);
 outputs.
Wire.write(0x00);

Wire.endTransmission();

Wire.beginTransmission(0x20);

Set ports in Bank B (0x01) to be all
Wire.write(0x01);
 outputs.
Wire.write(0x00); 

Wire.endTransmission();

}

void loop()

{

delay(100);
 Set the bit pattern for the port in Bank A
Wire.beginTransmission(0x20);
 (0x12). This will turn on the LED
connected to to pin 28 on the port
Wire.write(0x12);

expander.
Wire.write(B10000000); 

Wire.endTransmission();
 Set the bit pattern for the port in Bank B
Wire.beginTransmission(0x20);
 (0x13). This will turn on the LED
Wire.write(0x13);
 connected to to pin 1 on the port
expander. Notice how the least significant
Wire.write(B00000001); 

bit controls the state of pin 1.
Wire.endTransmission();

delay(100);

Wire.beginTransmission(0x20);

Wire.write(0x12); 

Wire.write(B00000000);

Wire.endTransmission(); 

Wire.beginTransmission(0x20);

Wire.write(0x13); 

Wire.write(B00000000);

Wire.endTransmission(); 

}

Let’s have a look at the equivalent sketch using the Adafruit library (next page):

5
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

#include <Wire.h>

#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

void setup() { 
 Set I/O 8, which is pin 1, to be output.


mcp.begin();
 Count I/O numbers counter clockwise
starting from IC pin 21 being 0 (GPA0).
mcp.pinMode(8, OUTPUT);

GPA7 is I/O 7, GPB1 is I/O 8, GPB2 is I/O
mcp.pinMode(7, OUTPUT);
 9 etc.
}

void loop() {

delay(100);

mcp.digitalWrite(8, HIGH);

mcp.digitalWrite(7, HIGH);

delay(100);

mcp.digitalWrite(8, LOW);

mcp.digitalWrite(7, LOW);

}

Next, let’s have a look at digital inputs using a button.

Demo 3: Digital inputs


In this demo, we’ll connect a button to one of the digital inputs. When the button is
pressed, an LED connected to a digital
output will be turned off.

Here’s the circuit:

The button is connect to pin 21, which is


GPA0. Don’t forget the pull down resistor
(10KΩ).

The sketch that reads the state of the


button and updates the state of the LED
could not be any easier, see next page:


6
Peter Dalmaris The MCP23017 port expander Arduino Step by Step

#include <Wire.h>

#include "Adafruit_MCP23017.h"

Adafruit_MCP23017 mcp;

void setup() { 

Set I/O 7, which is pin 1 (GPA7), to be
mcp.begin();
 output.
mcp.pinMode(7, OUTPUT);

mcp.pinMode(0, INPUT);
 Set I/O 0, which is pin 21 (GPA0), to be
} input.

void loop() {

mcp.digitalWrite(7, mcp.digitalRead(0));

}

! Use digitalRead to read the state of the


button, then update the LED with
digitalWrite.
!
!
Wrap-up
Using the MCP23017 port expander is almost trivial. The Adafruit library hides all the low-
level detail without adding much fat to the overall size of your sketch (it adds around 1,000
bytes to the amount of memory that the Wire library requires).

You could also use the MCP23017 as an I2C-based shift register and control 16 LEDs, or
an array of 8x8 LEDs. Just remember that each pin can provide a maximum of 15mA, so
you will need to consider your display’s power requirements.

You could also control relays and through them much larger loads, like motors and lights,
and make this part of your home automation system.

You might also like