ARM
Microcontrollers
35 projects for beginners
Bert van Dam
BertBert
van van
DamDam
Elektor
Elektor International
International Media
Media BV BV
p.o box
p.o box 11 11
61146114
ZG ZG Susteren
Susteren
TheThe Netherlands
Netherlands
1 BACKGROUND 10
1.1 WHAT IS AN ARM MICROCONTROLLER 10
1.2 WHAT IS A PROGRAM 11
2. WHAT YOU NEED 13
2.1 NEED TO HAVE 13
2.2 NICE TO HAVE 22
3. TUTORIAL PROJECTS 24
3.1 A SMALL TEST 24
3.2 YOUR FIRST C PROGRAMS 28
3.2.1 A flashing LED 29
3.2.2 Let's make a mistake 36
3.2.3 A different way of flashing 39
3.2.4 Change LED 40
3.2.5 Two alternating flashing LEDs 40
3.3 EXPLORE THE WEBSITE 41
4. SWITCHES 43
4.1 TIMER LED 43
4.2 TWO WAY SWITCH 50
4.3 THREE FLASHES 52
4.4 TIMED LED FLASHER 56
5. ANALOG SIGNALS 61
5.1 VARIABLE SPEED FLASHING LED 61
5.2 DARKNESS ACTIVATED SWITCH 66
5.3 SINGLE WIRE SILENT ALARM 69
5.4 SINE GENERATOR (ANALOG OUT) 75
6. USB COMMUNICATION TO A PC 81
6.1 ECHO 81
6.2 A SERIAL COUNTER 87
6.3 VOLTMETER 90
6.4 IN-CIRCUIT DEBUGGING 96
Index 247
livemail
mbed internet
youtube
modem/router
PC
In this book we will use the mbed platform which contains an ARM microcontroller, the
NXP LPC1768. The mbed uses cloud computing for programming, a revolutionary new
concept for software development. This means you do not need to install software in
order to program the mbed. All you need is an internet browser such as Microsoft Internet
Explorer, and a USB port on your PC. You develop software using your browser and
store the results in the cloud. You can access your project from any PC, anywhere in the
world, and continue working. After your work is completed it can be transferred with a
few simple mouse clicks to your mbed hardware. Of course you can download your
projects and store them locally if you prefer.
The projects in this book are meant for beginners, either with ARM microcontrollers,
microcontrollers in general or the C programming language. That doesn't mean that these
8 7 8
Apart from a projects book, this book is also a reference book. The explanation of the C
commands and mbed libraries with example programs makes this the kind of book that
you will want to keep next to your PC. The index will point you to explanations of the
commands and to sample projects.
I would like to thank Richard York, Simon Ford, Bert Oudshoorn, Bill Hohl and Chris
Styles for their help in realizing this book.
8 9
Let's look at a
daughter". At fi
only because y
understand that
sentence, name
without realizin
the most "logic
Figure 2. ARM microcontroller. "Question: If tr
Answer: We m
this is funny is
Because they can be programmed ARM microcontrollers can be used in many different down, so you w
ways. You can find ARM microcontrollers in mobile phones, organizers, cameras, VCRs, is given unexpe
remote control units, vending machines, and so on. They control motors and heaters,
decipher remote control signals, measure temperatures, and much more. It is because they So our natural l
are found LQVLGHPDFKLQHVWKDWPLFURFRQWUROOHUVDUHRIWHQFDOOHG³HPEHGGHGV\VWHPV´ don't want in ou
does exactly w
So even when you have never actually seen an ARM microcontroller you are practically formal language
surrounded by them. Chances are you have one in your pocket right now. In this book we mathematics. T
will explain how you can program an ARM microcontroller yourself. We will start with answer.
the very basics so do not worry if this is all new to you. Once you have completed the
projects in this book, you can move to the next level of knowledge and complexity and
buy part two - for intermediates - and part three - for experts - in the ARM series.
1
By Jack Handy
Famous for his D
10 9 10
A program is a set of instructions that tell your microcontroller what it needs to do. So
why do you need a special language for that? In English we can give instructions too. At
the breakfast table for example you might say "Could you hand me the butter please?"
and you will be handed the butter. Let's take a closer look at this question. You didn't
really ask for the butter. All you asked was if the person you addressed would be able to
hand you the butter. So the most logical result of the question would be "yes" or "no"
depending on the actual location of the butter. The words "could" and "please" are
redundant. You don't need them to get what you want, you were just trying to be polite.
Even if we ignore that, there is another problem with this question. You'd be very
surprised if the person to whom you asked this question would take the butter container
and dump the contents on your outstretched hand. Even though you just asked for the
butter you meant "the container that holds the butter, including the butter that is in it". So
even this simple question contains logical inconsistencies. You need to understand the
world in order to understand the question, rather than just knowledge about English
words.
Let's look at another example: "I saw the neighbor cutting down the tree with his
daughter". At first glance there appears to be nothing wrong with this sentence. But that is
only because you know what a tree is, and you know what a daughter is, so you
understand that the daughter was helping the neighbor. The other possible meaning of the
sentence, namely that the neighbor is using his daughter as a saw, is rejected by you
without realizing it. In fact a lot of jokes rely on your ability to automatically recognize
the most "logical" interpretation, by suddenly changing that interpretation. For example:
"Question: If trees could scream, would we be so cavalier about cutting them down?
Answer: We might, if they screamed all the time, for no good reason1". The reason that
this is funny is that you assumed that trees would only scream while they were being cut
down, so you were inclined to answer the question with "Probably not". The answer that
is given unexpectedly changes your interpretation as to when trees might scream.
So our natural language leaves a lot of room for interpretation, and that is something we
don't want in our microcontroller program. We want to be certain that the microcontroller
does exactly what we want, and nothing else. Languages without ambiguity are called
formal languages. An example of a formal language that you are probably familiar with is
mathematics. The question "1 + 1 = ? " leaves no room for interpretation and has only one
answer.
1
By Jack Handy, American Writer and cast member of Saturday Night Live from 1991-2003.
Famous for his Deep Thoughts comedy sketches.
10 11
There are many microcontroller languages such as C, JAL, Basic, and Pascal. In this book 2. What yo
we have opted for C because it is the most widely used language for programming
microcontrollers. If you are looking for information on the internet, such as example In this chapter
programs or tips and tricks, chances are you will find them in C. If you understand C you exciting hobby.
will usually be able to read other high level languages as well.
Apart from that
All programs consist of a series of commands. There are basically four types of to make notes.
commands. even more valu
you will find it
Inputs
The sources of
These commands collect information from components outside of the microcontroller. for free from t
This could for example be a switch or a temperature sensor. boek). You wi
errata for this b
Outputs
2.1 Need to
These commands send information from the microcontroller to components on the
outside. An example of such a component is a buzzer, or a LED.2 An mbed NXP
2
Some people pronounce LED as abbreviation (el-ee-de) in which case we need to write "an
LED". Others pronounce LED as a word (led, to rhyme with lead), in which cause we need to
write "a LED". With the increasing popularity of LED lighting more and more people pronounce
LED as a single word. For that reason we use "a LED" in this book.
11
12
Apart from that you also need this book, preferably your own copy so you can write in it
to make notes. Your own notes and information on parts that you use make this book
even more valuable. Writing in a new book for the first time is not easy, but after a while
you will find it easier.
The sources of the programs in this book, and accompanying software can be downloaded
for free from the publishers website, or from www.boekinfo.tk (note the spelling of
boek). You will also find other interesting information and links there, including the
errata for this book.
This book is based on the mbed NXP LPC1768 unit. It contains an ARM Cortex-M3
microcontroller and some associated hardware on a small printed circuit board - or PCB.
The board has pins in DIP format, which means it can be used on a breadboard - as we
will do in all projects in this book - or in a standard predrilled PCB. This means that no
soldering is required. The mbed has a USB connection used for programming and can be
connected to any PC that has a USB port. The same port will also be used in some of the
projects for communication between a program in the mbed and a program on your PC.
12
13
Your mbed comes with a small credit card size quick reference card that contains all Function
functionalities of the mbed and the associated pins. Keep this card with your mbed
because you will be using it quite often.
SPI
Serial
I2C
AnalogIn
The following table shows what the different pins and functionality's are for. The color AnalogOut
refers to the color on your card, not in this book for it is grayscale only. A lot of these
functions are discussed in this book, or in the next one - this book is the first in a series of
three. As you can see the list is quite impressive.
PwmOut
Function Color Description
These are the power pins. The mbed can be powered
by its USB connection or by a separate power supply
Power Red - connected to GND and Vin. The mbed is equipped CAN
with a built-in power regulator that supplies 3.3 volts
(Vout) and 5 volts (Vu) for your projects.
These pins understand - as input - or generate - as
output - voltages of either 3.3 or 0 volts, but nothing
in between. The mbed has 26 digital pins, all of
Digital Light blue
which can also be used for other purposes. In
addition to this the mbed has four LEDs labeled
LED1 to LED4 which act as digital outputs.
13
14 14
14 15
mention this in
Function Color Description
all projects, unl
USB - Universal Serial Bus - is a communication SURMHFWGRHVQ¶W
protocol used between the microcontroller and connected to the
USB Light orange
other computers such as a PC. The mbed has one
USB port3. Parts
Many suppliers
A browser for the Internet a good way to s
The mbed can be programmed in a revolutionary way. You do not need to install any The number of
software on your computer. All you need is a browser for Internet access. The same when you need
browser that you use for all your other internet activities, for example Microsoft Internet projects in this
Explorer.
Oscilloscope (S
A breadboard
A breadboard is an ideal tool for prototyping. Projects can be built very quickly and
easily simply by inserting the components into the breadboard.
Often the powerrails consist of two separate parts that are not connected to each other.
The top and bottom rails are never connected. In preparation for this book connect all
sections of the power rail together as you can see in the previous Figure. We will not
3
The USB connector on the mbed hardware is not connected directly to the microcontroller but to
a separate driver chip.
16 15 16
mention this in any of the projects so make sure you prepare your breadboard this way for
all projects, unless specifically told otherwise. <RXZRXOGQ¶WEHWKHILUVWWRZRQGHUZK\D
SURMHFWGRHVQ¶WZRUN RQO\WRILQG RXWODWHUWKDW part of the power rail you used was not
connected to the power source.
Parts
Depending on what you want to build you will need electronic parts. If possible try to get
SDUWVWKDWILWLQWRDEUHDGERDUG6RPHSDUWVPD\KDYHZLUHVWKDWDUHWRRWKLFN'RQ¶Wforce
them into the breadboard, but solder small wires to them instead.
Many suppliers sell small bags of mixed parts (resistors, LEDs, capacitors). This may be
a good way to start your parts collection.
The number of parts that you need for this book is quite limited. You can either buy parts
when you need them, buy a starterkit, or use the list in the appendix to buy parts for all
projects in this book.
Oscilloscope (Software)
16 17
When working with for example sound a simple oscilloscope can be a very convenient [î
tool. You do not need an expensive machine for this. A simple software tool that runs on
10
your normal PC will do just fine for the projects in this book. It does not need to be
installed so it can run on any computer off a memory stick or even the mbed.
The software oscilloscope WinOscillo uses the soundcard of a PC to convert the signals.
One of its limitations is that you need to make a small interface to protect the soundcard. 5
10 k
measuring
pens -5
left or right
2k2 LIN
2k2
MIC in
common
The interface in the previous Figure is used to reduce the maximum voltage on the Unfortunately t
microphone or line input of the soundcard from a maximum of 5 volts to 0.9 volts. Never commands that
connect the interface to voltages over 5 volts. Make sure you connect the common and need a few, and
left or right wires correctly, and make sure that the common wire is connected to the
ground of your project, and not the other wire. Inside your PC the common of the Com
soundcard, and the ground of RS232 and USB are all connected. So if you switch those F
around on your project you are likely to blow a fuse or cause some other damage. F
alt-e
In the Windows Mixer you need to enable the microphone, and turn the level to full.
Switch off noise suppression and other signal enhancements if the Mixer shows these Ctr
features. Ctr
Ctr
Apart from just viewing the signal WinOscillo can also make a recording of the signal, or Ctr
take a snapshot of the image so you can save it. In this book you will find several Ctr
examples. Crt
Crt
17
18 18
10
-5
-4 -2 0 2 4
Dt=3,84 ms t (ms)
Figure 8. WinOscillo saved image with measuring lines and timed interval.
Unfortunately the user interface of WinOscillo is in French. The next list shows the
commands that you will use most, with the English translation. Fortunately you will only
need a few, and the shortcuts are easy to remember.
Command Explanation
F2 Select oscilloscope...
F3 ... or spectrum.
alt-enter Full screen (with controls on top).
Ctrl-S Store signal (as a short .wav or as .csv for use with Excel).
Ctrl-L Load signal (select pause first otherwise it will take ages!).
Ctrl-M Take a snapshot as .wmf.
Ctrl-V Vertical cursor line.
Ctrl-H Horizontal cursor line.
Crtl-W Switch between both (if both are enabled).
Crtl-G Tone generator.
18 19
Pea
HyperTermina
In many project
to work you ne
are included in
moment you do
Figure 9. Spectrum Analyser.
When working with for example sound or interrupts a frequency counter or a spectrum
analyzer can be a very convenient tool. The free Analyzer in the download package 4
It is a VB3 prog
If your version
vbrun300.dll in t
located. Installati
19
20 20
requires the same interface as WinOscillo. It does not need to be installed so it can run on
any computer off a memory stick or even the mbed.4
The operation is simple. Connect the interface to the microphone or line input of the PC.
Make sure you connect the common and left or right wires correctly, and make sure that
the common wire is connected to the ground of your project, and not the other wire.
Inside your PC the common of the soundcard, and the ground of RS232 and USB are all
connected. So if you switch those around on your project you are likely to blow a fuse or
cause some damage.
Click on the Run button to start the program. The whole spectrum of frequencies that the
program detects is displayed. Click with the mouse button in the graph near the peak that
you are interested in. The blue line will jump to that location. The program will
automatically search for the highest peak near the blue line and indicate that with a short
red line. The measured frequencies of the blue line - called "Mark"- and the red line -
called "Peak" - are displayed in the lower right corner.
Command/Option Explanation
Resolution Resolution of the measurement.
Max Level Vertical max.
Range Vertical scale.
Ave Number of measurements that is averaged.
Display Three ways to display the data.
Mark Frequency at the blue line.
Frequency at the nearest peak to the blue line - shown with a
Peak
short red line.
In many projects we will use a USB connection to display data on a PC. In order for this
to work you need a terminal program such as HyperTerminal and an mbed driver. Both
are included in the free download. In section 6 the installation is discussed. At this
moment you do not need to do anything yet.
4
It is a VB3 program, so you need vbrun300.dll. Most Windows versions support this by default.
If your version doesn't (you will know because the program will not start) you will find
vbrun300.dll in the free download. Place this file in the directory where the Spectrum Analyser is
located. Installation is not needed.
20 21
21
22 22
Sound Editor
When using sound in microcontrollers you must be able to change the sampling rate.
Many programs claim to do that but when saving the converted sound they revert back to
default sampling rates. In this book we will use Cool Edit. In the download you will find
a shareware version of Cool Edit 96.
Instructions on how to convert sound to another sampling rate are given in section 9.4.
The sounds you need for the projects in this book are part of the download file, so
installing Cool Edit is not required for this book, but if you want to use other sounds you
will need it.
22 23
Connect the mbed to a free USB port on your PC using the supplied USB cable. The blue
LED on the mbed will light.
Figu
Your default br
the mbed webs
yourself. Make
will need this qu
Usern
Figure 13. Mbed connected to the PC.
Passw
The PC will make a dong-ding sound. Simply wait and do nothing. Windows will
recognize the mbed as a "microcontroller" and tell you about this using a small window.
After a few seconds it will also recognize it as "USB device for mass storage". You do
not need an administrator account or administrator privileges to do this, so it will work on Depending on y
any modern Windows PC. saying that you
24 23 24
After both little windows have been shown and closed, open Windows File Explorer on
your PC and go to the newly created drive called "MBED". On this drive, which is in
reality the mbed itself, you will find a file called "mbed.htm". Make sure you have a
connection with the internet and double click on this file. The screenshots in this section
are made on a Windows XP SP2 machine, Dutch version, so your screens may differ but
they will contain the same information.
Your default browser (in my case Microsoft Internet Explorer) will start and connect to
the mbed website on the internet. Click on the sign-up button and create an account for
yourself. Make a note of the username and password that you have selected because you
will need this quite often.
Username
Password
Depending on your browsers' security settings you may get a warning while logging in
saying that you are about to view unsecure content. This is because some of the content
24 25
on the mbed website is user based - and thus secure - but some is accessible to everybody
- thus unsecure. This warning is normal, simply click on the OK button.
25
26 26
A small window will pop up asking if you want to store the file
"HelloWorld_LPC1768.bin". Click on the Save button and save the file on the mbed
drive. While saving the blue LED on the mbed will flash irregularly.
26 27
At this point the file, which is the "Hello World" program, is on the mbed but it has not way you will
been loaded in the microcontroller yet. Press the little button on the mbed to load the file programs in thi
into the microcontroller and run it. The blue LED will flash shortly to indicate that program manua
loading is in progress. Then the program will run, and flash the first LED on the row of quicker this way
four on the mbed.
3.2.1 A flashin
Congratulations! You have executed your first ARM microcontroller program: a flashing
LED!5
So what just happened? On the mbed website you selected a pre-compiled program. You
downloaded a flashing LED program called "Hello World" onto the mbed hardware,
loaded the program into the ARM microcontroller and started the program. Without any
kind of special software or cumbersome installation progress!
From this point onward we will assume that you know how to access and login to the
mbed website. If in doubt consult the steps we took in this project.
In the first tutorial project we used a precompiled program. In this project you will write
your own C program. Well, almost anyway. Microcontrollers do not understand normal
human language. Instead they require a special language. In this book we will use a
programming language called C. This language is very popular, and almost everyone who
programs microcontrollers on a professional level uses it, or knows how to use it. Other You will need t
languages are for example JAL, Basic and Flowcode. When you see a C program for the you get a warn
first time it looks a bit intimidating. That is because it uses special characters like * { ; # enable it.
etc, but it is not all that hard to master. In this book we will learn by doing. So we will
discuss a project, and discuss the C commands that we use in the project one by one. That
5
If the LED doesn't flash you most likely saved the file to a different location instead of the mbed
drive, so the microcontroller cannot find it. Click on the "Hello World" button and try again.
27
28 28
way you will get direct hands-on experience. Even though the source code of all
programs in this book is part of the free download I would recommend that you enter the
program manually anyway. This is of course more work, but you will learn C a lot
quicker this way.
Let's get started. If you haven't done so already login to the mbed website. On the top
right hand side click on the word "Compiler".
You will need to have Javascript enabled in order for this part of the website to work. If
you get a warning that Javascript is disabled consult your browser manual or helpfile to
enable it.
28 29
Depending on your browsers' security settings you may get a warning after you select the With the right
compiler saying that you are about to view unsecure or mixed content. This is because workspace. A s
some of the content on the mbed website is user based - and thus secure - but some is gray with a sm
accessible to everybody - thus non-secure. The warning is normal, simply click on the "Tutorial" (with
OK button. and then the win
The compiler is a special program - on the internet - that will take a program written in C The program w
and convert it into a different format so it can be transferred into the microcontroller. The find a line calle
compiler screen consists of three separate areas. On the left hand side is the "Program "mbed" and an
Workspace". This is your own private area where you can store your programs. At this second line con
moment of course there are none. The top screen on the right side is the "Program for now click on
Workarea". Here you will see the actual C code or the program that you are working on.
And on the bottom you will find the "Compiler Output" area. This is where messages
from the compiler will be shown. The top menu is gray - because no programs have been
selected - except on the far right side where you can select the ARM microcontroller that
you use. It should say "mbed NXP LPC1768" because that is the mbed that we are using
in this book.
6
The "new" butto
29
30 30
With the right mouse button single click on the text "MyProgram" in the program
workspace. A small menu will open up. Select new program. 6 The screen will become
gray with a small window where you can enter a name for your new program. Enter
"Tutorial" (without the quotation marks) and click on OK. A few messages will appear
and then the window closes.
The program workspace now contains a program called Tutorial. Underneath you will
find a line called "main.ccp" with an icon of a piece of paper in front of it, and a line with
"mbed" and an icon of a gear. The first line is the file that contains your program, the
second line contains the libraries. We will discuss the libraries in the following chapters,
for now click on "main.ccp" to open the program.
6
The "new" button in the top left corner has the same effect.
30 31
give it a differe
used as input as
the format of a
type na
Much to your surprise you will find that a program is already there, even though you
didn't do anything yet. This is the default program - to flash LED1 - to help you get
started. Let's take a close look at this program.
The first step in any program is to load a library. A library is basically a selection of
commands that are specially designed for the microcontroller that you are using. Most of
these commands are not standard C commands but extra commands that allow you to use
all of the features of the microcontroller. You can load a library using the command
"#include" followed by the name of the library. Since we use the mbed hardware we will
load the mbed library. We have already told the compiler that we are using the NXP
LPC1768 - as shown at the top right corner - so the compiler will automatically select the
mbed library that is required for this particular ARM microcontroller.
#include "mbed.h"
The "pin" refers
Please note that C is case sensitive. That means that Include is
is not
not the
the same
same as
is include. card. And thes
The next step is to give a suitable name to the pins that we want to use. With the mbed addition to the
you have received a little quick reference card with all the pins and their functions. Not to LED4.
on the card are the four LEDs on the mbed, called LED1 to LED4. We will use LED1 but
DigitalO
31
32 32 32
give it a different name that is easier to remember: myled. Most pins on the ARM can be
used as input as well as output so we need to indicate how we want to use them. This is
the format of a declaration:
type name(pin);
The "type" indicates what kind of functionality we want to have. You can only choose
functionality that is available for that pin. Pin 5 for example can be a digital pin or an SPI
pin but not a USB pin. An output means that power will go out of the microcontroller to a
device connected to that pin. So an output can be used for example to light a LED. An
input means that power will go into the microcontroller. So an input can receive signals
from for example a switch. Since a LED is involved the pin can only be an output so we
define it as DigitalOut.
The "name" can be any name that you want to use in your program. It is usually a good
idea to use an informative name - so it is clear what you are referring to - but not too long
- so you do not need to enter a long name every time you want to use it.
The "pin" refers to the external connections of the mbed as shown on the quick reference
card. And these refer in turn to the physical pins underneath the mbed hardware. In
addition to the pins shown you also have access to four built-in LEDs with "pins" LED1
to LED4.
DigitalOut myled(LED1);
32 33
You can read this as "LED1 is a DigitalOut that I will call myled". Perhaps you noticed In our program
that the command is followed by a semi-colon. In C this is necessary so that the compiler
knows when one command ends and the next one starts. You don't have to use a semi- while(1
colon after a curly bracket because the curly bracket itself indicates the end of a your
command. It is a little bit like the point - full stop - at the end of an English sentence, }
which indicates to the reader the end of one sentence and the beginning of the next.
Beginners in C very often forget to use the semi-colon, so beware. In C however 1
opposite of true
This concludes the definition part of the program. The next part contains the actual statement mean
commands. Here we can tell the microcontroller what to do. In C this part is called program will
"main", and it has this syntax: microcontroller
In the appendix you will find an overview of the C commands used in this book so if you myled =
don't remember the correct syntax you can look it up. You can also use the index also to
look for an example for the C command to see how it can be used. In order to mak
again otherwise
The next command in the program is "while", with the following syntax: makes the progr
while(condition) { wait(sec
your commands - or actions - go here
} This time is in s
This is how the "while" command works: while a certain condition is met - we call this wait(0.2
"true"- the commands between the braces are executed. The condition that has to be true
is shown between then parenthesis. This command is much like regular English, just Now all we nee
formatted differently. You might for example say "While I'm driving I keep my eye on forever (otherw
the road". As long as "I'm driving" is true, you take the action "keep your eye on the
road". At this point w
summarize:
while(I'm driving) {
I keep my eye on the road
}
33
34 34
while(1) {
your commands - or actions - go here
}
In C however 1 means the same as true, and 0 means the same as false - which is the
opposite of true. So while(1) can be read as while(true). Now true is always true, so this
statement means that the commands between the braces will be executed forever. The
program will never exit this loop, so it will never stop! Unless you turn the
microcontroller off or replace the program by another one.
That means the following commands in our program will be executed forever:
myled = 1;
wait(0.2);
myled = 0;
wait(0.2);
We already know that 1 means the same thing as true, but it also means the same thing as
"on". So myled - which as you will remember is LED1 - is switched on by this command:
myled = 1;
In order to make a flashing LED we need to wait a little bit before we switch the LED off
again otherwise it will happen so fast that you will not see any of it. The "wait" command
makes the program wait for a certain time.
wait(seconds);
This time is in seconds, so the next line makes the program wait for 0.2 seconds.
wait(0.2);
Now all we need to do is switch the LED off, wait a bit, and then repeat these commands
forever (otherwise the LED would flash just once).
At this point we have discussed all C commands in this flashing LED program. Let's
summarize:
34 35
myled =
Program Explanation
The "save" but
#include "mbed.h" Include the library with extra commands. some unsaved c
will immediate
DigitalOut myled(LED1); Give LED1 the name myled and tell the compiler that it window doesn't
is an output.
36 35 36
myled = 1
The "save" buttons in the menu bar have now turned green. That means that you have
some unsaved changes in your program. Click on "save" first and then on "compile". You
will immediately get an error message in the compiler output area, and the download
window doesn't appear.
The error is indicated with a red icon and says "Expected a ";" (E65)". On that same line
the compiler also tells you where the error is located: in main.ccp in the Tutorial project,
in line 8 column 8.
If you check to see where line 8 column 8 is you will find that this is not the place where
the semi-colon was removed, but the place where the compiler discovered that is was
missing. In this case you could place the semi-colon at that exact spot and fix the problem
(don't take my word for it: try it) but that would make your program very hard to read for
others because they expect to see the semi-colon behind a command and not in front of
the next one. So put the semi-colon where it belongs and save the file.
The next line in the compiler output area is not an error but a warning, hence it has a blue
icon. The warning is that since the program contains an error a download file cannot be
generated.
In a lot of cases you cannot fix the problem at the location where it is discovered. As an
example remove the first brace in the while command, and then compile the program, like
this:
while(1)
myled = 1;
wait(0.2);
myled = 0;
wait(1);
}
36 37
very regular ba
lines that you en
Often multiple
one brace resul
first error or wa
Figure 26. Compiler confusion with missing brace. as well.
This time the error message is much less clear. First we get a warning that the statement A special kind
in line 8 is unreachable. The reason for this is that if you have only one statement program compi
following the while command you do not need to use the braces. during executio
LEDs pattern.
while(1)
myled = 1;
wait(0.2);
myled = 0;
wait(1);
}
So as far as the compiler is concerned the bold part is a valid while statement, which to
the compiler looks like this: Should you run
consult section
while(1) myled = 1;
3.2.3 A differe
Since 1 is always true this tiny while loop - just the "myled = 1" command - will never
exit. That means that any command after the while loop will never be executed, or as the Let's change th
compiler calls it: such a command is "unreachable". Technically that is not a syntax error, seconds, but of
so the compiler issues a warning as shown by the yellow icon. The compiler accepts the further. Note t
first closing brace it encounters because it thinks that it belongs to the main statement, but downloading yo
then it reads a second closing brace in line 12 and issues an error for that: "Expected a And do remem
declaration (E169)". microcontroller
The next line in the compiler output area is not an error but a warning, hence it has a blue The correct pro
icon. The warning is that since the program contains an error a download file cannot be
generated. Note that if your program has warnings only it will compile and download. Do #includ
pay attention to the warnings though, because they usually indicate that even though the
program doesn't contain any syntax errors, chances are it will not do what you expect it to DigitalO
do.
int main
So you see that just by reading the error messages it is not always simple to find out what while
went wrong. For that reason the best way to develop a large program is to compile on a my
wa
37
38 38
very regular basis. Then if an error pops up you know you probably made it in the last
lines that you entered.
Often multiple errors and warnings in a program are related. In this example leaving out
one brace resulted in one warning and one error. When debugging it is best to solve the
first error or warning, and then simply recompile. With any luck that solved other issues
as well.
A special kind of error is the "blue LEDs of death". This means that even though the
program compiled and downloaded just fine the mbed ran into an unrecoverable error
during execution. You can recognize this error because it generates a distinct flashing
LEDs pattern.
Should you run into this situation and you can't seem to find out what the problem is
consult section 10.5 for debugging information.
Let's change the way the LED flashes. This time we want the LED to be on for 0.2
seconds, but off for 1 second. Try to change the program and test it before reading
further. Note that this program has the same name as the previous one so while
downloading you will be asked if you want to overwrite the existing file. Select "yes".
And do remember to press the button on the mbed to load the file into the
microcontroller.
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1;
wait(0.2);
38 39
myled = 0;
wait(1); The correct pro
}
} #includ
Blog
In order to achieve two alternating flashing LEDs we need to do two things.
1. First we need to define both LEDs, and give them different names, for example
myled1 and myled2.
2. Then we need to switch one LED on and the other off, want a bit, and reverse the
situation. We can use the flashing frequency of the previous project.
Try to write a program based on this information - chose any two LEDs you want - and
test it before reading on.
39
40 40
#include "mbed.h"
DigitalOut myled1(LED1);
DigitalOut myled2(LED4);
int main() {
while(1) {
myled1 = 1;
myled2 = 0;
wait(0.2);
myled1 = 0;
myled2 = 1;
wait(1);
}
}
The mbed website contains a wealth of information. At this point you may find a lot of
that information rather complicated and perhaps overwhelming but as you progress
through this book you will find the website quite informative and very useful. When the
time is right you will be pointed to the right sections, for now simply look around, click
on the links and get a feel of what is available. Note that everything you see if free for
private use, but limitations may exist with respect to public or commercial usage.
Item Description
Information on mbed and the website by the developers. Here
Blog
you will find new developments and planned upgrades.
40 41
4. Switche
Item Description
This is where you can ask questions and read answers and tips In this chapter
from other mbed users. Before you post make sure to search the probably a goo
forum first so the same questions don't get asked over and over. subjects. If you
The subjects are on the right hand side of the screen. The forum commands are
Forum variables.
is in English, but for many users this is not their first language.
So if you feel someone has insulted you it's best to assume that
he or she hasn't mastered English very well, and may appear 4.1 Timer LE
rude without intending to be.
Lot's of information on the mbed and the base library, and In this project
Handbook
reference guides. Technically thi
An area where mbed users can post projects, experiments, switch. The firs
Cookbook
resources and ideas for others to see and use.
If a microcontro
An assortment of notes that mbed users have posted. Treat with means it must
Notebook caution: some notes may work, others may not. These are connect a switc
generally not finished projects. anything and th
Your personal page on the mbed website. You can enter details in two different
in your profile and post notes, idea's and software. You can
MyHome
upload a picture of yourself, which will be shown for example + 3.3V
in the forum when you post a message.
MyNotebook A direct link to your notebook in the MyHome section.
The pin-out guide and technical reference to the NXP LPC1768
QuickReference
microcontroller. We will be using this section quite often.
Technical data and a link to the datasheet. We will be using this
Technical Reference
section quite often.
Imagine that in
the ground thro
now low - also
down" to the gr
closed the pin i
switch is closed
41
42 43
4. Switches
In this chapter we will discuss switches. This subject is not very complicated so it is
probably a good idea to build some of these before moving on to the more advanced
subjects. If you are new to C programming at least read this chapter because new C
commands are introduced such as "if-then" and "for", as well as logical operators and
variables.
seconds when
In this project we will light a LED for 5 seconds when the
the uses
user presses a switch.
Technically this is called a monostable multivibrator, but it is better known as a timer
switch. The first thing we need to know is how to connect a switch to a microcontroller.
If a microcontroller is keeping an eye on a certain pin this pin is not allowed to float. That
means it must always be connected to either the plus or the ground. If you were to
connect a switch to a pin, and the switch is open, then the pin would not be connected to
anything and that is a forbidden state. So we will use a resistor, which can be connected
in two different ways.
+ 3.3V + 3.3V
10 k
switch
to mbed pin
to mbed pin
switch
10 k
Imagine that in the previous Figure the left switch is open. The pin is now connected to
the ground through a 10k resistor. So from the microcontroller's point of view the pin is
now low - also called zero or false. You might say that the resistor is "pulling the pin
down" to the ground, and for this reason it is called a pull-down resistor. If the switch is
closed the pin is connected directly to the plus - also called high, one, or true So if the
switch is closed the signal on the pin is true, if it is open the signal on the pin is false.
43 42
43
The setup on the right side of the previous Figure works exactly opposite. In this case
closing the switch results in a false reading. That is a bit counter-intuitive so we will not
use it in this book, but you may come across it on the internet. The resistor in this set-up
is called a pull-up resistor.
When the switch is closed a small current will flow through the resistor, so it is a good
idea to use a rather high value resistor. Generally speaking 10k is considered a suitable
value. Using Ohm's law we can calculate how much current goes through the resistor.
V=I*R
Or written differently: I = V / R or R = V / I
So in this case the current is 3.3 volts / 10.000 ohm = 3.3 10-4 A or 0.33 mA7. That is
almost nothing, but why do we even care? Well, we get our power from the USB port that In order to buil
usually can deliver about 500 mA. The mbed has a current limiter on the USB power shown in sectio
supply that cuts off at 450 mA to prevent damage to the host PC. The mbed itself uses need to make th
about 100 to 200 mA so that leaves 250 to 350 mA for us to play with. This means we do
need to keep an eye on the power consumption. Fortunately the current that flows through
the resistor poses no problem.
Now that we know how to connect a switch we need to determine which pin to use. For
that we consult the quick reference card. We can use any of the light blue ones (5 to 30),
so we will select for example pin 20.
Use the schema
the resistor is b
decoding the c
represented as
clarification.
7
If a notation like 4 10-3 is new to you it can be read like "move the decimal point 3 places to the
left". So 4 10-3 is the same as 0.004. By the same token 4 103 is the same as 4000 - "move the
decimal point three places to the right". The meaning of the letters is: M=106, k=103, m = 10-3, u =
10-6, n = 10-9, p = 10-12
43
44 44
In order to built this project you need a breadboard, with all power sections connected as
shown in section 2.1. We will power the breadboard using the mbed itself, so you will
need to make the following connections.
Pin Connection
GND To the blue powerline of the breadboard.
Vout To the red powerline of the breadboard.
20 To the switch.
Use the schematic and picture of the breadboard to build this project. The color coding of
the resistor is brown-black-orange (keep the gold or silver band on the right side when
decoding the colors). The mbed identified as the LPC1768 is in the schematic, and
represented as a rectangle. Only the pins in use are shown, the others are left out for
clarification.
44 45
10k
Note that since
main program w
need a new C co
if (condi
Figure 29. Timer LED schematic.
comm
}
else{
comm
}
It is possible tha
if (condit
comm
}
If the button is p
45
46 46
turns blue when you enter it you have to use a different name instead8. In our program we
will use the name button - from push button switch. This means that this is definition part
of the program:
#include "mbed.h"
DigitalIn button(p20);
DigitalOut myled(LED1);
Note that since pin 20 has no special name - like LED1 - we must refer to it as p20. In the
main program we need to do something based on the condition of the switch. For that we
need a new C command: the if-then statement:
if (condition){
commands if condition is true
}
else{
commands if condition is false
}
There are some similarities to the while command. There is a condition between brackets,
and there are commands between braces. If the condition is true then the first set of
commands is executed, else - meaning the condition is false - the second set of
commands is executed. In our program the condition is the state of the button.
It is possible that you do not need the "else" part. In that case you can omit it:
if (condition){
commands if condition is true
}
If the button is pressed - meaning the pin will be high - action must be taken.
if (button == 1){
light the LED for 5 seconds
}
Note that we used a double equal to sign. A single equal to sign is meant for calculations,
a double one for conditions. That means that button == 1 means "is the value of variable
8
Since C is case sensitive you could use Switch as a variable. This is however likely to cause
confusion so we will never do that in this book. In fact most programmers will refrain from this.
46 47
button equal to one?". But button = 1 means "Give the variable button value 1". This is a indented and un
frequent source of mistakes so beware.9 We already know that 1 is the same as true so we example, where
can simplify this to:
Indente
if (button){ #include
light the LED for 5 seconds
} DigitalIn
DigitalO
We know how to turn the LED on and off and how to wait, so the rest of the program is
straightforward. This is the completed source: int main
while
#include "mbed.h" if (b
m
DigitalIn button(p20); w
DigitalOut myled(LED1); m
}
int main() { }
while (1) { }
if (button) {
myled = 1; You can indent
wait(5); But there is an
myled=0; "Format" and y
} when you have
}
} Indenting will a
programmer of
with this:
Enter this program into the compiler on the mbed website, compile and download to the
mbed drive. Once downloading is completed press the button on the mbed to transfer the if (butto
program into the microcontroller. If you press the button on the breadboard LED1 will }
light for 5 seconds. From now on we will assume that you know how to compile and
download a program. And then expan
You may have noticed that we indent the code every time a loop or condition is used. if (butto
This way the source is much easier to read. The next table shows the same source myle
wait(
myle
9
}
What would happen is you say "if (button=1) then..."? The microcontroller will first give button a
value of 1. This will always be possible, so the "condition" is always true and the commands
following the "then" statement will always be executed. Of course you can simply try this in your
program and see what happens.
47
48 48
indented and un-indented. Do you notice how hard it is in the second source to see, for
example, where the while loop ends?
You can indent your source yourself - and in fact you should, if only to learn how to do it.
But there is an easier way. In the compiler click on the magic wand button labeled
"Format" and your entire source will be indented for you. This is particularly convenient
when you have moved chunks of code around and the indenting is off.
Indenting will also help you to remember closing brackets or curly brackets. Experienced
programmer often enter the brackets first, and then fill them in later. They would start
with this:
if (button) {
}
if (button) {
myled = 1;
wait(5);
myled=0;
}
48 49
int main() { }
while (1) { }
if (button) { }
myled = !myled;
} There is a risk
} the microcontro
} make the pin h
before it will in
This program does work, but you will not see any of it. Before you are able to remove flip the pin so t
your finger off the switch the LED has been on and off thousands of times. So there is no "flips" the pin t
telling in which position it will end. The solution is to make the program wait until you to the microcon
release the button using a while statement.
The faster you f
while(button); project all we h
this is not a pro
capacitor - than
49
50 50
While the button is pressed the while statement is repeated. The loop doesn't contain any
other commands so the program will "stop" here and wait for the button to be released.
This is much better but not perfect. The switch we use is a mechanical device. When you
press it the contacts internally touch and then slide over each other to their final position.
During this sliding the contacts sometimes touch, and sometimes don't. You will not see
any of this but the mbed is lightning fast, so it will see it, and assume this to be a series of
rapid button-presses by the user. This effect is called "bouncing" of the switch. We can
fix this easily by making the microcontroller wait for a very short moment before
accepting a new switch position. Depending on the quality of the switch a time between
0.1 and 0.5 seconds is more than enough, so we will select 0.3 seconds.
while(button)wait(0.3);
#include "mbed.h"
DigitalIn button(p20);
DigitalOut myled(LED1);
int main() {
while (1) {
if (button) {
myled = !myled;
while(button)wait(0.3);
}
}
}
There is a risk associated with the statement myled =!myled. In order to make this work
the microcontroller first has to check what the actual status of the pin is. Let's assume we
make the pin high, and connected to the pin is a capacitor, that must be charged first
before it will indeed be high. Let's assume that before charging is completed we want to
flip the pin so the microcontroller check the status. It is (still) low so the microcontroller
"flips" the pin to high. Again. If the load is large enough it may in fact "never" look high
to the microcontroller.
The faster you flip the pin, or the higher the load, the sooner you run into trouble. In this
project all we have connected to the pin is a LED, and we flip it at a leisurely pace. So
this is not a problem. If the speed is high, or the load is too high - for example a coil or a
capacitor - than it is better to use an intermediary variable.
50 51
But imagine we
flag = ! flag; so it is better to
myled = flag; such as the num
while the prog
In order to do this we will need to define "flag" as a variable. We will discuss how that change value.
can be done in the next project. variable a name
memory of the
For now all that remains is to build the hardware. We will use the exact same hardware as location is, and
in the previous project. Once the program is running press the switch to light the LED, programmers ar
and then press it again to switch it off again. If it doesn't always work then increase the will see it very
debounce time slightly. we might as we
refer to i we b
memory locatio
4.3 Three flashes
In this project we will make a LED flash three times for 0.1 seconds every time you press This is very m
the button. Of course we could do that like this: drawer - for ex
drawer is the va
#include "mbed.h"
Before we can u
DigitalIn button(p20); be reserved for
DigitalOut myled(LED1); The more room
also the more
int main() { reserve more ro
while (1) {
if (button) { Dataty
myled = 1; (unsig
wait(0.1);
myled = 0; signed
wait(0.9); unsign
myled = 1; (signe
wait(0.1);
unsign
myled = 0;
wait(0.9); (signe
myled = 1; float
wait(0.1); double
myled = 0;
wait(0.9);
The previous ta
}
"to" means "up
}
} 10
The signed (po
be omitted if it i
Note that the defa
51
52
But imagine we want the LED to flash 200 times. That program would look rather silly,
so it is better to use a counter. A counter is a variable that is used for counting things,
such as the number of flashes. A counter is a variable. That means that the value can vary
while the program is running. The opposite of a variable is a constant, which cannot
change value. Variables are stored in the microcontrollers memory. When we give a
variable a name what we are really doing is giving a name to a specific location in the
memory of the microcontroller. We as programmers have no idea where this particular
location is, and we don't need to know because we give it an easy to remember name. C
programmers are for some reason very fond of the letter "i" as name for a variable, so you
will see it very often as name for counters and the like. We will use it too, even though
we might as well use the letter "f" or a complete word such as "counter". So whenever we
refer to i we basically tell the microcontroller something like "go see what is in the
memory location that we named i, and use the value that you find there".
This is very much like a drawer. The drawer is the memory location, the label on the
drawer - for example "socks" - is the name of the memory location and what is in the
drawer is the value of the memory location - for example socks = 6.
Before we can use a variable we need to tell the mbed compiler how much room needs to
be reserved for this variable - in our drawer metaphor: how large the drawer needs to be.
The more room we reserve the larger the value is that the variable can hold. But of course
also the more memory is used, and the supply is not unlimited. It is advisable to not
reserve more room then you really need.
The previous table shows some of the datatypes that we can use. In this context the word
"to" means "up to and including". The precision means that even though these variables
10
The signed (positive and negative numbers) and unsigned (positive numbers only) indicator may
be omitted if it is shown between brackets. So a char is exactly the same as an unsigned char.
Note that the default for char is unsigned but for short and int it is signed.
53
53
can hold very large numbers the precision is just 6 digits. Note that if you want decimals Logical
you must choose either float or double, even if you use small values. The range of a
variable "wraps around". This means that if you cross the range boundary you continue at
the other boundary. If for example a char holds value 255 and you add 1 you cross the
range boundary, because the maximum is 255. That means you continue at the other end
of the range, so at 0. So for a char 255 + 1 = 0. By the same token 255 + 5 = 4.
The first three types are also available in an unsigned version. That means that that
negative values are not allowed, and the positive range is longer. An unsigned char has a
range from 0 to 255. The upper value can be calculated by adding the "normal" ranges
while ignoring the minus sign, so 128 + 127 = 255. Since we want to count to three a char
will do nicely, which is declared like this:
In case the < operator is new for you, a small overview of the commonly used operators is
shown in the next table.
}
53
54 54
You could read this command "for (i=0;i<2;i=i+1)" as "starting at zero increment i at
each loop while i is smaller than 2". In this project we want to flash the LED three times,
so we need so slightly modify the for command to
for (i=0;i<3;i=i+1)
Before you read further, verify that this "for" command will indeed run three times. You
will find that i = i + 1 is often abbreviated to i++. Abbreviations like this unfortunately
make C code difficult to read for beginners, but everybody uses it so we do need to
discuss it in this book. And use it too, so you will become accustomed to it. That means
the complete program is:
#include "mbed.h"
DigitalIn button(p20);
DigitalOut myled(LED1);
char i;
int main() {
while (1) {
if (button) {
for (i=0; i<3; i++) {
myled = 1;
wait(0.1);
myled = 0;
wait(0.9);
}
}
54 55
}
} Command
t.start()
The next table shows some abbreviations that you are likely to encounter in this book or
other C programs: t.reset()
t.stop()
Abbreviation Meaning Explanation t.read_us()
i++ i=i+1 Increment i by 1.11 t.read_ms(
i-- i=i-1 Decrement i by 1. t.read_s()
i+=5 i=i+5 Add 5 to i.
For reading a t
i-=5 i=i-5 Subtract 5 from i. name you need
i*=5 i=i*5 Multiply i by 5. your timer myti
i/=5 i=i/5 Divide i by 5.
In this project w
then we will fla
The hardware is identical to project 4.1. Once the program is loaded press the switch seconds the LE
momentarily. The LED will now flash three times. not flash during
The program de
4.4 Timed LED flasher also declare a ti
#includ
In the previous project we used a counter to count events. In this project we will use a
timer to measure elapsed time. Unlike a counter a timer is not a normal variable. It is
DigitalI
basically a built-in stopwatch that can be started, stopped and read much like a normal
DigitalO
stopwatch. In the mbed we can use an "unlimited" number of timers. Each timer can have
Timer t
it's own name, just like a variable.
The next step is
Timer t;
the button, and
value it can hol
The previous statement declares a timer with name t. With this timer we can use the
anyone would w
following commands:
int i;
55
56 56
Command Description
t.start() Start timer t.
t.reset() Reset timer t to 0.
t.stop() Stop timer t.
t.read_us() Read the time of timer t in uS (microseconds)12
t.read_ms() Read the time of timer t in mS (milliseconds)
t.read_s() Read the time of timer t in S (seconds)
For reading a timer you need to use an int. Note that if you give your timer a different
name you need to replace the "t" in the table with the name of your timer. If you named
your timer mytimer then the start command is mytimer.start().
In this project we will use a timer to measure the time that the user presses a button. And
then we will flash a LED during that same time. So if the user presses the button for 4
seconds the LED will flash for 4 seconds after the user releases the button. The LED will
not flash during the time the button is pressed, only afterwards.
The program declarations are identical to those in the previous project, but this time we
also declare a timer called t. Note that timer must be with a capital T.
#include "mbed.h"
DigitalIn button(p20);
DigitalOut myled(LED1);
Timer t;
The next step is to declare the variable. We will use i to record how long the user pressed
the button, and we will do this in milliseconds. If we define i as an integer the maximum
value it can hold is 2,147,483,647 mS. That translates to about 36 hours. It is unlikely that
anyone would want to press the button for so long so this is a safe choice.
int i;
Timing the period that the button is pressed is actually quite easy. We will start the timer
at the beginning of the program, and as soon as the user presses the button we will reset
the timer to zero. Then we will wait for the button to be released, taking into account that
bouncing may occur. Once the button is released we immediately record the timer value
in variable i. We use a 0.3 second delay in the button loop for debaouncing. That means
12
Note that 1 second = 1,000 milliseconds = 1,000,000 microseconds.
56 57
that after the user has released the button the timer will continue to run, so we need to
correct for that. Since the time is measured in mS we need to subtract 300 mS. int i;
Perhaps you were tempted to use "while (t.read_ms()==i)". Theoretically this is of course int i;
correct. The flashing of the LED however takes a total of 1 second - 0.5 seconds on and
0.5 seconds off. So it is very likely that the timer will never be exactly equal to i at the int main
moment that the program is checking, because when that occurs flashing is still in t.star
progress. So it is almost certain that the timer will "overshoot". By using "while while
(t.read_ms()<i) " we avoid that problem. if (
By now you probably realized that the program would be much easier to read if you could
add some comments in normal English. In fact you can. Any line that starts with // is
ignored by the compiler, so you can use this to add comments.
// This is a comment.
If you need more than one line you can preceed every line with //, or you can use /* to
open a comment and */ to close it.
/* This is a comment
and this too,
and this line too */ }
}
You can even add comments following commands. }
57
58 58
The compiler will turn these lines green so you can easily spot the comments. It is
considered good programming practice to add sufficient comments so that if you see the
program years from now you still understand what it will do. In a professional
environment you should include comments so that other project members understand the
program.
It is not recommended that you add comments that explain C commands, for when you
read code you are supposed to know C. Except of course when you write a book on C
programming, like this one.
And this is the completed program including the main loop and some comments.
#include "mbed.h"
DigitalIn button(p20);
DigitalOut myled(LED1);
Timer t;
int main() {
t.start();
while (1) {
if (button) {
// the button is pressed so record the time
t.reset();
while (button) wait(0.3);
i = t.read_ms() - 300;
// the button is released so flash the LED
t.reset();
while (t.read_ms()<i) {
myled = 1;
wait(0.5);
myled = 0;
wait(0.5);
}
}
}
}
58 59
Use the schematic and picture of the breadboard to build this project. The color coding of 5. Analog s
the resistor is brown-black-orange (keep the gold or silver band on the right side when
decoding the colors). In the previous
context means 3
use of DigitalO
The mbed is eq
Vout 3.3 volts. In fa
(3.3 V)
Switch between, for ex
LPC1768 discuss a few p
p20 area on your qu
analog to digita
GND
ADC.
10k
Figure 31. Project schematic.
5.1 Variable
In this project
Figure 32. Project on a breadboard. easy way to ma
side of the varia
When the program is in the microcontroller hold the button for say 5 seconds. The LED the position of t
will remain off. Then release the button. For 5 seconds the LED will flash and then stop wiper is at the b
again. Since a single flash takes 1 second - 0.5 seconds on and 0.5 seconds off - the are turning the k
"playback" time can only be accurate to one second.
The next table s
59
60
5. Analog signals
In the previous projects we used pins and signals that were either 0 or 1, where 1 in this
context means 3.3 volts, and 0 of course 0 volts. These are called digital signals hence the
use of DigitalOut and DigitalIn in our declarations.
The mbed is equipped with a series of pins that can also read voltages other than 0 and
3.3 volts. In fact they can read - or in the case of pin 18 also write - any voltage in
between, for example 0.61 volts. These signals are called analog. In this section we will
discuss a few projects that use this technique. The analog pins are marked with an orange
area on your quick reference card - pins 15 to 20. The mechanism to convert signals from
analog to digital is called an Analog to Digital Converter, also called A/D converter or
ADC.
The next table shows the functions that you can use in relation to the AnalogIn pins.
60
61
Putting these tw
Function Description
#includ
AnalogIn() Create an AnalogIn, connected to the specified pin.
Read the input voltage, represented as a float in the range Analog
read() DigitalO
0.0 to 1.0.
Read the input voltage, represented as an unsigned short int main
read_u16()
in the range 0 to 65.535. while(1
operator float An operator shorthand for read(). my
wa
my
The first step is to select a pin to connect the pot to. We can choose any pin from 15 to
wa
20, so we will select for example 20. We will call this pin mypot. As LED we will use
}
LED1. Note the two capitals in AnalogIn.
}
#include "mbed.h"
In order to buil
shown in sectio
AnalogIn mypot(p20);
need to make th
DigitalOut myled(LED1);
Now we need to find out what the analog signal on pin mypot is. For this we use the read
function: mypot.read(). In the table you can see that read returns a value between 0 and 1,
and that it is a float. That means that 0 is equal to 0 volts, and 1 is equal to 3.3 volts. So
based on the measured value the actual voltage can be calculated:
V = read() * 3.3
Use the schema
Where V is the voltage. So if read() is for example 0.1 then the voltage is 0.1 * 3.3 = 0.33 schematic ident
volts. In this project we are not really interested in the actual voltage because all we want are shown, the o
to do is to make a flashing LED with variable speed. The range of 0 to 1 is very
convenient. If we use this value in a wait statement we get a wait period between 0 and 1
second.
while(1) {
myled = 1;
wait(mypot.read());
myled = 0;
wait(mypot.read());
}
61
62 62
#include "mbed.h"
AnalogIn mypot(p20);
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1;
wait(mypot.read());
myled = 0;
wait(mypot.read());
}
}
In order to built this project you need a breadboard, with all power sections connected as
shown in section 2.1. We will power the breadboard using the mbed itself, so you will
need to make the following connections.
Pin Connection
GND To the blue powerline of the breadboard.
Vout To the red powerline of the breadboard.
20 To the pot.
Use the schematic and picture of the breadboard to build this project. The mbed is in the
schematic identified as the LPC1768, and represented as a rectangle. Only the pins in use
are shown, the others are left out for clarification.
62 63
In the table at
"operator float;
Vout
"mypot.read()"
(3.3 V) like this "myp
program bit eas
LPC1768
10k
p20 myled = 1;
wait(mypo
GND myled = 0;
wait(mypo
In the table we
Figure 34. Variable speed flashing LED schematic. pins. So how di
in front of the m
The pins of most pots do not fit into a breadboard. Don't force them in or you will search for Anal
damage the connectors inside the breadboard. Instead solder three short pieces of wire to
the contacts. The thick part on the pot pins in the next Figure is solder, the wires are bend
down into the breadboard and thus invisible.
Compile the program and download it onto the mbed. Do remember to press the button to
transfer the program into the microcontroller. LED1 will now start flashing. The further
you turn the pot to the left the faster it will flash. If you turn the pot all the way to the left
it will flash so fast that it appears to be on all the time, just a little bit less bright.
63
64 64
In the table at the beginning of this chapter the last entry is the rather mysterious
"operator float; an operator shorthand for read()". This means that instead of using
"mypot.read()" to get the analog value you could also just refer to the name of the pin,
like this "mypot", to achieve the exact same thing. Using the shorthand makes the
program bit easier to read. Modify the flashing section of your program and test it.
myled = 1;
wait(mypot);
myled = 0;
wait(mypot);
In the table we showed you all the functions that can be used in relation to the AnalogIn
pins. So how did we know that? In the Program Workspace of the compiler click on the +
in front of the mbed library. This will show all the sub-libraries of the mbed library. Then
search for AnalogIn and click on it.
64 65
You will find a very short description of the library, and example and then a list of all
functions that you can use. The text and function descriptions are not geared towards
beginners but you will still be able to find lots of interesting information.
Note that "performing a read" is generally called an "AD conversion" where AD stands
for Analog to Digital. AD is often also spelled as A/D.
In this project we will light a LED once it gets dark. In order to do this the amount of
light must be measured, for example using an LDR - a Light Dependent Resistor. The
relationship between the quantity of light and the resistance of the LDR is unfortunately
not linear and usually looks something like this:
The next table shows some everyday situations with a rough estimate of the amount of
Lux.
Even "identical" LDRs may differ as much as 50% in their resistance. So in any case we
need some sort of calibration, of a fine-tuning pot. Good to remember: the more light the
lower the resistance.
We cannot connect the LDR directly to a pin, because the analog pins measure a voltage,
not a resistance. The solution is to connect the LDR over the ground and the wiper of the
pot. The pot now functions as "double" resistor, and thus as voltage divider. The added In theory the pr
advantage is that the pot can now be used to fine-adjust the moment at which the LED threshold light t
should be lit, so in the program we can use an arbitrary threshold value of 0.5.
#includ
Analog
65
66 66
Vout
(3.3 V)
LPC1768
10k p20
GND
LDR
If you built the project make sure to place the LDR away from the LED. The blue mbed
LEDs are very bright and when it is dark enough to light the LED the LED itself may
make it too light again so the LED is switched off again.
In theory the program is simple. Read the analog value of pin20. If that value is above the
threshold light the LED, if not turn the LED off.
#include "mbed.h"
AnalogIn myldr(p20);
66 67
The solution is to have two thresholds, one for switching the LED on, and another one for
switching it off. If these two measurements are further apart than the error in the
measurements, then switching the LED on and off will be very smooth.
i = myldr;
if (i > 0.5) myled = 1; Fig
if (i < 0.4) myled = 0;
In parallel with
The first step is to measure the analog value and store it in float i. If i is higher than 0.5 closed the resis
the LED will be switched on. But i has to be lower than 0.4 for the LED to be switch off windows opens
again. So the level has to drop 0.1 which is more than the error in the measurement. resistors are dif
switch.
Note that since the "if" statement only has a single command you do not need to use
braces. Also do remember to declare i a float. This is the completed program.
#include "mbed.h"
AnalogIn myldr(p20);
DigitalOut myled(LED3);
67
68 68
float i;
int main() {
while (1) {
i = myldr;
if (i > 0.5) myled = 1;
if (i < 0.4) myled = 0;
}
}
In this project a room with three entrance points (windows, doors) will be guarded using a
single wire. The wire runs from entry point to entry point and ends at the +3.3 volts
connection. Each entry point has a switch that is normally closed, for example a magnetic
switch as shown in the next Figure on a sliding door.
Figure 39. Sliding door with magnetic switch and parallel resistor.
In parallel with each switch a different resistor is mounted. As long as all the switches are
closed the resistance of the wire is zero. If one of the switches opens - meaning a door or
windows opens - the resistor over that switch will now be part of the wire. Because all
resistors are different simply measuring the resistance of the wire can identify the open
switch.
68 69
We will assume
10 k
other situations
if (i<0.9
// al
Figure 40. Triple voltage divider. } else a
The mbed is not capable of measuring resistance, but it can measure voltages - in fact this Note that we d
is what the A/D converter does. Therefor we use the entire single wire as one side of a command. Also
voltage divider. If in the previous Figure all switches are closed the mbed is connected The command:
directly to the +3.3 volts.
alarm1=
If switch S1 is open the mbed is connected to the ground using a 10k resistor and at the
same time to the +3.3 volts using a 33k resistor. The voltage on the mbed can be Is shorthand for
calculated using this formula:
{ alarm
10k alarm2=
Vmbedpin = 33k + 10k * 3.3 volts = 0.77 volts alarm3=
}
By the same token the voltages for the other switches can be calculated. Since 3.3 volts is
equivalent to an AD reading of 1.00 the expected measurements for each switch can be The conditions
calculated as well. smaller than 0.9
value is larger t
Switch Resistor Voltage Measurement
if (i>0.4
S1 33k 0.77 0.23
S2 22k 1.01 0.30 But the next con
is equal to or s
S3 10k 1.63 0.50
language has an
none n/a 3.30 1.00
69
70 70
The exact measurements may vary depending on the accuracy of the resistors and
possible wear in the switches. For that reason we will use ranges rather than exact
setpoints in the software.
AnalogIn myinput(p20);
DigitalOut alarm1(LED1);
DigitalOut alarm2(LED2);
DigitalOut alarm3(LED3);
We will assume that one of the switches is open if the AD reading is lower than 0.9. In all
other situations we will switch the LEDs off.
if (i<0.90) {
// alarm
} else alarm1=alarm2=alarm3=0;
Note that we do not need braces after the "else" keyword because there is only one
command. Also note the convenient way to switch all three LEDs off at the same time.
The command:
alarm1=alarm2=alarm3=0;
Is shorthand for:
{ alarm1= 0;
alarm2=0;
alarm3= 0;
}
The conditions for the first switch are easy. We already know that the AD measurement is
smaller than 0.90 - otherwise this section of the code would not be executed - so if the
value is larger than 0.4 the third switch must be open.
if (i>0.40) alarm3=1;
But the next condition is a bit more complicated. This one applies if the AD measurement
is equal to or smaller than 0.4, and at the same time larger than 0.25. Fortunately the C
language has an AND operator.
70 71
The logical AND operator is written as a double ampersand &&, and should be read as }e
"and". As you can see in the truth table the output is true only if both inputs are true. }
Using the logical AND the second switch can now be programmed. }
if ((i<=0.40)&&(i>0.25)) alarm2=1;
33 k
Note the extensive use of brackets. This is to make sure that the compiler first determines
if i<=0.40 and i>0.25 are true or false separately before it starts with the actual AND
operation. Strictly speaking this is not necessary, and you could use this instead: S1
if (i<=0.40&&i>0.25) alarm2=1;
In a program as small as this you might as well, for you can easily test if the compiler
understands you. But as your programs get bigger and bigger testing becomes ever more
complicated. In that case it is better to insert a few extra brackets to make sure, rather
than leave them out and live on hope.
if (i<=0.25) alarm1=1;
The three switc
Putting it all together results in the following program. Remember that i has to be switch is closed
declared as a float, and that we can use "i = myinput" as an abbreviation for "i = used NO - Nor
myinput.read()" have a center co
be closed when
#include "mbed.h" switches as sho
magnet is near
AnalogIn myinput(p20); detergents.
DigitalOut alarm1(LED1);
DigitalOut alarm2(LED2); The three resist
DigitalOut alarm3(LED3);
10k col
float i; 22k col
33k col
71
72 72
int main() {
while (1) {
i = myinput;
wait(0.1);
if (i<0.90) {
if (i>0.40) alarm3=1;
if ((i<=0.40)&&(i>0.25)) alarm2=1;
if (i<=0.25) alarm1=1;
} else alarm1=alarm2=alarm3=0;
}
}
33 k 22k 10 k
S1 S2 S3
Vout
(3.3 V)
p20
LPC1768
10 k
GND
The three switches need to be of the NC - Normally Closed - type. This means that the
switch is closed unless you push the button, as opposed to the other projects where we
used NO - Normally open - pushbutton switches. Most people use change switches that
have a center contact and a NO as well as a NC contact. "In the field" these switches must
be closed when the door or window is closed too. In practice most people use magnetic
switches as shown on the first Figure in this section. This switch is closed as long as the
magnet is near it. The advantage of this type of switch is that it is insensitive to dirt or
detergents.
72 73
The picture shows the project on a breadboard with the resistors very close to the 5.4 Sine gen
switches. In real life it is better to mount the resistors further away so that cutting the wire
will leave the resistor in the circuit and light the correct LED. In this project w
73
The mbed has o
Figure 42. Single wire alarm on a breadboard.
Digital to Analo
Once the program is running press any of the three switches to simulate a security breach value between 0
which will light the appropriate LED. If you press multiple switches at the same time the on the pin.
LEDs will not correspond to the switches. Of course you could change the program to
accommodate this, however if burglars enter your house through all windows at the same The next table s
time lighting the proper LEDs may not be your biggest worry.
Function
5.4 Sine generator (analog out) AnalogOu
In this project we will not read an analog signal but generate one instead.
write()
write _u16
operator=
In this project w
18 a sine shaped
by slowly light
oscilloscope so
There is a wh
important ones.
73
74
74
The nextFunction
table shows the functions that you can use in relation to the AnalogOut pin.
Description
AnalogOut() Create an AnalogOut connected to the specified pin
Function Description
Set the output voltage from 0 to 3.3 volts, specified as a
write()
AnalogOut() float in the
Create anrange 0.0 to 1.0.
AnalogOut connected to the specified pin
Set the output voltage from 0 to 3.3 volts, specified as an
write _u16() Set the output
unsigned voltage
short in the range 0from 0 to 3.3 volts, specified as a
to 65,535.
write()
float in the range 0.0 to 1.0.
operator= An operator shorthand for write()
Set the output voltage from 0 to 3.3 volts, specified as an
write _u16()
In this project we will use unsigned short
the analog pin in thea sine
to make range 0 to 65,535.
generator. This means that on pin
18 a sine shaped signal will be made. We will connect a LED to it which will then "flash"
operator=
by slowly lighting up andAnthenoperator shorthand
slowly going forWe
out again. write()
will also connect a software
oscilloscope so we can see the signal shape and verify that it is indeed a sine.
In this project
There is a we willseries
whole use the analog
of math pin toavailable;
functions make a sine generator.
the next Thisthe
table shows means
most that on pin
18 a important
sine shaped
ones.signal will be made. We will connect a LED to it which will then "flash"
by slowly lighting up and then slowly going out again. We will also connect a software
oscilloscope so we can see the signal shape and verify that it is indeed a sine.
74
There is a whole series of math functions available; the next table shows the most
important ones.
75
74
The angle of the sin function has to be in radians (rad). A full circle of 360 degrees is 6.28
rad.14 If we move around the circle in steps of 0.01 we get 628 sine values which should
be enough for a smooth result.
Unfortunately sine values are in the range -1 to +1, while the D/A converter expects a
signal between 0 and 1. We can convert it to the correct range by dividing by two - which In the schemati
results in a range of -0.5 to +0.5 - and then add 0.5. that the arrow a
In order to actually see something we will add a small delay of 0.01 second. That means
that the total sine wave will take 6.28 seconds.
#include "mbed.h"
AnalogOut signal(p18);
float i;
int main() {
while (1) {
for (i=0; i<6.28; i+=0.01) {
signal = sin(i)/2 + 0.5;
wait(0.01);
}
}
}
13
This basically means that the number will be rounded to the nearest integer that is no less than
the original. So 2.7 will become 3, but beware that -2.7 will become -2 and not -3 as you might
expect.
14
$FWXDOO\GHJUHHVLVHTXDOWRʌUDGZKLFKLVDERXWUDG
75
76 76
The built in LEDs are not connected to pin 18, so we need to connect an external LED. A
LED has a plus and a minus side - formally known as anode and cathode. If you look
closely at the LED you will see that the metal inside the LED is larger on one side. This is
the minus side and it needs to be connected to the ground. Usually the wire is a bit shorter
on that side. Of course this doesn't apply to the tiny LEDs that are soldered on the mbed.
In the schematic the symbol of a LED looks like an arrow. An easy rule to remember is
that the arrow always points to the negative side.
LPC1768
p18 GND
220
LED
76 77
The 220 ohm resistor is used to protect the LED against a too high current. This is called
a current limiting resistor. Most normal LEDs require a current of 10 to 15 mA to light. 15 [î
Such a LED has a voltage drop of about 0.7 volts. That means that the resistor carries 3.3 10
- 0.7 = 2.6 volts.
mbed pin
220
3.3 - 0.7 = 2.6 volts
3.3 volts
LED
0.7 volts
0
GND
-5
Using Ohm's law you can calculate that the current is 12 mA which is within the target
range.16
77
78 78
10
-5
-20 -10 0 10 20
Dt=12,21 ms t (ms)
You can visualize the signal using software oscilloscope WinOscillo. For that you need to
use the special hardware described in section 2.2. Start the WinOscillo program. Use the
Sound Mixer of your PC to enable the microphone input on your PC, disable noise
suppression and other sound enhancements and crank the volume up to maximum. Turn
the variable resistor on the hardware unit all the way to zero, and then plug the unit into
the microphone plug of your PC. Important: connect the ground wire to the ground of the
breadboard and the live wire to LED. Slowly turn up the variable resistor until you see the
signal on then screen. Use the "X" - vertical stretch - and "t" - horizontal stretch - sliders
to make the picture fit nicely.
Note that the little spikes in the Figure are caused by the mbed power controller.
Unfortunately the signal doesn't look like a sine at all. The reason for this is that the LED
has a large influence on the signal. When it is off there is no current running through it so
the D/A converter is unloaded. When the LED lights brighter and brighter it consumes
more power so the load on the D/A converter is going up. This difference in load will
influence the voltage of the converter and quite frankly we do not give it enough time to
adjust. In any case D/A converters work best when the load is very low. We can test that
by removing the LED. The load is now zero and the sine shape is perfect, as you can see
in the next Figure.
78 79
6. USB com
[î WinOscillo v0.88
10
It is quite uncom
makes USB com
install a driver
minute or two.
that project befo
5
6.1 Echo
Your mbed is c
0
been used to co
be used for use
the PC or the o
need administra
know what this
-5
privileges.
-20 -10 0 10 20
Dt=12,04 ms t (ms) Connect the mb
Figure 49. Result with the D/A convertor is unloaded. Window. On so
close it before y
Using the left and right mouse buttons you can place vertical measuring lines in the
graph. It is best to pause the display first so you don't need to "chase" the graph when it
moves a bit. If you do not see any vertical cursor lines press Ctrl-V to display them. See
section 2.2 for more short keys and functions. In the previous Figure we measured a total
sine time of 12.04 mS using the vertical measuring lines. For a complete sine wave the
program had to calculate the sine, and convert it to an analog signal, 628 times. That
means that each loop took just 19 uS. Impressively fast!
79
80
6. USB communication to a PC
It is quite uncommon to discuss USB communication in a beginner's book. But the mbed
makes USB communications so easy that it would be a shame to skip it. You do need to
install a driver on your PC and perhaps a terminal program but that will only take a
minute or two. Driver installation is discussed in the Echo project so make sure you do
that project before any other USB project.
6.1 Echo
Your mbed is connected to the PC using a USB connection. So far this connection has
been used to copy programs to and from the PC. That same connection can however also
be used for user communications. That means that you can send data from the mbed to
the PC or the other way around. In order to do that you first need to install a driver. You
need administrator privileges or an administrator account to install drivers. If you don't
know what this is, but you can install software on your PC, then you already have these
privileges.
Connect the mbed to the PC but do not open the mbed drive in the Microsoft Explorer
Window. On some PCs this window will open automatically, in which case you need to
close it before you continue.
80
81
The driver is part of the download package that you downloaded from Each serial port
www.boekinfo.tk.17 The file you are looking for is called "mbedWinSerial_16466.exe" in number is diffe
the 6.1 directory. Run this file, and click on "Install" when a small window appears. You number of this n
may receive a rather threatening warning regarding the driver being unauthorized. This is
correct so when this happens click on OK to continue. You may get the warning multiple
mbe
times.
When the installation has completed a new serial port has been added to your PC. Not a On my PC the
real one of course but a virtual one. To all programs on your PC this virtual port looks when you see p
like a real hardware port, but it fact it goes directly to the mbed. For that reason the port
only exists when the mbed is plugged in. All Windows v
use this program
a Windows ver
version called H
compared to Hy
upgrading even
file in section
installation is c
cannot find the
c:\progr
V
Bi
D
Pa
St
Tr
Figure 51. The virtual mbed port has been assigned number 8 (Win XP Dutch version).
18
On Windows X
Device Manager.
by an enter.
19
If you upgra
17
Alternatively you can download it from the mbed website. HyperTrm.exe to
81
82 82
Each serial port on your PC has a number, and so does this virtual port. Unfortunately this
number is different on each PC. Open the Device Manager on your PC to see what the
number of this new port is (with the mbed plugged in), and make a note of this number. 18
On my PC the virtual port number is 8. Yours will most likely differ, so from now on
when you see port 8 in this book replace that by the port that your PC has assigned.
All Windows version prior to Vista have a terminal program called HyperTerm. We will
use this program to communicate to the mbed using the new USB connection. If you have
a Windows version that doesn't have HyperTerm you need to install a slightly extended
version called HyperTerminal Private Edition 6.3.19 This version has a few extra options
compared to HyperTerm, such as clear screen and clear backscroll, so you might consider
upgrading even if you do have HyperTerm. You will find this program in the download
file in section 6.1. Double click on it and follow the on-screen instructions. Once
installation is completed the new version will have replaced your old version. If you
cannot find the new version the most likely location is:
c:\program files\windowsnt\hyperterminal
Start the HyperTerminal program. A window will pop-up asking for the name for this
new connection. Enter mbed as name, select an icon and click on the "OK" button. Ignore
the first three fields. In the "Connect using" box select the COM number of the virtual
COM port. In my case 8 but you need to enter your own port number, then click on "OK".
In the next window make the following settings:
Variable Setting
Bits per second 9600
Databits 8
Parity None
Stopbits 1
Transportcontrol None
18
On Windows XP you can follow this route: Start - Configuration Screen - System - Hardware -
Device Manager. Alternatively you can do: Start - Execute and then type in devmgmt.msc followed
by an enter.
19
If you upgraded from WinXP I am told that you can copy the files HyperTrm.dll and
HyperTrm.exe to your new computer and the will still work.
82 83
Go to the mbed website, open the Compiler window and enter this program:
Compile and run this program. The only hardware you need is the mbed itself. The
message "Echoes anything you type" will appear in your terminal screen. If you press a
key on the keyboard of your PC it will be send over USB to the mbed, which will echo it
20
Use printable k
83
84 84
right back, and then it will be displayed on the terminal screen. 20 You can tell that this is
indeed happening because the standby LED on the mbed flashes each time that you press
a key to indicate that activity is taking place on the USB connection.
So how does this program work? First we need to create a virtual serial port on the mbed,
in this case we will call this port pc.
Once that is taken care of we now have the following commands at our disposal.
20
Use printable keys such as letters and numbers, and not keys like Ctrl or Alt.
84 85
85
86 86
Since the backslash \ is a special character you may wonder how to print one to the
screen. The solution is to use two of them in a row, like this \\. The first is the special
character but the second will be printed.
Now all we need to do is wait for a character, fetch it and write it. We can get a character
using getc() and write it using putc().
while(1) {
i = pc.getc();
pc.putc(i);
}
Since we want to send what we receive we might as well combine the two commands and
save ourselves the "trouble" of declaring i (as an int).
while(1) {
pc.putc(pc.getc());
}
When you are done with this project and close HyperTerminal it will ask if you want to
save your settings. That way you do not have to enter the settings each time you want to
use the mbed. I have saved it on my mbed so I always carry it with me.
It is important to realize that the virtual COM port only exists when the mbed is plugged
in. If you start HyperTerminal before plugging in the mbed your will get an error message
stating that HyperTerminal is "Unable to open the COM port". If that happens click on
"OK", plug in the mbed, wait for the dong-ding sound, wait five more seconds, and then
click on the little yellow telephone to "pick it up", or rather: open, the connection. If
needed press the reset button on the mbed to restart the program and send the "Echoes
anything you type" message to the PC again.
In this project we will display a counter in HyperTerminal. At first glance that seems
easy, we could for example to something like this:
pc.putc(i);
i++;
If you try this - and I suggest you actually do - you will find that part of the time nothing
happens, and the rest of the time you get weird characters.
86 87
Counter
Now here is a n
each other, beca
Counter will alw
point the count
previous one e.
visible. If for ex
was not want w
spaces will era
Figure 54. Weird characters.
this.
#includ
The reason is that serial communications uses a coding system for letters and numbers.
This coding system is called ASCII. 22 That means that when the mbed sends a zero then
Serial p
HyperTerminal treats this as an ASCII code and prints the character that has ASCII code
0. Now the first 31 ASCII codes are control codes and they are unprintable, so nothing
int i=0;
happens. ASCII code 32 is a space and 33 an exclamation mark. In the previous Figure
you can see that the list does indeed start with a space followed by an exclamation mark.
int main
So instead of printing a series of numbers we have printed the corresponding ASCII
while
codes.
pc
i++
The easiest way to print numbers - and text for that matter - is to use the "printf" function.
}
In the previous project we have already seen how printf can be used to print text and to
}
control the cursor location. Printing numbers is just as easy.
We will use the
pc.printf("Counter %d",i);
and run it. On
project.
This command prints the word Counter followed by a space, and followed by %d. Now
%d is not what is actually printed. It merely means "print an integer at this location".
Which integer that is, is shown outside the quotation marks, so in this case i. So if i is 55
then this command would print:
Counter 55
22
In the appendix you will find an ASCII table that lists all codes with their meaning.
87
88 88
Counter 55 units.
Now here is a nice trick. If we preceed the text with \r then the texts will be printed over
each other, because \r will make sure printing starts at the beginning of the line. That way
Counter will always remain in the same place, followed by a changing number. At some
point the counter will restart at zero, and that means that the number is smaller than the
previous one e.g. consumes less space. That means part of the old number will remain
visible. If for example you print 5 over the number 100 what you will see is 500 and that
was not want we meant to see. So we will follow %d with a couple of spaces so that the
spaces will erase any residual digits on the screen. That means the program looks like
this.
#include "mbed.h"
int i=0;
int main() {
while (1) {
pc.printf("\rCounter %d ",i);
i++;
}
}
We will use the hardware of the previous project - just the mbed itself. Enter the program
and run it. On the PC run HyperTerminal with the settings provided in the previous
project.
88 89
This looks very nice, and the best thing is that it didn't require any programming on the the hexadecima
PC side, just a terminal program! We used %d as a format specifier in the printf extra ones are r
command, but that is just for integers. The next table shows some of the other options that counting in Hex
you can use. So if you want to print a number make sure you use the correct format
specifier. 0,1,2,3,
6.3 Voltmeter
In section 6.1 we have seen a few cursor control commands. In this section we will add a
few new ones. These are VT52 commands; hence the VT52 setting you made in
HyperTerminal when you installed it. The next table shows these commands together
with the ones that we have discussed previously.
89
90 90
the hexadecimal system has 16 digits, or symbols. Since only 10 "real" numbers exist the
extra ones are represented by the letters A to F where A is 10 and F is 15 in decimal. So
counting in Hex goes like this:
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
It is not all that complicated to count and calculate in Hex, but for the projects in this
book we will simply remember that Hex means 16 digits from 0 to F, and we will use the
calculator that comes with Windows to convert numbers from Hex to decimal and the
other way around. Note that in the VT52 commands Hex numbers are prefixed with a x.
So 12 is the decimal number 12, and x12 is the Hex number 12 - which is 18 in decimal.
Start the Windows calculator, and put it in scientific mode using the View menu. If you
use Windows 7 you need to put the calculator in programmer mode. Click on the Dec
radiobutton, and enter the number 18. Then click on the Hex radiobutton. The number
you just entered is automatically converted to Hex, and the display now shows 12.
When you selected the Hex radiobutton the 5 letter keys became active, because these are
valid digits in Hex. Clear the display and enter the number 1B. Then select the Dec
radiobutton. Instantly the number 1B is converted to decimal and the display now shows
27. We will be using this functionality of the Windows calculator quite often.
90 91
If we use the \x1B\x48 command - cursor home - followed by the \x1B\x4A command -
clear screen from cursor - we effectively send the cursor home and clear the screen. If we
start our program with this command we can be certain that the HyperTerminal screen is
empty and the cursor is at the home position.
pc.printf("\x1B\x48\x1B\x4A");
So if we follow this command by one that actually prints text we are certain where the
text will be.
This means: go down two lines, go to the beginning of the line, print some text and then Float
the float. We know that a float has six digits accuracy so that means that this command Print
will print the measurement with six decimal places, for example 0.253618. There is Print
Print
nothing wrong with that, but it looks a bit silly because it suggests an accuracy in the
Print
measurement that doesn't exist. It would be better if we had just 2 decimal places instead
of 6, so like this 0.23 - one digit before the decimal point and two behind it.
Just for fun we
Fortunately this is possible. Between the % sign and the "f" we can enter the total sure the cursor
minimal length of the field, then a point, and then the number of digits behind the decimal we always start
point. The next figure shows a graphical representation. Be ware that the 6 in this Figure same location. W
does not represent the number of digits before the decimal point, but the total minimal
length of the field, e.g. the digits including the decimal point. while (1
pc
i=m
pc
pc
wa
}
91
92 92
%6.2f
2
123.45
6
So for example %4.2f would print something like this: 0.23. You can read %4.2f as "print
a float to a field with a minimum length of four with one decimal point and two
decimals". The decimal point and the two decimals take up three positions. Since we just
said that the field length is 4 that leaves just one digit before the decimal point.
Remember that the first number is not the number of digits before the decimal point but
the total minimal length of the field. So what happens if you make a mistake and make
the field length too small? Nothing. It is the minimum length so the program will still
print the full number. If you make the field length too long the number will be printed
with leading spaces. This is very convenient because it allows you to print numbers of
varying length neatly in a column. Some examples:
Float 1234.567891
Printed using %4.2f 1234.56
Printed using %7.2f 1234.56
Printed using %9.2f 1234.56
Printed using %7.4f 1234.5678
Just for fun we will also print the actual AD measurement. In the main loop we will make
sure the cursor is at the home position, and then print the two texts and numbers. Since
we always start at home we are certain that two lines down will also always end up at the
same location. Without the home command we would simply fill the screen.
while (1) {
pc.printf("\x1B\x48");
i=mypot.read();
pc.printf("\n\n\rMeasurement %4.2f ",i);
pc.printf("\n\n\rVoltage %4.2f volt ",i*3.3);
wait(0.5);
}
92 93
Putting it all together gives us this program. In the main program we will include a small
delay of 0.5 seconds to give the PC time to display the text in HyperTerminal.
#include "mbed.h"
float i=0;
int main() {
pc.printf("\x1B\x48\x1B\x4A");
pc.printf(" ---===[ Voltmeter ]===---");
while (1) {
pc.printf("\x1B\x48");
i=mypot.read();
pc.printf("\n\n\rMeasurement %4.2f ",i);
pc.printf("\n\n\rVoltage %4.2f volt ",i*3.3);
Compile the pr
wait(0.5);
settings you sav
}
The restart will
}
Otherwise this c
Use the schematic and picture of the breadboard to build this project. Only the pins in use
are shown, the others are left out for clarification. The pot in this project is temporary, see
the remarks further down in the text.
Vout
(3.3 V)
LPC1768
10k
p20
GND
93
94 94
Compile the program and download it onto the mbed. Start HyperTerminal using the
settings you saved previously and press the button on the mbed to restart the program.
The restart will cause the header of the page to be printed and the screen to be cleared.
Otherwise this command might get lost during the USB startup period.
If you turn the pot you will see the values change on the screen. You may notice that the
measurements tend to vary slightly even if you do not touch the variable resistor. This is
94 95
the inaccuracy in the AD measurement, a normal phenomena. Now you understand why declared a char,
printing the float with 6 decimal places would serve no purpose. That means tha
executed foreve
The pot is just for testing. If you want to use this device as a voltmeter you have to
remove the pot and attach a wire to pin 20. To use it connect the ground to the ground Actually inserti
object you want to measure and the wire to the point that you want to measure the voltage that you can us
of. in. If your prog
a LED in diffe
Beware: never attempt to measure voltages higher than 3.3 volt, and do not mix ground program is stuc
and plus wire. If you do you will seriously damage the mbed! LED on stateme
of the program
6.4 In-circuit debugging DigitalO
Debugging means finding errors in your program. We are not talking about syntax errors char i;
- the compiler will find those for you - but logical errors. Let's take a look at the
following program. Can you spot the logical error? Can you fill in the next table? int main
while
Flashing LED time (in seconds) fo
LED on
LED off Perhaps once y
use the next tec
use is i so let's a
Flashing LED program with for loop:
bold. Note the s
#include "mbed.h"
#includ
DigitalOut myled(LED1);
DigitalO
Serial p
char i;
char i;
int main() {
while(1) {
int main
for (i=0;i<260;i++) wait(0.1);
while
myled = 1;
for
wait(0.2);
myled = 0;
}
}
}
my
Since the for loop is executed 260 times the LED will go on after 260 * 0.1 seconds = 26
seconds. And then it will go off again after 0.2 seconds. Right? Well, wrong. Variable i is 25
You can find th
95
96 96
declared a char, and a char is a variable in the range 0 to 255 as discussed in section 4.3. 25
That means that i will never be larger than 255 - never mind 260 - so the for loop will be
executed forever and the LED will never be on.
Actually inserting a LED on statement in your program is the first debugging technique
that you can use. The mbed makes this very easy for you because it has four LEDs build
in. If your program isn't working the way you expect it to then insert statements that light
a LED in different locations. Then run the program. You can tell where - and if - the
program is stuck by checking which LEDs are on and which are not. Because we have a
LED on statement in this program we immediately know that the error must be in the part
of the program before this statement, so in this part:
DigitalOut myled(LED1);
char i;
int main() {
while(1) {
for (i=0;i<260;i++) wait(0.1);
Perhaps once you know this you can spot the error right away. But if you don't we will
use the next technique: printing variables to the PC. In this program the only variable in
use is i so let's add a few lines to the program which will print i. The new lines are printed
bold. Note the space just before %d otherwise the numbers are printed against each other.
#include "mbed.h"
DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
char i;
int main() {
while (1) {
for (i=0;i<260;i++) {
pc.printf(" %d",i);
wait(0.1);
}
myled = 1;
25
You can find this information also in the appendix, or using the index.
96 97
wait(0.2); while
myled = 0; for
}
}
The next Figure shows the result in HyperTerminal. It is immediately obvious that i }
increases to 255 and then restarts at zero. Since the number 255 is not used in our my
program the error must be that i is declared too small. And indeed if you change "char i;" wa
to "int i;" the LED will flash as expected. my
}
}
Technique
In this program the numbers in HyperTerminal appear rather quickly. This is not a
problem because we were not interested in each separate number, just the general
overview. But let's assume that you want to examine each number carefully before the
next one is printed. This may happen for example when you print a series of different
variables and need to evaluate if these are correct.
Print varia
We can make the program stop and wait for a key to be pressed - on the keyboard of the without pa
PC - by using the getc statement. In the next program the added line is printed bold.
#include "mbed.h"
DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
char i;
int main() {
97
98 98
while (1) {
for (i=0;i<260;i++) {
printf(" %d",i);
pc.getc();
wait(0.1);
}
myled = 1;
wait(0.2);
myled = 0;
}
}
After each number is printed the program will wait for you to press any key. Note that we
do not tell the program what to do with the information it received from the keyboard. We
didn't even assign it to a variable.
Since you will need debugging skills quite often a short summary.
98 99
7. Motors a
Technique When to use In this chapter
To be used when you want to evaluate associated with
multiple variables and you want to know if highly recomm
the relationship between these variables is information.
correct. For example that one is always
The same, but with a pause. twice the other. Also very convenient for 7.1 An electr
situations where specific events need to
take place at specific variable values. This
way you can easily see if that event is In this project w
indeed taking place. small electric m
supply voltage a
To be used when you want to simulate
The same but with processing of
certain conditions manually. This
the keyboard feedback (not
technique will be discussed in part two of Property
discussed).
this series.
Voltage (v
Current, fr
Current, st
Regardless of
problems.
1. The m
2. The m
3. The c
We can solve a
chip manufactu
drive a single sm
26
Motor data acc
with permission.
27
If this informa
the motor so it ca
can't cool itself so
99
100
In this project we use a 9 volts Lego motor type 71427, but in principle you can use any
small electric motor. If your motor is different however you may need to use a different
supply voltage and possibly a different driver IC.
Regardless of the motor that you use, you will have at least one of the following
problems.
1. The motor requires a higher voltage than the 3.3 volts that the mbed delivers.
2. The motor draws a higher current than the mbed can deliver.
3. The coil in the motor causes voltage spikes than can damage a microcontroller.
The Lego motor for examples runs off 9 volts, and uses about 3.5 mA free running (360
rpm) up to 360 mA stalled (6 Ncm torque) This is way over the 3.3 volts and 40 mA that
a digital pin of the mbed can supply. And even if this would match there is still problem
three to take care of.
We can solve all three problems at the same time by using a TC4427A dual mosfet driver
chip manufactured by Microchip. This chip is designed to drive two mosfets but it will
drive a single small motor just as well.
26
Motor data according to measurements by Philippe (Philo) Hurbain www.philohome.com, used
with permission.
27
If this information is not in the datasheet you can easily measure it yourself. Pinch the axle of
the motor so it can't run and measure the current consumption using a multimeter. A stalled motor
can't cool itself so do this quickly otherwise you can permanently damage the motor.
100
101
The table also shows some data for the MAX4420 single mosfet driver IC in case the int main
TC4427A isn't powerful enough for your particular motor. Note that this IC has a while
different pin configuration, and since it is a single driver you will need two of them. mo
mo
The TC4427A is powerful enough for our Lego motor. The reverse current is the my
protection against voltage spikes. my
wa
mo
mo
my
my
wa
}
}
In the software we will make the motor run forward for 1 second and then backward for 1
second. That means we first make pin "in A" on the driver IC high and pin "in B" low.
Then we wait one second and reverse both pins. We select pins 19 and 20 because they
are close to the driver IC on the breadboard. Two LEDs have been added to visually
indicate the direction of the motor.
101
102 102
#include "mbed.h"
DigitalOut motor1(p19);
DigitalOut motor2(p20);
DigitalOut myled1(LED1);
DigitalOut myled2(LED2);
int main() {
while (1) {
motor1=1;
motor2=0;
myled1=1;
myled2=0;
wait(1);
motor1=0;
motor2=1;
myled1=0;
myled2=1;
wait(1);
}
}
For this project you need a stabilized 9 volts power supply. If you don't have one you will
find instructions on how to build one at the end of this project. We will use this power
supply to power the motor and the mbed. This way you will not need a USB connection
to run the project. Note that you can use this same technique to run any of the other
projects in this book without a USB cable. Except of course the ones that actually use
USB communications.
102 103
Pay close attention to the schematic of this project, and the picture of this project on the
breadboard. Make sure to connect the 9 volts wire to pin Vin and the driver IC only, and
make sure the ground wire is connected to the ground of the mbed.
A small 0.1 uF capacitor is mounted over the motor wires to prevent interference.
103
104 104
LPC1768
Vin + 9V
4 2
3 TC4427 6
5 7
0.1 uF
motor
In the next Figure the 9 volts power wires come in from the left side. The ground wire is
connected to the breadboard powerrail. The +9 volts wire is connected to the mbed and to
the TC4427A mosfet driver IC. The mbed Vout pin is connected to the breadboard
powerrail but not used in this project.
104 105
Of course you
When USB is connected but external power is not switched on the Vin pin carries about multimeter to s
4.5 volts from the USB connection that may be enough to make your motor run or jitter. used for all the
This is not a problem but it is perhaps better to connect the external power and switch it
on, before you connect the mbed to the USB cable.
7.2 Motor co
In order to use this project you don't need the USB cable - other than for downloading the In the previous
source - because the project is powered by the external power supply. speed. The eas
Unfortunately t
For the 9 volts power you are strongly discouraged to use a Lego battery block. The at all, and whe
switch on the battery block is reversible meaning it can reverse the polarity. This may voltage usually
seriously damage the mbed. Use a stabilized power supply of 9 volts instead.
The solution is
If you don't own one you can build the schematic in the next Figure. This power supply and simply swi
expects 15 to 24 volts AC - or 15 to 32 volts DC - transformer to be connected to the faster the moto
wires labeled "in". The transformer can be a simple wall wart type. 28 The input is rectified smooth. We kee
so the polarity is irrelevant. The transformer should also be capable of delivering enough rather the width
current. How much "enough" is depends on your project, but 500 mA goes a long way. or PWM for sho
This project for example draws less than 200 mA and that includes the motor and the
mbed. It is recommended to mount the 7809 on a heatsink of say 9 cm2 - about 1.5 inch2.
It might be convenient to mount the UA7809 in a plug so you can change it for another
1
type.29 In projects 7.3 and 7.4 for example you could us an UA7806 and in 8.2 optionally
an 7805.
UA 7809
9v 3 1
2 in 1
1000 uF/
35 v
0.1 uF 1
in 2
0
4 x 1N4007
105
106 106
Of course you can also build a variable voltage power supply but then you will need a
multimeter to set it to the correct voltage. See the appendix for an example that has been
used for all the projects in this book.
The solution is to keep the voltage constant on 9 volts - preventing any startup problems -
and simply switch the power on and off quickly. The longer you leave the power on the
faster the motor will spin. If you do that quickly enough the motor runs amazingly
smooth. We keep the frequency of the on and off pulses the same, but vary the length - or
rather the width - of the pulses. This technique is therefor called Pulse Width Modulation,
or PWM for short.
10%
duty cycle
50%
period
100%
The relative width of the pulse is called "duty cycle", because this is the moment where
the motor can actually deliver duty - or power. The distance between the pulses is called
the "period". In the previous Figure you see an example of three different duty cycles. In
the top graph the duty cycle is 10%, which means that 10% of the period the power is
actually on. In the middle graph 50% and in the bottom graph 100%. Of course the latter
means that the power is continuously on.
106 107
The previous ta
Of course pulse
pulse width or p
you did not set.
#include
DigitalO
AnalogI
PwmOu
If the datasheet
Command Description can do it try diff
PwmOut Create a PwmOut connected to the specified pin. if the motor ma
write Set the output duty-cycle, specified as a fraction30 (float). motor moves ro
which is in fact
Return the current output duty-cycle setting, measured as a
read
fraction (float).
period Set the PWM period, specified in seconds (float).
period_ms Set the PWM period, specified in milliseconds (int).
period_us Set the PWM period, specified in microseconds (int).
pulsewidth Set the PWM pulsewidth, specified in seconds (float). Then all we nee
cycle for the PW
pulsewidth_ms Set the PWM pulsewidth, specified in milliseconds (int). "motor =" is sh
pulsewidth_us Set the PWM pulsewidth, specified in microseconds (int). command would
operator = An operator shorthand for write().
motor0
operator float() An operator shorthand for read().
motor.p
while (1
moto
30
A fraction means that for example 35% is represented as 0.35. }
107
108
The previous table shows the functions that you can use in relation to the PwmOut pins.
Of course pulse width, duty cycle and period are closely related. In general you either set
pulse width or period but not both. You then use the duty cycle to control the variable that
you did not set. In this project we will set the period.
The first steps in our program are to define the motor pins (one digital and one PWM) and
an analog pin so we can control the speed using a variable resistor. Note PwmOut is case
sensitive.
#include "mbed.h"
DigitalOut motor0(p19);
AnalogIn mypot(p20);
PwmOut motor(p21);
The next step is to make the digital motor contact low, and set the period. What the period
should be is a difficult matter. Sometimes the datasheet of the motor that you use contains
a variable like "PWM frequency". In that case you can calculate the period using this
formula:
If the datasheet contains no information, or you do not even have a datasheet then all you
can do it try different periods until you find one that works. In general you could say that
if the motor makes a high pitched almost whistling noise the period is too short. If the
motor moves rough the period is too long. For the Lego motor the ideal period is 90 uS,
which is in fact rather short.
Then all we need to do is read the position of the variable resistor and use that as a duty
cycle for the PWM pin. For that we can simply say "motor = mypot.read();" because
"motor =" is shorthand for "motor.write()". If we do not want to use the shorthand the
command would be "motor.write(mypot.read());".
motor0 = 0;
motor.period_us(90);
while (1) {
motor = mypot.read();
}
109
109
Putting this all together results in this program. In the next Figu
connected to th
#include "mbed.h" the TC4427A
powerrail and u
DigitalOut motor0(p19);
AnalogIn mypot(p20);
PwmOut motor(p21);
int main() {
motor0 = 0;
motor.period_us(90);
while (1) {
motor = mypot.read();
}
}
Pay close attention to the schematic of this project, and the picture of this project on the
breadboard. Make sure to connect the 9 volts wire to pin Vin and the driver IC only, and
make sure the ground wire is connected to the ground of the mbed.
p20 + 9V
percentage - an
range is 0 to 10
GND p19 p21 you need to wr
as a prefix for a
4 2
3 TC4427 6
#includ
5 7 DigitalO
Analog
0.1 uF PwmOu
Serial p
109
110 110
In the next Figure the 9 volts power wires come in from the left side. The ground wire is
connected to the breadboard powerrail. The +9 volts wire is connected to the mbed and to
the TC4427A mosfet driver IC. The mbed Vout pin is connected to the breadboard
powerrail and used by the variable resistor.
When you run this program you will find that there is a minimum duty cycle for your
motor. Below that minimum nothing happens. If you want to know what that minimum
value is you can send the duty cycle to the PC and display it in HyperTerminal. This takes
a few extra lines plus the use of a variable i. Since the duty cycle is strictly speaking a
percentage - and in this program a fraction - the measurement is multiplied by 100 so the
range is 0 to 100, displayed with one decimal. Please note that in order to print a % sign
you need to write two of them in the printf() statement, because a single one is regarded
as a prefix for a variable.
#include "mbed.h"
DigitalOut motor0(p19);
AnalogIn mypot(p20);
PwmOut motor(p21);
Serial pc(USBTX, USBRX);
int main() {
float i;
motor0 = 0;
motor.period_us(90);
pc.printf("\x1B\x48\x1B\x4A");
110 111
The next Figure shows that the Lego motor has a minimum duty cycle of 2.1%. You
could modify your program so that it will only send values above the minimum to the 7.3 Servomo
motor using a simple if-then statement. We will leave that as an exercise for you. In the previous
this project we
servomotor is t
angle and then
a circle.31 Serv
aviation and in
lever rather than
Meanwhile we have another issue to solve. Let's make the motor run in the other direction
by changing " motor0 = 0;" to " motor0 = 1;". Try this and see what happens before you
continue reading.
When you switch the direction of the motor you also switch the way the variable resistor
works. That is because the PWM pin now needs to be reversed as well. At first it was the The angle that
positive part of the period ran the motor, but now it is the negative part. You can solve The longer the p
that by using one minus the variable resistor reading as duty cycle. once and the se
the servo will "
#include "mbed.h"
DigitalOut motor0(p19); 31
Since a servo m
AnalogIn mypot(p20); servo so that it c
PwmOut motor(p21); positioning syste
discuss that in thi
111
112 112
int main() {
motor0 = 1;
motor.period_us(90);
while (1) {
motor = 1- mypot.read();
}
}
7.3 Servomotor
In the previous project we used PWM to control the speed of a regular electric motor. In
this project we use a servomotor. The difference between a regular motor and a
servomotor is that a regular motor spins around, while a servo motor turn to a specific
angle and then stays there. In fact servo's can normally only rotate over 180 degrees, half
a circle.31 Servos are used for positioning things, particularly in the field of robotics,
aviation and industrial machinery. For that reason servos are usually equipped with a
lever rather than a wheel.
The angle that a servo will assume is based on the length of a pulse on its control wire.
The longer the pulse the further it will turn. In theory you only have to give that pulse just
once and the servo will remain in that position. But if you keep on giving that same pulse
the servo will "resist" being moved away from that position. So if you want the servo to
31
Since a servo moves its axle a specified angle when given a pulse many hobbyists modify their
servo so that it can turn 360 degrees, and use it to drive a robot. This makes a dead reckoning
positioning system a bit more accurate. This will - obviously - void your warranty so we will not
discuss that in this book.
112 113
firmly hold something in a certain position - and what would be the point of a servo if moto
you didn't - than it is recommended to keep feeding it pulses. while
}
By now you probably guessed that PWM would be an ideal mechanism to provide such
pulses, and you are correct. The frequency of the pulses - how often we give one - is set For our particu
by the PWM period. For a normal servo 20 mS is a common value - a frequency of 50 degree angle ch
Hz. The length of the pulses, and thus the rotation angle of the servo axle, is set by the cycle the lever
duty cycle. this time check
duty cy
Angle
0
Figure 73. Section of the Hitec HS-422 datasheet. 45
90
First let's consult the datasheet of the servomotor, in our case the Hitec HS-422 Deluxe.
The clockwise pulse is listed as 1500 to 1900 uS - 1.5 to 1.9 mS. This is the pulse length 13
to get the lever in the 90 degrees position. That is a rather wide range so the first step is to 18
determine what the exact value is for our unit. Build the hardware at the end of this
project, but do not enter any program just yet. Since your resu
own results. Ba
A normal period for a servomotor is 20 mS. That means that to travel 90 degrees the duty the positions in
cycle needs to be between 1.5 mS/20 mS = 0.075 and 1.9 mS/20 mS = 0.095. Enter the longer because
following program, and see what value you need to enter in the line "motor = 0.075;" to
get the lever in the 90 degree position. A servo is rather strong so make sure it can move #includ
freely.
PwmOu
#include "mbed.h"
int main
PwmOut motor(p21); moto
while
int main() { mo
motor.period_ms(20); wa
113
114 114
motor = 0.075;
while (1);
}
For our particular unit 0.072 yields the best result. The datasheet also lists that for a 45
degree angle change 400 uS is required. That means that if we add 800 uS to the duty
cycle the lever should be at the 180 degree position. Run the previous program again but
this time check to see which value is needed exactly to get to that position.
For our particular unit 0.118 yielded the best result. Based on this we can calculate the
required duty cycles for the other angles in 45 degree increments.
The results are shown in then next table. The data printed bold are measured, the others
are calculated.
Since your results may vary an empty column has been added where you can enter your
own results. Based on this table the next program is made. It will cycle the servo through
the positions in the table and hold that position for one second. The first delay is a bit
longer because the servo needs to rotate back to the starting position.
#include "mbed.h"
PwmOut motor(p21);
int main() {
motor.period_ms(20);
while (1) {
motor = 0.026;
wait(1.5);
114 115
motor = 0.049;
wait(1);
motor = 0.072;
wait(1);
motor = 0.095;
wait(1);
motor = 0.118;
wait(1);
}
}
The datasheets lists a maximum current of 150 mA, but states that this is "no load
running", so when the servo is used to move anything the current will be higher. Since
this current will not run through the mbed this is not a problem. However the servo needs
4.5 to 6 volts. Fortunately however the control of the servo regards 3.3 volts still as
"high" so we can connect it directly to the mbed. The control consumes less than 1 mA so
that is ok too (the mbed can deliver 40 mA).
A servo is rath
Pay close attention to the schematic of this project, and the picture of this project on the supply on, and t
breadboard. Make sure to connect the 6 volts wire to pin Vin and the servo only, and make
sure the ground wire is connected to the ground of the mbed. If you do not have a 6 volts [î
power supply you can use the power supply shown in chapter 7.1 and use a UA7806 30
instead of the UA7809. Of course you can also built a variable voltage power supply but
then you will need a multimeter to set it to the correct voltage. See the appendix for an
example.
25
LPC1768 20
Vin + 6V
GND p21
15
servo
10
Servos have three wires, generally marked black (ground), red (+6 volts) and yellow
(control). The yellow wire is connected to pin 21 of the mbed. As you can see in the next
Figure the servo plug can be connected to the breadboard using small wires pushed into
the plug.
115
116 116
A servo is rather strong so make sure it can move freely. Switch the external power
supply on, and then connect the USB cable to download the program.
30
25
20
15
10
-40 -20 0 20 40
Dt=2,33 ms t (ms)
116 117
You can visualize the signal using software oscilloscope WinOscillo. For that you need to In section 4.3
use the special hardware described in section 2.2. Turn the variable resistor all the way to microcontroller
zero, and then plug the unit into the microphone plug of your PC. Important: connect the part of memory
ground wire to the ground of the breadboard and the live wire to the PWM pin of the integer - using "
mbed. Slowly turn up the variable resistor until you see the signal on then screen. Use the
"X" - vertical stretch - and "t" - horizontal stretch - sliders to make the picture fit nicely. Each location in
but it holds suc
The previous Figure shows the signal at an angle of 180 degrees. With the left and right to a memory loc
mouse buttons measuring lines were placed at the second peak from the left, showing a
width Dt of 2.33 mS. At 180 degrees the duty cycle is 0.118 and since the period is 20 mS Lets say you liv
that means the width was 0.188 * 20 mS = 2.36 mS. That corresponds nicely with our and you have a
measurement. Within its limitations - it uses the soundcard as measuring hardware - number of peop
WinOscillo is a great tool for visualizing and analyzing data. Note that the little spikes in your house - the
the horizontal lines are caused by the mbed power controller.
If you have dec
using &i. So all
7.4 USB controlled servo command expec
In this section we will control a servo from HyperTerminal using USB. We will enter a i we will use &i
number of degrees, e.g. 130 and then order the servo to rotate to that position and hold it.
pc.scan
In chapter 6 we discussed USB communications, and showed how you can get data from
HyperTerminal using the getc() command. That command transfers single keystrokes to Just like in the
the mbed. It would be much easier if we could get complete numbers, so that instead of receive. Using
for example a separate 1 a 3 and a 0 we would get the number 130 - much like we can request just two
print complete numbers using printf(). Fortunately there is such a command: scanf().
pc.scan
As a beginner y
you need to us
declared a point
int *ptr
By now you ar
The previous Figure shows what the manual has to say about the scanf command. saves memory
Noteworthy is that the string is not followed by a variable - like in the printf() command -
but by "pointers to variables". So what are pointers? 32
There are two
variable, and to a
117
118 118
In section 4.3 we discussed what variables are. When you declare a variable the
microcontrollers reserves a part of memory where you can store values, and gives that
part of memory the name of that variable. So when you declare a variable called "i" as an
integer - using "int i" - a section of memory is reserved and given the name "i".
Each location in memory has an address. A pointer doesn't hold a value, like a variable,
but it holds such an address. So a variable is a memory location and a pointer is pointing
to a memory location. Hence the name.
Lets say you live at 123 Walnut Street, you've put a sign on your house saying "The Nest"
and you have a family of four. The name of your house - the variable - is The Nest. The
number of people in your house - the value of the variable - is four. And the address of
your house - the pointer - is 123 Walnut Street.
If you have declared an integer called i then you can point to the memory location of i
using &i. So all you need to do is to preceed the variable with an ampersand. The scanf()
command expects a pointer to a variable rather than the variable itself. So instead of using
i we will use &i.
pc.scanf("%f",&i);
Just like in the printf() command we can set the format of the number that we want to
receive. Using %f means that we get the default format, but we could for example also
request just two digits.
pc.scanf("%2f",&i);
As a beginner you probably will not need to declare pointers just yet. If you do however
you need to use an asterisk (*) as a prefix. The next command means that you have
declared a pointer called ptri.
int *ptri;
ptri = &i;
By now you are probably wondering why we need all this stuff. Basically because it
saves memory and time. 32 Rather than moving variables around we leave them where
32
There are two other, more advanced reasons: to allow functions to "return" more than one
variable, and to allow dynamic memory allocation for arrays.
118 119
they are and simply point to them. It is a bit like your house. If someone asks you where els
you live you don't have to actually take her to your house, you can just point at the }
address on a piece of paper and say "there". The latter is of course much quicker. }
Let's continue with the project. We know from the previous project that a duty cycle of The hardware i
0.026 yields a 0 degree angle, and a duty cycle of 0.118 a 180 degree angle. So one requirement. Fi
degree is: program. Start H
button - the rese
0.118 - 0.026
180 = 0.000511
The minimum value is 0.026 - for zero degrees - so formula for the conversion from
degrees to a duty cycle is:
If the user enters a value outside the permitted range of 0 to 180 degrees the servo will get
incorrect commands. For that reason the command should only be given if it is within that
range, so if the angle is larger than - or equal to - zero and smaller than - or equal to - 180.
To combine these two ranges we use the AND operator &&. While we are at it we might
as well add a notice to the user in case a value outside the allowed range is entered.
int main() {
motor.period_ms(20);
while (1) {
pc.printf("\n\r Enter degrees (0-180):");
pc.scanf("%f",&i);
pc.printf("%4.0f",i);
if (i>=0&&i<=180) motor = i*0.000511 + 0.026;
119
120 120
The hardware is identical to the previous project, but this time the USB connection is a
requirement. First connect the external power, than the USB cable and download the
program. Start HyperTerminal with the settings discussed in section 6 and press the little
button - the reset button in fact - on the mbed.
On the HyperTerminal screen you can enter an angle in degrees. When you press enter
the value you entered is shown and the servo rotates the lever into the right position.
While you are typing you will not see anything until you press enter. You can fix that by
changing a setting in HyperTerminal. Goto "File", Properties" and select the "Settings"
tab. Click on the "ASCII setup" and check "Echo typed characters locally" as seen in the
next Figure.
120 121
8 Sensors
So far we have
outside world to
The next table
example project
The drawback
appears to be c
shiny object w
detected at 59 c
infrared sensor,
121
122 122
8 Sensors
So far we have used switches and (variable) resistors to provide information about the
outside world to the microcontroller. In this chapter we will discuss a few other sensors.
The next table shows an overview of all sensors that are discussed in this book, with an
example project.
In this project we will use a Sharp GP2Y0D340K infrared object detector. The sensor
emits a beam of infrared light. Infrared light is invisible to humans, but is reflected by
objects just like visible light. By measuring the amount of reflected infrared light the
presence of an object in front of the sensor can be detected.
The drawback of using this sensor is obvious: an object with good reflective properties
appears to be closer than an object with poor reflective properties. In one test, a black
shiny object was detected at 23 cm while an identical non-shiny white object was
detected at 59 cm. Be aware that objects that look black to us may not look black to an
infrared sensor, for example different types of black masking tape.
122 123
The datasheet indicates that the optimum operating voltage is 4.5 to 5.5 volts, but
fortunately the sensor also works at 3.3 volts, the operating voltage of the mbed. That
means it can be connected to the Vout pin.
The sensor is basically a switch that is turned off when an object is detected. That may
strike you as odd but the real purpose of this sensor is to detect objects that break the
infrared beam. In the recommended setup the sensor is looking at "itself" using a mirror.
Anything that passes through the beam breaks the signal and will make the sensor output
high. In this setup it can be used for burglar alarms, shop door signals, visitor counters
and so on.
In our project we used the sensors as a free roaming infrared eye. Typical applications are
proximity sensor for robots or inside machinery. For this application we need to invert the
signal from the sensor and use it to control a LED.
#include "mbed.h"
DigitalIn infrared(p20);
DigitalOut myled(LED1);
int main() {
while (1) {
myled = !infrared;
}
} In the previous
and a magnifyi
hold parts toget
glass you have a
123
124 124
Use the schematic and picture of the breadboard to build this project. Only the pins in use
are shown, the others are left out for clarification. A notation of 4/6 means that both pin 4
and pin 6 need to be connected the same way.
Vout 1
5 2 4/6
GND
1.5
1 uF
In the previous Figure a "third hand" holds the sensor. This is basically a set of two clips
and a magnifying glass on a small stand that is sold in electronics shops. It is meant to
hold parts together when you are soldering. If you remove one clip and the magnifying
glass you have a great holder for experiments like this.
124 125
The infrared sensor must be equipped with a small resistor and capacitor. The value of the
resistor is not an error, 1.5 ohm is correct. These components must be mounted as close as
possible to the sensor. If you keep the connecting wires short you can mount the sensors
and the associated components on the breadboard. But if you want to place the sensor a trigger input
to module
bit further away it is recommended to solder the resistor and capacitor directly onto the
sensor.
sonic burst
from module
We follow the s
Figure 83. Resistor and capacitor soldered to the back of the unit. pulse of at least
enough:
In this case the wires between sensor and breadboard are about 20cm so the parts are
soldered to the unit. Multiple units on the same powerlines may cause interference. If that // send p
happens a 10 uF capacitor over the powerlines can solve this. trigger=
wait(0.0
When you run the program the LED is off. Hold your hand in front of the sensor to make trigger=
the LED go on. The detection range is approximately 30 cm.
The echo line i
8.2 Ultrasonic range finder time measurem
timer.34
The SRF05 ultrasonic range finder is a relatively cheap ultrasonic sensor that uses sound // wait f
waves to measure the distance of objects. The detection cycle is started by the mbed with while (!
a pulse of 10 uS or more on the "pulse trigger" line. As soon as this line goes low again
the ultrasonic module sends a burst of 8 pulses of 40 kHz sound. To avoid direct coupling // measu
between transmitter and receiver the unit waits a bit and then sets the "echo line" to high. t.reset()
This is the signal for the mbed to start a time measurement. The first ultrasonic echo to be while (e
received switches the "echo line" back to low again. At this point the mbed must stop the i = t.rea
time measurement. The distance to the object that caused the echo can be calculated
based on the elapsed time.
33
Copyright Dav
34
As discussed in
125
126 126
trigger pulse
10 uS minimum
trigger input
to module
8 cycle
sonic burst allow 10 mS from
end of echo to next
sonic burst trigger pulse
from module
We follow the steps from the manual as closely as possible. The first step is to submit a
pulse of at least 10 uS to the pulse trigger line, so we opt for 40 uS, which should be long
enough:
// send pulse
trigger=1;
wait(0.00004);
trigger=0;
The echo line is normally low, so we wait for it to go high. As soon as that happens a
time measurement must be started until the line is low again. For this we will use a
timer.34
33
Copyright Daventech, used with permission.
34
As discussed in section 4.4
126 127
// s
Variable i now contains the length of the echo pulse in uS so the distance can be easily trig
calculated. The speed of sound through the air at room temperature is about 342 m/s. 35 At wa
a distance of 11 cm the echo took 617 uS. trig
// display result // d
pc.printf("\x1B\x48"); pc
pc.printf("\n\n\rPulselength %6.0f uS",i); pc
i=i/58; i=i
pc.printf("\n\n\rDistance %4.0f cm",i); pc
wa
We now have all the separate pieces of the program. All that needs to be added are }
declarations, the timer start command and a loop delay. }
float i;
int main() {
t.start();
pc.printf("\x1B\x48\x1B\x4A");
pc.printf(" ---===[ Ultrasonic Range ]===---");
while (1) {
35
We conserve energy: the temperature in my office is about 19 degrees C. The formula is c = 20
* square root(T) where T is the air temperature (in Kelvin) and c is the estimated speed of sound at
that temperature. Note that degrees Kelvin can be calculated by adding 273.15 to the temperature
in degrees C.
127
128 128
// send pulse
trigger=1;
wait(0.00004);
trigger=0;
// display result
pc.printf("\x1B\x48");
pc.printf("\n\n\rPulselength %6.0f uS",i);
i=i/58;
pc.printf("\n\n\rDistance %4.0f cm",i);
wait(2);
}
}
You can use the schematic and the picture of the breadboard to connect the SRF05. If you
watch closely you will see that one of the SRF05 pins is not connected. This is because
we operate the unit in SRF04 compatibility mode, so this pin is not required. The
advantage is that you can optionally also use the SRF04 in this project.
Vout V+
p20 echo
SRF05
LPC1768
p19 trigger
GND
GND
128 129
The SRF05 is designed to operate at 5 volts. It works at 3.3 volts as well, but the
minimum distance is larger. A difference in maximum distance was not observed. The
data in the table are actual measurements, the values for your unit may differ.
In this project we use 3.3 volts for the SRF05. If you want the smaller minimum distance
you can use an external power supply of 5 volts. Connect the ground to the ground of the
mbed, and the +5 volts to the V+ pin of the SRF05. You do not need to change the wires
to pin 19 and 20. The SRF05 will recognize the 3.3 volts trigger signal as a high signal.
The echo reply to the mbed is 5 volts, higher than the operating voltage of 3.3 volts.
Normally this is a big no-no, however the mbed is 5 volts tolerant so in this case it is
allowed: you will not damage anything.
8.3 Human d
In this project w
and can be hidd
alum
(8 x
During operation a little LED on the back of the unit will flash at each pulse as an
indication that the unit is operational. The next Figure shows the actual measurements in
HyperTerminal during operation. The schematic s
sweeper of a va
One of the side
digital output th
129
130 130
In this project we will build a human detector. An aluminum foil sheet acts as a detector
and can be hidden for example underneath the carpet or a rug.
100k
aluminum foil
(8 x 13 cm)
p20 p19
LPC1768
The schematic shows that the aluminum foil - for example 8 x 13 cm - is connected to the
sweeper of a variable resistor with a very large value, and to a digital input on the mbed.
One of the side of the pot is not connected to anything, the other side is connected to a
digital output the mbed.
130 131
The program may surprise you. A large resistor connects the output and input. We make
the output high and the wait for the connected input to be high - or rather: not low. You'd
think that this would always be the case considering that it is connected to a high output
pin. But it is not.
#include "mbed.h"
DigitalIn capin(p20);
DigitalOut capout(p19);
DigitalOut human(LED1);
int main() {
while (1) {
capout=1;
human=0;
while (!capin);
human=1;
wait(0.1);
}
}
The mbed is "looking" at the input pin to see if it is high or low. In order to do that a
small current has to run through the pin. The problem is that the resistor is so large that
even this small current causes a voltage drop. So the input pin is not "as high" as you
might expect. If the pot is set in the middle - so at about 50 k - the voltage on the input is
not 3.3 volts but only 0.8 volts. And that is considered "low" by the mbed. That means
that the command " while (!capin);" will halt the program.
A capacitor consists of two conducting plates with a non-conducting medium - called the
dielectric - in between. Due to this design it is capable of storing a certain amount of
electrical charge. How much that is depends on the dimensions and the materials used.
The aluminum foil in its plastic sleeve acts as such a capacitor. The foil is one plate, the If you use a ru
plastic is the dielectric and the air is the other plate. That is not a very good design for a capacitive load
capacitor so it doesn't hold a lot of charge. That means it is charged "instantly" and it account. Once y
doesn't do anything to the voltage so the mbed will not even notice its presence. Then put on yo
If you remove y
When you put your hand on the sensor you are changing this capacitor. Now your body
replaces part of the air, and this causes the capacitor to have a much higher capacity. This Once you have
means that the small current through the resistor is "stored" in the capacitor and raises the so that the LED
voltage on the mbed input. If the capacity of the capacitor is large enough the voltage on a warning is dis
the input can be high enough to be regarded as high. At that moment the LED is lit and
the program continues.
131
132 132
If you use a rug or carpet on top of the sensor, then that in itself will be part of the
capacitive load of the sensor. So you will need to adjust the sensitivity to take this into
account. Once you have downloaded the program place the sensor at the desired location.
Then put on your shoes and step on top of the sensor. Turn the pot so that the LED is on.
If you remove your foot the LED should now be of.
Once you have established the correct setting for the pot, you could change the program
so that the LED stays on longer, or you could add USB capabilities to the program so that
a warning is displayed in HyperTerminal when a person is detected.
132 133
while
cap
wa
t.re
cap
wh
i=
pc
}
}
If you are interested in the charge times of the detection capacitor you can use the
following program to collect data. This program will first make the output low to
discharge the capacitor, and then make it high again. It will then measure how long it
takes for the capacitor to charge.
#include "mbed.h"
DigitalIn capin(p20);
DigitalOut capout(p19);
DigitalOut human(LED1);
Serial pc(USBTX, USBRX);
Timer t;
float i;
int main() { F
t.start();
133
134 134
while (1) {
capout=0;
wait(0.1);
t.reset();
capout=1;
while (!capin);
i = t.read_us();
pc.printf(" %f ",i);
}
}
When you use this program you can view the data on the HyperTerminal screen. Adjust
the pot so that the program is outputting data. This means that this command "while
(!capin);" is passed and the capacitor is charging enough to help the input pin get high.
The values that you see vary wildly. This is the charging time in uS for that particular
setting of the pot.
Now put you hand on the sensor. You will immediately see the measured times drop.
Depending on the setting of the pot there may be a huge drop in charge times.
134 135
The previous Figure shows the charge times at a pot setting of about 1/3 up, so 33 k.
Somewhere around sample 70 a hand is nearing so the charge time shows a sharp drop to
below 500 uS. When the hand is flat on the sensor the charge times drops even further to
about 12 uS.
In case you are wondering how to get these data into an Excel spreadsheet to make a
graph like this you can use the "Capture Text" functionality of HyperTerminal. Select
"Transfer" and then "Capture Text" and then enter an appropriate file name. When you
are done use the same menu path to get to "Stop". In Excel simply load the file and
parsing will be suggested automatically. Select "space" as field delimiter.
Much like the Wii® remote control the GP1S036HEL sensor reacts to tilt and motion too.
The sensor has a tiny ball inside. On one side of the ball is an LED and on the other side
are two light sensitive sensors. When you tilt the sensor the little ball moves, thereby
blocking - or rather, interrupting - the light to one or more of the internal sensors. For that
reason Sharp calls this device the "Photointerrupter for Detecting Tilt Direction".
This sensor can also be used to detect motion and even vibration, assuming the vibrations
are a bit "wild". Example applications are a battery powered bicycle light that remains
switched on as long as the bicycle is moving - add a light sensor to make sure that the
light is on only in the dark - or a home built Wii-like remote control.
Connecting the sensor is easy with the only exception being that the diagram in the
datasheet of the manufacturer says "top view", but should read "bottom view". So pay
attention when connecting the unit.
The LED inside the sensor is connected using a 220 ohm current limiting resistor. That
translates to a current of I = V / R = 3.3 / 220 = 15 mA, way below the maximum of 100
mA as specified by the manufacturer. The output collector can deliver a maximum
current of 20 mA. We will use a 1k resistor which results in a current of 3.3/1k = 3.3 mA,
also far below the maximum.
135
136 136
1k
Vout 1 5
p20 4
LPC1768 GP1S036HEL
p19 3
2
GND
136 137
Sensor po
Level, in f
Rotated 90
Rotated 18
Rotated 27
In addition to d
ball inside is flu
Acce
To t
To
8.5 Tempera
Figure 94. The project on a breadboard.
The temperatur
The software is very straightforward because this is a static sensor. The only thing that temperature of
needs to be done is to keep an eye on the sensor outputs and send that information to the Centigrade equa
two status LEDs.
The nice thing
#include "mbed.h" easy to use. T
microcontroller
DigitalIn sens1(p20); the mbed need
DigitalIn sens2(p19); conversion will
DigitalOut dir1(LED1);
DigitalOut dir2(LED2); In chapter 5 we
that is a bit of a
int main() { reality it is not
while (1) { capacitor betwe
dir1=sens1; signals that in
dir2=sens2; measurements a
} declare a count
} speaking this is
itself.
137
138 138
The tilt sensor can detect four rotations in a vertical plane. The LEDs display the different
positions the sensor can detect as shown in the table:
In addition to determining its position the sensor can also indicate acceleration. The little
ball inside is flung to one of the sides if the sensor is accelerated (or decelerated).
The temperature sensor LM35 generates a voltage that is directly proportional to the
temperature of the unit. That means that regardless of the supply voltage 1 degree
Centigrade equals 10 mV.
The nice thing about this sensor is that you do not need to calibrate it, and that it is very
easy to use. The downside is that the sensor needs to be relatively close to the
microcontroller to prevent any kind of loss in the cabling and that the power regulator of
the mbed needs to work accurately. If the voltage is not exactly 3.3 volts the A/D
conversion will be off, and thus the measured temperature.
In chapter 5 we have already seen than the A/D measurements tend to vary. In this project
that is a bit of a problem because it suggests that the temperature is fluctuating while in
reality it is not. We will solve this problem in two ways. First of all we add a 100 nF
capacitor between the AnalogIn pin and the ground. This will eliminate noise - stray
signals that interfere with our wiring. Second we will take a large series of A/D
measurements and then take the average. For this we use the "for" loop. Normally we
declare a counter variable to be used in the loop at the beginning of our program. Strictly
speaking this is not really necessary: we can also declare the variable in the for statement
itself.
138 139
That means we can convert the A/D measurement to a temperature using this formula:
Where T is the temperature and A/D the result of the A/D conversion. Since we took 100
measurements in i this translates to:
Simplified:
We will setup an USB connection and display the temperature in HyperTerminal using
the commands we have discussed earlier.
#include "mbed.h"
float i=0;
int main() {
pc.printf("\x1B\x48\x1B\x4A");
pc.printf(" ---===[ Temperature ]===---");
while (1) {
pc.printf("\x1B\x48");
i=0;
for(int t=0;t<100;t++) i=i+temp.read();
139
140 140
The hardware is quite simple. The 100 nF capacitor - code 104 - is mounted close to the
LM35 but that is not a requirement. If you hold the LM35 with the pins down and the text
facing you the left pin is the +3.3 volts, the right pin is the ground and the center pin
carries the temperature related voltage.
Vout
p20 LM35
LPC1768
100 nF
GND
140 141
A low temperat
It is rather unlik
Figure 97. The temperature of my office in HyperTerminal. how to switch h
It is quite easy to turn this project into a low temperature alarm. Simply add a threshold
value for 100*i and check against it. Let's say you want an alarm LED to go on if the
temperature drops below 20 ºC. Since each degree is 10 mV the threshold should be 20 *
10 mV = 0.2 volts. This is the equivalent of an A/D measurement of 0.2/3.3 = 0.0606.
Since we add 100 measurements in i the threshold value for i should be 100 * 0.0606 =
6.06.
Since any measurement is always fluctuating, if only by a tiny bit, the LED may start
flashing around the threshold value. For sometimes the measurement is just below the
threshold, and at another time just above it. The solution is to introduce hysteresis.36 That
means that the threshold for the LED to go on is not the same as for the LED to go off. So
we will make the LED go off at a temperature of 20.2 degrees. That translates to a value
for i of 6.12.
#include "mbed.h"
float i=0;
int main() {
pc.printf("\x1B\x48\x1B\x4A");
pc.printf(" ---===[ Temperature ]===---");
36
Hysteresis means "lagging behind" and is a very common natural phenomena.
141
142 142
while (1) {
pc.printf("\x1B\x48");
i=0;
for(int t=0;t<100;t++) i=i+temp.read();
pc.printf("\n\n\rTemperature %4.1f C ",i*3.3);
if (i<6.06) toocold=1;
if (i>6.12) toocold=0;
wait(0.5);
}
}
A low temperature alarm is in fact a thermostat that can be used to control a space heater.
It is rather unlikely that your heater runs off 3.3 volts, so in section 10.3 we will discuss
how to switch higher voltages and currents.
142 143
The audible frequency range is between 20 Hz and 20 kHz.37 The sensitivity of our ears #includ
is highly frequency dependent, as you can see in the next figure.
DigitalO
90
int main
80 while
sound pressure (dB)
70 sou
wa
60
sou
50 wa
40 }
30
}
20
10
The simplest way to make a sound is to connect a speaker to a powersource and quickly
switch the power on and off. The result is a signal that is alternatingly high and low. The In the project w
frequency of the resulting sound is calculated based on the time of the high plus the low this speaker wo
only deliver 40
37
James Boyk has shown in his May 2004 article "There's Life Above 20 Kilohertz! A Survey of contains a coil
Musical Instrument Spectra to 102.4 kHz" that people react to sounds above 26 kHz even if they other things. Fo
FDQ¶WFRQVFLRXVO\KHDUWKHP 11.0 and 12.6 m
part. That is because a single sound wave consists of a positive part and a negative part. If
the high time is 0.01 second and the low time is 0.01 second as well then the sound
frequency is:
1
f = 0.01+0.01 = 50 Hz
Note that this is half the pin-change frequency. The program itself is rather
straightforward. Make the pin high, wait a bit, and than make it low again and wait a bit.
#include "mbed.h"
DigitalOut sound(p21);
int main() {
while (1) {
sound=1;
wait(0.001);
sound=0;
wait(0.001);
}
}
volume p21
1k
LPC1768
speake r GND
8 ohm 0.4 W
In the project we use an 8 ohm speaker of 0.4 W. If you apply Ohms law you will see that
this speaker would draw 3.3/8 = 412 mA of current, much too much for the mbed that can
only deliver 40 mA. In this case however Ohms law does not apply because a speaker
contains a coil in an electric field, so the resistance depends on the frequency, amongst
other things. For this particular speaker in this project the measured current is between
11.0 and 12.6 mA, so within specification for the mbed.
144 145
[î
38
A 1k LIN variable resistor is used to control the volume. At 3.3 volts the volume is not
very impressive but a beep can quickly become quite annoying. 8
-2
-4
You can connect the input of the speaker - so pin 21 - to the PC using the special
hardware described in section 2.2 so you can see what the signal looks like with
WinOscillo. A waveform like this is called a "square wave". It is easy to make but it
doesn't sound particularly pleasing to the human ear.
The square wave in the next Figure looks quite nice. Most of the deviations are caused by 9.2 Variable
the capacitor on the soundcard of your PC. The square wave has peaks and valleys of 1 In the previous
mS each which matches the wait statement in the program perfectly. the thought cro
tone generator s
#includ
Analog
DigitalO
int main
float
while
i=
38
sou
A LIN variable resistor has a linear change in resistance while a LOG variable resistor has a wa
logarithmic change in resistance. Often LOG types are used in sound applications and particularly
sou
volume control. In this book however all variable resistors - or pots - are LIN.
145
146 146
-2
-4
-4 -2 0 2 4
Dt=1,00 ms t (ms)
#include "mbed.h"
AnalogIn mypot(p20);
DigitalOut sound(p21);
int main() {
float i;
while (1) {
i = mypot.read()/100;
sound=1;
wait(i);
sound=0;
146 147
While we are at
the wait stateme
volume p21 Vout
frequency
(3.3 V) #includ
1k
LPC1768
10k
p20 Analog
DigitalO
speake r GND
8 ohm 0.4 W
char fla
int main
Figure 102. Schematic of the variable frequency project. while
wa
On the breadboard the left pot controls the frequency and the right pot controls the flag
volume. Note that both variable resistors are LIN. The current through the 8 ohm 0.4 W sou
speaker varies according to measurements between 11.0 and 12.6 mA depending on the }
frequency. }
147
148 148
Technically the square wave is a bit askew because the "low period" includes the A/D
conversion while the "high period" doesn't. We can fix that by using a "flag" variable to
flip the pin. It is not recommended to use the command "sound = !sound" because in
order to execute that the mbed first needs to see what the current status of the sound pin is
before it can make it the exact opposite. Since that pin is connected to a speaker and thus
a coil there is no telling what the current status will be at that particular moment,
especially at higher frequencies. So it is unlikely that the resulting sound will be a nice
square. It is considered good programming practice to use an intermediary variable, a so
called flag. Since this flag will only be zero or one it is declared a char which is more
than large enough.
While we are at it let's behave like C programmers and combine the A/D conversion with
the wait statement thus eliminating the need for float i.
#include "mbed.h"
AnalogIn mypot(p20);
DigitalOut sound(p21);
char flag=0;
int main() {
while (1) {
wait(mypot.read()/100);
flag = !flag;
sound=flag;
}
}
The next Figure shows the original asymmetrical square wave. The high period is 6.08
mS and the low period 6.17 mS. That implies that an A/D conversion takes about 6.16 -
6.08 = 0.08 mS.
With the adapted program both periods are 6.17 mS. Of course you will not see or hear
any difference unless you use a tool like WinOscillo.
148 149
speake r
0 8 ohm 0.4
-2
-4
-40 -20 0 20 40
Dt=6,08 ms t (ms)
Many people find groups of teens hanging about annoying and look for non-violent ways
to keep their doorsteps empty. One solution is to play a high pitched whistle at a
frequency that only teenagers can hear. The constant whistle gets annoying very quickly.
The target frequency is 16 to 20 kHz.
If you are a teenager yourself you can use this project to make a secret doorbell or
warning signal that adults cannot hear. In fact you could even use Morse-like signals to
secretly communicate even whilst surrounded by unsuspecting adults.
We can use the Beep program to make this high pitched sound. For a frequency of 16 First built the h
kHz we need a wavelength of 1/16000 = 6.25 10-5. Since this delay is split in two parts - microphone or
one for the high pulse and one for the low pulse - each wait statement must be half of this and the hot wir
so 3.13 10-5. mbed but plenty
At these high frequencies the amount of time that it takes for the mbed to execute its #includ
program begins to play a role. This processing time "adds" to the delay causing a slightly
DigitalO
149
150 150
lower frequency. The best solution is to simply test a few delays close to the calculated
value and see which one yields the best result. For this we will use the Spectrum Analyser
software.
volume p21
1k
LPC1768
speake r GND
8 ohm 0.4 W
First built the hardware. Connect the special hardware as discussed in section 2.2 to the
microphone or line input of the PC. Connect the common wire to the ground of the mbed,
and the hot wire to pin 21 of the mbed. There is no room on the breadboard next to the
mbed but plenty near the variable resistor. Run the following program.
#include "mbed.h"
DigitalOut sound(p21);
150 151
int main() {
while (1) {
sound=1;
wait(0.000035);
sound=0;
wait(0.000035);
}
}
Start the Spectrum Analyser program, and click on the Run button. The whole spectrum
of frequencies that the program detects is displayed. Turn the variable resistor on the
special hardware up until you see a clear peak in the signal. Click with the mouse near the
high peak to move the blue line. The small red line will now search for the strongest
signal near the blue line, and this value is shown at the bottom right corner.
With a wait statement of 0.000035 the calculated frequency is 1/0.000035/2 = 14.3 kHz.
In reality the measured frequency is 13.1 kHz. Repeat this process for a series of different
wait statements to get the following table.
Fig
Frequency Frequency
x in Wait(x); This shows th
(kHz, calculated) (kHz, measured)
approximately 0
0.000035 14.3 13.1
0.000030 16.7 15.6 #includ
0.000025 20.0 18.4
0.000020 25.0 21.5 DigitalO
We can put these measurements in a graph. If we draw a line from 16 kHz to the int main
measurements curve and then down to the time axis we can estimate the correct x for our while
target frequency. sou
wa
sou
wa
}
}
151
152 152
This shows that the desired frequency can be obtained with a wait statement of
approximately 0.000028, so this is the completed program.
#include "mbed.h"
DigitalOut sound(p21);
int main() {
while (1) {
sound=1;
wait(0.000028);
sound=0;
wait(0.000028);
}
}
The next Figure shows the corresponding measurement, which indeed shows a frequency
of 16.0 kHz, so spot on.
152 153
generation. It i
flashing LED to
#includ
PwmOu
DigitalO
int main
speak
speak
myle
while
my
wa
Figure 108. Youth repellent at 16 kHz.
}
This program works as it should, but it has no time for other things. In fact even adding a }
simple functionality such as a flashing LED to show that the program is running requires
a major re-write because the timing will be off. In section 7.2 we discussed the use of When I made t
PWM - pulse width modulation - to control a motor. It turned out that PWM is basically a spectrum analy
square wave, so it could be used to generate sound as well. So when my tee
to ask "Do you
The formula for the period is period = 1/frequency so for 16 kHz that means: "What is that ho
153
154 154
generation. It is just a simple setting and that's it. This means it is now easy to add a
flashing LED to show that the program is still running.
#include "mbed.h"
PwmOut speaker(p21);
DigitalOut myled(LED1);
int main() {
speaker.period_us(62.5);
speaker = 0.5;
myled = 0;
while (1) {
myled = !myled;
wait(1);
}
}
When I made this project I had no idea if it actually worked, for I couldn't hear it. The
spectrum analyzer did show a strong peak at 16 kHz, but would it be annoying enough?
So when my teenage daughter walked into my office I switched it on and I was just about
to ask "Do you hear anything?" when she jumped back, covered her ears and yelled
"What is that horrible noise!?"
So I guess it works just fine. Note that in some countries the use of this device on public
or semi-public premises is illegal. So check your local laws before using it.
In this project we will use a file, a ticker and a function, which will all be discussed in the
next chapter. If you want you can do this project and take for granted that files, tickers
and functions exist and work as claimed. However if you are curious as to why this is it is
recommended that you read sections 10.1 to 10.3 before continuing.
In this project we will use the mbed to play a small sound. If you read section 10.1 the
thought may have occurred to you that it should be possible to read a file from the mbed
drive and play it through a speaker. In theory this is indeed possible, in practice however
the speed of the mbed drive is much too low. So we will use a small trick: we will read
the entire file into the microcontrollers' memory, and then play it back. The drawback of
this technique is that the length of the sound file is limited by the size of the available
memory.
154 155
In this project w
The NXP LPC1768 has 512 kB flash - for programs - and 64 kB data mamory. With our we will take is
free mbed tools we can only access half of that, so for the sound file we have 32 kB Edit and select
available. There are many different types of sound files, the most commonly known is following data:
MP3. This is a highly compressed sound, and deciphering it would be a bit too much for a
beginner's book so we will use a WAV file instead. A WAV file is made by sampling the Sample
sound using an A/D converter at a certain frequency. This frequency is called sampling Channe
rate or bit rate. The digital samples are stored in a file. In order to play this file each Resolut
sample needs to be send to a D/A at the exact same bit rate that was used during Quality
recording. Pre/pos
The higher the bitrate the more samples are taken per second and the higher the sound Then click on
quality. A higher bitrate also means a larger file, and our room is limited. If the sampling using a differen
rate is 16,000 Hz the available memory will hold 32 k / 16 kHz = 2 seconds of sound. At expects files in
half the sampling rate the memory will hold 32 k / 8 kHz = 4 seconds. For speech an 8k digits, followed
sampling rate is quite acceptable with respect to intelligibility. the filename.
We can verify t
properties, and
39
Licensed from
40
The free down
rate, ready for us
41
The size on d
room the file tak
Figure 109. Convert sample type in Cool Edit. PC stores files on
counted as compl
155
156 156
In this project we will use the text "O my God, I'm, like, totally blonde". 39 The first step
we will take is to convert the sound file to a lower sampling rate.40 Load the file in Cool
Edit and select File and then Convert Sample Type. A small window will open. Enter the
following data:
Then click on the OK button. When the conversion is done save the file on the mbed
using a different file name, for example blonde8k.wav. Note that the mbed file systems
expects files in the 8.3 format. This means that the filename should be no more than eight
digits, followed by a decimal point, followed by three digits. Spaces are not allowed in
the filename.
We can verify the size of the file in Windows Explorer. Right click on the file and select
properties, and check the size. In the previous Figure the size is shown as 27,033 bytes.41
39
Licensed from www.audiosparx.com.
40
The free download contains a prepared sound file - blonde8k.wav - with the correct sampling
rate, ready for use.
41
The size on disk, in this case 32,768 bytes, is irrelevant for this project. It shows how much
room the file takes when stored on disk. This is always larger than the real file size because your
PC stores files on disk in sections. Since a section can only hold one file partially used sections are
counted as completely used.
156 157
Assuming we s
zero. The only
at the fixed freq
exact frequency
we can be certa
while (!
done = 0
sound =
Before we can p
use the size we
file, so in this ca
Figure 110. The size is 27,033 bytes (WinXP SP2 Dutch version). char blo
157
158 158
Assuming we set done to zero the program will stay in this loop until done is no longer
zero. The only way that this can happen is in the ticker routine, and this routine is called
at the fixed frequency of 8 kHz. That means that the program will leave this loop at the
exact frequency of 8 kHz. If the next command is to send the data to the D/A converter
we can be certain that the sound is played at the correct speed.
while (!done);
done = 0;
sound = float(blonde[i])/255;
Note that the D/A converter expects a value between 0 and 1, while a WAV file contains
values between 0 and 255. If we simply divide the WAV number by 255 the compiler
will assume that we want a char value as result, so either 0 or 1. In reality however we
want a float, so values from 0 to 1. We can tell the compiler that we want a float by
forcing it to treat the WAV values as float - rather than char. For this you can use the
command float().
Before we can play the file we need to read it into the data memory of the mbed. First we
use the size we observed in Windows Explorer to declare an array that can hold the entire
file, so in this case and an array of 27033 chars that we will call "blonde".
char blonde[27033];
The next step is to open the file and read it into the array. You need to be careful that you
use the correct file length.
All that is left as far as software is concerned are a few declarations and loops to wait for
the button to be pressed.
#include "mbed.h"
Ticker rhythm;
LocalFileSystem local("local");
DigitalIn button(p20);
DigitalOut myled(LED1);
AnalogOut sound(p18);
int i, done=0;
158 159
float c;
char blonde[27033];
void myrhythm() {
// ticker routine
done=1;
}
int main() {
while (1) {
10k
// play the sound
for (i=0;i<27033;i++) {
while (!done);
done = 0;
sound = float(blonde[i])/255;
}
It is recommend
} irrelevant - as l
} seen that the US
that is not a pro
noise. When yo
noise is elimina
159
160 160
Once the program is compiled you can check memory usage by clicking on the Build
Options in the Compiler screen. This shows that the program uses 85% of RAM memory.
The array is 27,033 bytes, the available RAM memory is 32 k, so the usage is 27,033 /
32,000 = 84.4%. The rest is used by other variables in the program. Note that if you do
not have enough memory the program will not compile.
+4.5 - 9 V
headphones
10k
GND
It is recommended that you use an external power supply for this project. The voltage is
irrelevant - as long as it is between 4.5 and 9 volts. In previous projects we have already
seen that the USB power supply causes tiny spikes on the powerline. Normally speaking
that is not a problem but in sound applications such as this these spikes cause an annoying
noise. When you use an external power supply and pull the USB plug from the PC this
noise is eliminated.
160 161
9.5 Cricket
In the previous
will use a small
rhythm.
Figure 113. The project on a breadboard, on the right part of the headphones is visible. New in this pro
intervals. In ord
When the program is loaded using the reset button LED1 will light. Make sure the file
blonde8k.wav is on the mbed drive. Now press the button on the breadboard to read the random
file and load it into the microcontroller. The LED will go off during reading. When the
LED is back on press the button to listen to the sound. The LED is off during playback. Variable "max"
You can repeat the playback step as often as you like. will get. The ne
including six.
The volume is more than enough if you use headphones. If you want to use a speaker
consult the next project where an LM358 is used to allow the connection of a small random
speaker.
The percent sig
If you want to use your own sound in this project you need to take the following steps. 16%5 is 1, beca
1. Use Cool Edit to convert the sample type to mono, 8 bits and a reasonable sampling Of course ther
rate for example 8 kHz for speech. Save the file in an 8.3 setup. microcontroller
2. Check to see if the size of the file is small enough to fit in the mbed, so less that 32 these instructio
kB, and note the size. If not then use a lower sampling rate, or make the sound bit problem. Witho
shorter. user is not able
3. Adjust the length of the array in the software and the two locations where they array
is used to the size of the file, and change the file name. The second issu
4. If you used a different sampling rate then change the frequency of the ticker to match the generator,
the sampling rate. generated are e
5. Copy the sound file to the mbed, compile and run the program. cricket. In fact
knowing that th
for a game this
case the seed ca
161
162 162
9.5 Cricket
In the previous project we used a sound file that was played just once. In this project we
will use a small sound bit and play it in a random manner, to emulate a cricket.
The first part of the program is quite similar to the previous project. The sound file we
use is much smaller this time, just 1165 chars, and the sample frequency is slightly higher
at 9766 Hz. Since we have plenty of room anyway we will not bother to change the
sampling rate to another frequency. That means the ticker function should be executed
every 1/9766 = 0.00010 seconds.
rhythm.attach(&myrhythm, 0.0001);
New in this program is that the sound isn't played just once but repeatedly, with random
intervals. In order to get random numbers the "rand" function can be used.
randomnumber = rand()%max;
Variable "max" indicates the maximum number minus one that variable "randomnumber"
will get. The next command for example will generate random numbers from 0 up to and
including six.
randomnumber = rand()%7;
The percent sign means "modulo" which is the remainder after a division. For example
16%5 is 1, because 16/5=3 remainder 1.
The second issue with random number generators is that they need a first number to start
the generator, the so-called seed. If the seed is the same then the numbers that are
generated are exactly the same as well. Often this doesn't matter, like in the case of our
cricket. In fact it may even be beneficial because you can test two different programs
knowing that the numbers that they work with are the same. If random numbers are used
for a game this is a huge problem because it would make the game predictable. In that
case the seed can be changed using this command the "srand" command.
162 163
srand(number); // set
rhyth
A good way to do this is run a counter. When the user presses a button use the current
counter position as seed. Since it is unlikely that a user can press a button twice at the while
exact same counter position this is a reasonably random way to seed the generator.
// p
c = rand()%100; for
if (c>70) wait (2);
else wait(c/100);
In crickets, as in many other animals, Lévy motion is quite common. That means several }
short intervals with occasional long intervals. In this program 30% of the intervals is 2
seconds, while 70% of the intervals are in the range of 0 to 1 second. // i
c=
Putting it all together results in this program. if (
els
#include "mbed.h" }
}
Ticker rhythm;
LocalFileSystem local("local"); You can use th
DigitalIn button(p20); project is identi
AnalogOut sound(p18); speaker of cour
give it a summe
int i, done=0;
float c; The mbed D/A
char cricket[1165]; limited current.
all. In section 5
void myrhythm() { the signal consi
// ticker routine
done=1; The solution is
} fluctuations una
OPAMP. The
int main() { converter, whic
unaffected. Thi
// press the button to load the file the OPAMP w
while (!button); provide much m
163
164 164
while (1) {
You can use the same hardware as in the previous project. The sound volume in this
project is identical to the previous on, so you could use headphones to listen to it. Using a
speaker of course is more fun because you can locate the mbed somewhere in a room and
give it a summer feeling.
The mbed D/A converter - like all D/A converters for that matter - can only supply a very
limited current. If you connect a speaker to the pin you will probably not hear anything at
all. In section 5.4 we have already seen that even a small load on the converter will distort
the signal considerably.
The solution is to use a small amplifier for the current, while keeping the voltage
fluctuations unaffected. We will use an LM358 operational amplifier - also known as
OPAMP. The advantage of an OPAMP is that is poses almost no load on the D/A
converter, which means that the voltage fluctuations of the D/A converter are practically
unaffected. This is important otherwise the sound would be distorted. At the same time
the OPAMP will copy the voltage from its input to its output, but with the ability to
provide much more current. Enough current in fact to drive a small speaker.
164 165
-
output
input
+
OPAMP
In our case we need to make sure that DC is blocked from reaching the speaker. If it were
passed through it would "pull" the coil of the speaker to one side making it harder for the
coil to move. That would seriously dampen the sound, so we use a DC blocking capacitor
of 10 uF.42
+4.5 - 9 V
GND
can use exactly
1. Make sure t
2. Download t
Figure 115. Cricket schematic. 3. Press the b
chirping au
The LM358 is equipped with two OPAMPs in an 8 pin package, but in this project we
will only use one. 9.6 Sound sw
So far we have
an Electret micr
An Electret mic
42
You can check this by leaving out the capacitor to see what effect that has on the speaker. current limiting
165
166 166
You can use this same technique for project 9.4, the talking microcontroller. In fact you
can use exactly the same hardware.
So far we have used the mbed to make sound, this time we will use it to detect sound with
an Electret microphone.
An Electret microphone needs power so we will connect it to the ground, and through a
current limiting resistor of 2k2 to +3.3 volts. The signal from the microphone is led
166 167
through a 1 uF capacitor to block DC current and fed into an analog pin of the mbed. In In the program
principle the microphone will produce both positive and negative waves - negative with the thresh
meaning below ground level. The mbed doesn't like voltages outside the 0 to 3.3 volt detected and the
range, and most definitely not negative values. For that reason a 100k LIN variable
resistor is connected to the pin as well to raise the default level. In the program we will #includ
use 50% as threshold, so the variable resistor must be set about halfway.
Analog
DigitalO
float i;
2k2
int main
Vout
1 uF (3.3 V) while
i=
LPC1768
if (
els
100k
+
p20
GND }
Electret
Microph one }
167
168 168
In the program all we need to do is measure the voltage on the analog pin, and compare it
with the threshold value of 0.5 - or 50%. If the voltage is higher a sound has been
detected and the LED will be lit for one second.
#include "mbed.h"
AnalogIn myinput(p20);
DigitalOut myled(LED1);
float i;
int main() {
while(1) {
i = myinput;
if (i>0.5){myled=1;wait(1);}
else myled=0;
}
}
Adjust the variable resistor to the point were the LED stays off during "silent" periods.
Now clap your hands and the LED will light for 1 second. Since the microphone is not
amplified the sensitivity is not very high, but high enough to detect clapping sounds.
We said earlier that the Electret microphone will produce both positive and negative
waves, because soundwaves have a positive as well as a negative part. The variable
resistor "raises" the voltage level so that the negative parts of the sound wave stay well
above zero volts, or ground.
168 169
10 Miscella
This section co
other than that t
offset due to
varia ble resistor
10.1 Using fi
+
- The PC regards
of it is. This dr
format. Interest
this file area dir
need for additio
Figure 120. Left: original level at the 1 uF capacitor, right: level offset by the 100k pot. The advantage
file. Let's say t
That means that when you clap your hands the voltage will rise above the "quiet" level in remote location
the positive part of the wave, but fall below that level in the negative part of the wave. So take the mbed b
interestingly enough the following program will work as well! an Excel spread
#include "mbed.h"
AnalogIn myinput(p20);
DigitalOut myled(LED1);
float i;
int main() {
while(1) {
i = myinput;
if (i<0.5){myled=1;wait(1);}
else myled=0;
}
}
The changes in the program are printed bold. Of course the variable resistor now needs a
slightly different position. To adjust it start slightly "too much" toward the positive F
contact of the variable resistor and slowly turn it down until the LED goes on. Then turn
it back just a little bit.
The following t
169
170
10 Miscellaneous
This section contains a selection of miscellaneous projects that have nothing in common,
other than that they do not belong in one of the other chapters.
The PC regards the mbed as a memory stick, and thus as a separate drive. And in fact part
of it is. This drive is 2 MB large and is used for storing program source code in BIN
format. Interestingly enough the mbed has several commands that allow you to access
this file area directly. That means you can read and write files of up to 2 MB without the
need for additional hardware.
The advantage is that you can have the mbed communicate with the PC using a simple
file. Let's say that the mbed is recording temperature data for a certain period at some
remote location, perhaps even running on batteries. When that period is completed you
take the mbed back to the office, plug it in your PC and read the data using for example
an Excel spreadsheet.
PC
data sampling "in the field"
mbed
Figure 121. Using the mbed local file system to transfer data.
The following table shows some of the commands related to the local file system.
170
171
FILE *f
if(!fp) {
pc
}
Next we define
will read the f
whichever com
contain lines lo
lines. We keep
char bu
while(f
pc
Figure 122. Hardware for all projects in section 10.1: using files. wa
171
172 172
The hardware for this section is just the mbed, connected to a PC with a USB cable. Note
that the mbed file systems expects files in the 8.3 format. This means that the filename
should be no more than eight digits, followed by a decimal point, followed by three
digits. Spaces are not allowed in the filename.
As a first exercise we will read a local file. In the free download file you will find a file
called myfile.txt in the directory labeled 10.1. Copy that file to the mbed, but do not press
the reset button just yet.
The first step is to declare the local file system. This will enable us to use the relevant
commands. Since we intend to show the result on the PC we will declare a USB uplink as
well. The latter is not required if you do not want to send data to the PC, bypassing the
file method.
LocalFileSystem local("local");
Serial pc(USBTX, USBRX);
The next step is to open the file that we want to use. Since we want to read it we use "r" -
read - as operation. We will call the file fp. Note that this file is declared using a pointer,
so do not forget to use the *.
If the file fails to open - for example because the file doesn't exist - the variable fp will be
false. In that case an error message is printed to the PC using the USB data connection
if(!fp) {
pc.printf("File not found\n");
}
Next we define a char variable array to hold the data that we want to read. The program
will read the first line of the file, or the first number of chars that fit in the buffer,
whichever comes first. In this case we will assume that the textfile that we use doesn't
contain lines longer than 128 characters. That means that we will be reading complete
lines. We keep reading lines until there are none left, and print them to the PC.
char buffer[128];
while(fgets(buffer, 128, fp)) {
pc.printf("%s", buffer);
wait(1);
172 173
} This is
} to see if
can be r
When the program is done it closes the file and sends a "Done" message to the PC.
The next Figure
fclose(fp);
pc.printf("\n\n\rDone");
#include "mbed.h"
LocalFileSystem local("local");
Serial pc(USBTX, USBRX);
char buffer[128];
while(fgets(buffer, 128, fp)) {
pc.printf("%s", buffer);
wait(1);
}
fclose(fp);
pc.printf("\n\n\rDone");
}
173
174 174
This is a testfile,
to see if the text in this file
can be read by the mbed.
The next Figure shows the output of the program, which matches this exactly.
During local file operations the mbed drive is not visible from the PC. The drive name
will change from mbed to "removable drive" as shown in the next Figure. This is a
normal phenomenon. If you need access to the mbed anyway - for example because you
want to download a new program while this one is still running - simply hold down the
reset button, and keep it down. The mbed will stop running and thus the file system will
become visible again.
174 175
int c;
do {
c=
pc.p
wai
} while
Of course we a
The name of th
"MYDATA.TX
#includ
LocalFi
Figure 124. Mbed invisible during local file operations. Serial p
In the previous example the mbed read lines of text and sent them to the PC. Of course it int main
is also possible to read numbers. In the free download file you will find a file called FILE
MYDATA.TXT in the directory labeled 10.1. Copy that file to the mbed, but do not press
the rest button just yet. In case you are wondering why the file name is in capital letters: if(!fp
this file was written by the mbed itself. pc
}
Of course we still need to take the same steps:
int c;
1. Declare the file system. do {
2. Open the file. c=
3. Read from the file. pc.p
4. Close the file. wai
} wh
This time however step three is different because we do not want to read a certain "line"
or a certain number of string characters, but a single number. For this we use the "fgetc" fclos
command. This command will read every single character in the file, including the EOF -
the End Of File marker - that your Windows operating system has added to the file. This pc.pr
marker is necessary because without it software such as the Windows operating system }
would have no idea where a file ends. So contrary to the previous program this time we
need to read until the EOF marker is encountered.
175
176 176
int c;
do {
c = fgetc (fp);
pc.printf("%d\n\r", c);
wait(1);
} while (c != EOF);
As you can see the program will print every character, including EOF, but it will also use
EOF to exit the "do" loop. A do loop is selected because we need to read int "c" first
before we know if it is the EOF, so the file read operation has to be executed at least
once.
Of course we also need to change the "file open" command to reflect the new file name.
The name of the file is not case sensitive because to Windows "mydata.txt" is identical to
"MYDATA.TXT".
#include "mbed.h"
LocalFileSystem local("local");
Serial pc(USBTX, USBRX);
int main() {
FILE *fp = fopen("/local/mydata.txt", "r");
if(!fp) {
pc.printf("File not found\n");
}
int c;
do {
c = fgetc (fp);
pc.printf("%d\n\r", c);
wait(1);
} while (c != EOF);
fclose(fp);
pc.printf("\n\rDone\n");
}
176 177
If you run this program - with mydata.txt present on the mbed of course - the numbers 1 In this example
to 9 will be listed in HyperTerminal. The row will be terminated with -1, which is the following progr
EOF marker that is printed too. See section 9.4 for a fun application of this technique.
#includ
LocalFi
int main
FILE
int i;
for (i
fpu
}
fclos
}
int i;
for (i=1;i<20;i++) {
fputc ( i , fp ); 43
When you try
}
char [13]" cann
"/Tutorial/main.c
177
178 178
In this example a counter, counting from 1 to 19, is written to file fp. This results in the
following program.
#include "mbed.h"
LocalFileSystem local("local");
int main() {
FILE *fp = fopen("/local/mydata2.txt", "w");
int i;
for (i=1;i<20;i++) {
fputc ( i , fp );
}
fclose(fp);
}
When you close the file, using fclose(), the EOF marker is added automatically to the end
of the file.
It is not very likely that you will want to write text files with your mbed but just in case a
here is a small program for that as well.
Text can be written to a file using the "fprintf" command. This command works in a
similar way to the "printf" command except that this time a filename has to be specified.
Note the sequence of "\r\n". They have to be in this order otherwise Windows will not
recognize them as carriage return and new line characters within a file.
You can also prepare an array first and then print it. The array has to be declared one digit
larger than the text. This is because an invisible end-of-array character is added. If you
make the array too small you will get a very mysterious error message from the
compiler.43
43
When you try to declare the array with length 12 the error message is: "A value of type "const
char [13]" cannot be used to initialize an entity of type "char [12]" (E144)" in file
"/Tutorial/main.cpp"
178 179
function is show
char i[13]="and this too"; will return, "inb
fprintf (fp, "%s",i); the function req
fclose(fp); 1
When you run this program a file MYFILE2.TXT will be created on the mbed drive with
the following content:
f
This is a line of text, r
}
and this too
10.2 Functions
A function is a piece of code that can be called from anywhere within the program and 4. ... as a f
performs a certain task, or function. It is so to speak a group of commands that does
something useful.
A lot of functions are standard to the C language. For example printf is a function. When
If we call this
called it will print a series of character to for example HyperTerminal. In order to do that
variable "questi
a whole series of commands are executed. You will not see any of that because these
as an answer.
commands are part of the mbed library.
"threetimes" fun
The interesting thing about this is that you can make your own functions. This way you
can expand the power of C, and the power of the mbed libraries. The general format of a
179
180 180
function is shown below, where "outboundtype" is the type of variable that the function
will return, "inboundtype and variable name" is the name of the variable with its type that
the function requires, and "name" is the name of the function.
Do not worry, it is much easier than it appears. Take a look at this function:
The function is called "threetimes". It expects to be called with a float variable, which
inside the function will be referred to as "question". It will then multiply that float by
three, and return the answer as a float. The steps are shown in the next Figure as 1 to 4.
4. ... as a float.
180 181
To try this function enter the following program, and run it with HyperTerminal running
on the PC. As hardware simply use the mbed with a USB cable to the PC. float ad
return
#include "mbed.h" }
Beware that va
cannot use it a
function as well
Of course you c
any variables. I
Figure 127. The result of the "threetimes" function. write of the pr
directly to the U
The previous Figure shows that we did indeed get the expected answer.
void ad
We can pass as many variables to a function as we want just as long as they are all listed float
in the declaration. As an example we make a function called "add" that adds two float answ
variables together and returns the answer. pc.p
}
float add(float var1, float var2) {
return var1+var2; To test this func
}
#includ
You can test this function with the following program, which will print 10.000000.
Serial p
#include "mbed.h"
void ad
Serial pc(USBTX, USBRX); float
181
182 182
int main() {
pc.printf("\n\r Answer %f",add(7,3));
}
Inside a function you can declare and use other variables as well. These variables will
only be known inside that function, hence they are called "local variables". This is a re-
write of the previous function, this time with a local variable.
Beware that variable "answer" is known only inside this particular function, so you
cannot use it anywhere else. In fact you could declare a variable "answer" in another
function as well. Even though they have the same name they are not the same variables.
Of course you can also have a function that doesn't return a value, or that doesn't require
any variables. In that case you can use the word "void" instead of a type. This is a re-
write of the previous function, but this time it doesn't return the answer but prints it
directly to the USB connection.
#include "mbed.h"
182 183
183
184 184
Since the compiler will read the code from the top down, a function should be declared
before it is used, otherwise the compiler will issue an error "Identifier not defined" with
the name of your function.
Variables defined inside "main" are local to that function. That means that a variable
cannot be used in any other function. If you want to use variable "everywhere" you can
declare them in the same section where you declare pins and the like. Those variables are
called global variables. 44
#include "mbed.h"
float answer;
int main() {
add(7,3);
pc.printf("\n\r Answer %f",answer);
}
In the previous example variable "answer" is declared as a global variable. That means it
is known in all functions of this program. The add function puts a value in answer - the
sum of var1 and var2 - but doesn't do anything else. The main function simply prints
answer, which by now contains the value that the add function put in.
In this book we do not use many custom made functions because the book is geared
toward beginners.
A ticker is a mechanism to stop a running program momentarily, and then run a special
function. Once the special function is completed the normal program resumes.
44
In general it is better to use local variables and pass them to a function as a parameter. This way
you can easily copy your functions to other programs without having to wonder if you need to
copy any global variables too in order to make your function work.
184 185
The next step is to define functions for each ticker. The syntax for these functions is: flipLED
flipLED
void functionname(){
your commands Now all we ne
} command becau
while(1
45
wa
The ticker interface uses the ARM timer 3.
185
186 186
All these functions need to do is change the state of their respective LEDs. If the LED is
on then switch it off, and if it is off the turn it back on again. Since LEDs do not have
coils or capacitors and the frequency is quite low so we can use the NOT operator.
void flip1() {
myled1 = !myled1;
}
void flip2() {
myled2 = !myled2;
}
Note that the functions themselves contain no timing information. The next step is to
connect the tickers to the functions. This is called attaching. The following table shows
which commands are available once a ticker has been declared. Detaching basically
means that the ticker is not doing anything anymore.
Command Description
Attach a function to be called by the Ticker,
attach
specifying the interval in seconds.
Attach a function to be called by the Ticker,
attach_us
specifying the interval in microseconds.
detach Detach the function.
The design flash speeds of the LEDs are in seconds so we can use attach. The syntax is
In this command "tickername" should match with the Ticker previously declared and
"functionname" must match with the functions previously defined. Note the ampersand
for the function because this command requires a pointer. The interval is in seconds.
flipLED1.attach(&flip1, 2.1);
flipLED2.attach(&flip2, 0.61);
Now all we need is a loop for the third LED to flash. We can use a simple wait(4.2)
command because the tickers will interrupt that wait function as needed.
while(1) {
wait(4.2);
186 187
The hardware for this project is the mbed itself, connected to the USB port.
The relay is rat
calculate the cu
deliver 40 mA t
Contact
187
188 188
The mbed can deliver 40 mA on a pin. That is enough to light a LED or a servo, but not
for components that consume more power. In this section we will discuss three methods
to control more power with the mbed.
Another type of relay is a "solid state" relay that has no moving parts inside. This
component is not really a relay but a set of components in a single package that performs
a function similar to that of a normal relay. Since it contains no moving parts it is less
affected by wear and tear and physical shocks, but since the low and high voltage circuits
are not completely separated an important relay safety feature is lost.
In this project we will use a Meder reed relay type DIP05-1A72-12L. Inside is a set of
contacts in a glass tube. These contacts are the switch. A coil is wrapped around the tube.
When the coil is energized a magnetic field is build up inside the glass tube which causes
the contacts to attract each other, and thus close the switch. Unfortunately you will not
see any of this because the relay is completely enclosed. These are the technical data
according to the manufacturers datasheet:
Coil: 5 volts DC
500 ohm
50 mW
The relay is rated for 5 volts but it will also work at 3.3 volts. Using Ohm's law we can
calculate the current at 3.3 volts I = V / R = 3.3 / 500 = 6.6 mA. Since the mbed can
deliver 40 mA this is within the design specification.
188 189
The maximum voltage is 200 volts. Depending on where you live this may be enough to
switch mains - in 110 volts mains regions - or just too little - in 240 volts mains regions.
In this project we will use the relay to control a LED. This is for demonstration purposes
only because the mbed is perfectly capable of controlling a LED all by itself.
The relay contains a coil. The current through a coil is persistent. That means that if the
power is disconnected the current keeps flowing for a very short moment. This is caused
by the collapse of the magnetic field. As a result the voltage over the coil reverses and
may become very high. This voltage spike can seriously damage the microcontroller. The
solution is to use a protection diode over the coils of the relay. This diode is mounted
"backwards" so that it doesn't interfere with the normal operation but solely takes care of
the reversed voltage spike. For this purpose we use a 1N4007 which has a maximum
reverse voltage of 1000 volts (in our circuit it only gets 3.3 volts) and can handle a
current of 1 A with a maximum surge current of 30 A. More than enough for our
application.
Vout
(3.3 V) This project is
straightforward
LPC1768 p20 2 14
relay #includ
GND 6 8
DigitalO
220
1N4007
int main
LED while
rel
wa
Figure 129. Relay flasher schematic. rel
wa
When you build this project note that the numbering of the relay deviates from the }
numbering of microcontrollers. The numbers start in a different corner and go around in }
the opposite direction.
Remember that the diode needs to be mounted "in reverse", so the white band must be on 10.4.2 Transis
the mbed side. Make sure to check this before powering the circuit, because if the diode is
mounted incorrectly it will short-circuit the mbed.
A transistor is
Transistors are
example contain
low currents as
189
190 190
This project is meant to demonstrate the use of a relay so the program itself is
straightforward.
#include "mbed.h"
DigitalOut relay(p20);
int main() {
while(1) {
relay = 1;
wait(1);
relay = 0;
wait(1);
}
}
190 191
regarded as a "road" between pin c and pin e, and a "barrier", connected to pin b - see the In addition to sw
next Figure. The barrier is normally closed, so no current can flow between c and e. device, simply
When a suitable voltage is applied to pin b the barrier will open and current can flow mbed and the p
freely between c and e. What a suitable voltage for pin b is depends on the type of
transistor. To keep the barrier open a small current will flow through pin b as well. How NPN is the type
small this current is depends on the type of transistor, in any case a current limiting using a "1" fro
resistor is required (called RB in the next Figure). The letters b, c and e stand for base, proper NPN tra
collector and emitter respectively.
1. The max
+V
collector
S current c
e
3. Select a
0V
12.5 that
note of i
Figure 131. Basic NPN transistor connection schematic.
4. Calculat
using the
In this project we want to use a 10 volts 0.2 A lightbulb and control the brightness using
PWM. Both voltage and current are way over the specifications of the mbed, so we will
use a transistor. RB =
Using a transistor is quite simple, but selecting the right type is a bit more complicated. where Vc
The method described here was devised by John Hewes of the Kelsey Park Sports delivers.
College Electronics Club.46
In a simp
There are two basic types of transistors: NPN and PNP. An NPN transistor will conduct the same
when a small positive voltage is applied to the base, which in microcontroller terms is a
"1". 47 Only a very small current is required, because the transistor can amplify the RB =
current.
5. Choose t
for RB.
46
Used in adapted format with permission from the author. For more information see the website If the load
http://www.kpsec.freeuk.com/index.htm motor) you
47
Here is an easy to remember rule of thumb applicable to any electronic component: when shown dotted
conducting, the arrow in the symbol always points to the ground lead.
191
192 192
In addition to switching and amplifying current, you can also increase the voltage to your
device, simply by connecting the transistor to a higher voltage. The ground wires of the
mbed and the power source of the transistor must in that case be connected to each other.
NPN is the type you will be using most, because it seems logical to switch the device on
using a "1" from the microcontroller. The following steps will help select and use the
proper NPN transistor:
Vc * hFE,min
RB = 5 * Ic,max
RB = 0.2 × RL × hFE,min
192 193
6. Since the m
The PNP type works just the opposite way, where the transistor will conduct when the cannot use
base is connected to ground - low in microcontroller terminology. Since this is less
intuitive from the mbed point of view (you would expect something to go on when you Vc
make a pin high) you will not use a PNP type very often. RB = 5 *
0V
To clarify this, let’s take a look at a practical application. We want to run a 10 V 0.2 A
7RFODULI\WKLVOHW¶VWDNHDORRNDWDSUDFWLFDODSSOLFDWLRQ:HZDQWWRUXQD9$
light bulb from a microcontroller and use PWM to vary the light intensity. The power
10k
consumption of thethe light
lightbulb
bulbbulb is much
is five timeshigher
what than the can
the pin pin can handle
handle so asotransistor
a transistor
is
is required.
required.
1. The light bulb uses 200 mA, so the transistor needs to have an I c max of at least 200
mA.
3. The maximum current that the mbed can deliver is 40 mA, so the transistor needs a
hFE of at least 5 * 200 mA / 40 mA = 25.
The 9 volts pow
4. The transistor will be connected to the PWM pin so it is probably a good idea to Figure.
select a fast one, such as one designed for audio applications.
5. In the appendix (section 12.5) a small selection of transistors is listed with key
variables. From this list we choose the BC547B with Ic,max = 500 mA and hFE,min =
200.
193
194 194 194
6. Since the microcontroller and the light bulb will be run off different voltages we
cannot use the simplified formula so we use the normal formula instead.
In the hardware schematic the connections of the transistor are also shown. The
maximum voltage on the mbed is 9 volts, so if we want to run the lightbulb off 10 volts
we need two separate power supplies, one for the mbed and one for the lightbulb. Since
the lightbulb will be bright enough at 9 volts too we chose the easy way out and connect
everything to a 9 volts external power supply.
e
Vout
(3.3 V)
b
c
LPC1768
10k
p20 Vin + 9V
c
b
270 BC547B
e
The 9 volts power wires are on the left side right below the USB connector in the next
Figure.
194 195
We have alread
small electric m
Pr
Cu
V
D
Re
D
#include "mbed.h"
AnalogIn mypot(p20);
PwmOut bulb(p21); In the pin layou
mbed is connec
int main() { The voltage on
bulb.period_us(90); VDD. The maxi
while (1) { volts. The sam
bulb = mypot.read(); ground of the p
} TC4427A then
} 8 are NC, whic
shown in the ne
10.4.3 Mosfet driver electric candle
Mosfets are electronic components much like transistors. Power mosfets require a
minimum voltage of 4 to 10 volts on pin b - in mosfets this pin is called the "gate" - to
start conducting. In order to achieve that voltage mosfet drivers may be used. In this book
we use the mosfet drivers too, but not to drive mosfets but to control other things, such as
motors or a light bulb.
195
196 196
We have already discussed this technique in section 7, and used a TC4427A to drive a
small electric motor.
In the pin layout in the previous Figure pin 7 - out A - is controlled by pin 2 - in A The
mbed is connected to pin 2, so that pin is 3.3 volts - or 0 of course when then pin is off.
The voltage on pin 7 depends on the power supply of the TC4427A, pin 6, also called
VDD. The maximum voltage on that pin is 18 volts, in which case pin 7 will also be 18
volts. The same applies of course to pins 4 and 5. Pin 3 needs to be connected to the
ground of the power supply. If you use a different power supply for the mbed as for the
TC4427A then the grounds of both supplies must be connected to each other. Pins 1 and
8 are NC, which stands for Not Connected. So in principle the TC4427 is connected as
shown in the next Figure.
196 197
int main
float
candl
mbed control signal
while
c=
TC4427A if (
}
Figure 137. Voltages and connections for the mbed with a TC4427A mosfet driver. if (
In this project we will use the mosfet driver to control the same lightbulb - 10 volts 0.2
amperes - from the previous project. }
if (
The electric candle is actually a light bulb that constantly changes in brightness, causing a
candle-like flickering effect. We do this by connecting a small bulb to the PWM pin and
adjusting the duty cycle abruptly at random times. }
if (
Chance Random range Effect
10 % < 10 Slow flicker "minor draft"
}
10 % 10 to 20 Almost off "gust of wind" }
30 % 20 to 50 Slight flicker "draft" }
50% > 50 Steady
If you feel the f
Note that for the ranges the double ampersand is used for this is a logical condition and your own needs
not a mathematical equation that needs to be solved. To determine the chance the
command The maximum
volts we need t
c = rand ()%100; Since the lightb
connect everyth
is used, which will yield a "random" number between from 0 to 99. For the PWM period
the same period as for the motor in section 7 is used.
#include "mbed.h"
PwmOut candle(p21);
197
198 198
int main() {
float c;
candle.period_us(90);
while (1) {
c = rand()%100;
if (c<10) {
candle=0.8;
wait(0.015);
candle=0.6;
wait(0.015);
candle=0.86;
wait(0.015);
}
if (c>=10&&c<20) {
candle=0.2;
wait(0.025);
}
if (c>=20&&c<50) {
candle=0.8;
wait(0.1);
}
if (c>=50) {
candle=1;
wait(1);
}
}
}
If you feel the flickering is too much (or not enough) you can modify the program to suit
your own needs.
The maximum voltage on the mbed is 9 volts, so if we want to run the lightbulb off 10
volts we need two separate power supplies, one for the mbed and one for the lightbulb.
Since the lightbulb will be bright enough at 9 volts too we chose the easy way out and
connect everything to a 9 volts external power supply.
198 199
10.5 Learn
LPC1768
Vin + 9V
So far the pr
leave room f
GND p21 program: a s
2 In 1995 an
3 TC4427 6 pigeons to d
previously a
7
switch, but o
10 V / 0.2 A
pecked comp
painting was
In this projec
The microco
Figure 138. Electric candle schematic.
happens the
The breadboard looks very cozy. A good idea would be to use a rolled up piece of paper Eventually th
as a surrogate candle and mount the bulb on top. The whole thing can then be placed itself to pick
inside a Christmas ornament.
The program
program is
identical, so
brains howev
answer migh
question is: d
Because this
position that
inner workin
between biol
In this proje
done by dra
48
This progra
bring your mi
PIC microcon
Figure 139. Electric candle in operation on a breadboard. further study.
beginners.
49
Watanabe,
Picasso", Jour
199
200 200
So far the programs that we wrote did exactly what we wanted them to do, we did not
leave room for interpretation. In this section we will discuss an entirely different kind of
program: a self-learning program. The program will learn, based on user input.48
In 1995 an article by Watanabe was cause for commotion. It appears he had trained
pigeons to distinguish the difference between paintings by Picasso and Monet, a feat
previously assumed to be impossible. 49 The pigeons received a reward if they pecked a
switch, but only if a painting by Picasso was shown at the same time. Initially the pigeons
pecked completely at random. After a while however they stopped pecking if a Monet
painting was shown, and only pecked if a Picasso was shown.
In this project a yellow and green LED are switched on at random by a microcontroller.
The microcontroller can be "rewarded" for its choice of color by pressing a button. If that
happens the microcontroller will be more inclined to select that particular color.
Eventually the microcontroller will learn that you like this color best, and therefore limit
itself to picking just this one color.
The program learns in the same way the pigeons did in the research. Does that mean the
program is artificially intelligent? The behavior of the program and the pigeon is
identical, so from that point of view one might answer this question with "yes". Pigeon
brains however work totally different than our program, so from that point of view the
answer might be "no". However, nobody knows how pigeon brains work, and the
question is: does it matter?
Because this is a book on microcontrollers and not on philosophy we will take the
position that a program that behaves intelligently is in fact intelligent. The difference in
inner workings between the brain and the software will be regarded as the difference
between biological and artificial intelligence.
In this project a microcontroller randomly switches a yellow or green LED on. This is
done by drawing a random number. If the result is smaller than a threshold - called
48
This program, and many others like it, can be found in "Artificial intelligence - 23 projects to
bring your microcontroller to life" by the same author, ISBN 978-0-905705-77-4. The book uses
PIC microcontrollers and programming language JAL, and has a lot of footnotes to allow for
further study. We have decided to leave the footnotes in, even though this is unusual in a book for
beginners.
49
Watanabe, S., Sakamoto, J., & Wakita, M.: "Pigeon's discrimination of paintings by Monet and
Picasso", Journal of the Experimental Analysis of Behavior 63 (1995), pp. 165-174
200 201
"choice" - than the yellow LED will be switched on, if the result is equal to or larger than
the threshold the green LED will be switched on. char cho
if (button) { // w
// reward received, encourage the current behavior for
if ((yellowled) && (choice <= 10)) choice = choice + 1;
if ((greenled) && (choice > 0)) choice = choice -1;
If you press the button while the yellow LED is on the value of choice is increased by
one. This means that in this part of the program
The result of repeated adaptations of choice is that the microcontroller learns that you like Build the hardw
this color best, and for that reason only switches on this particular LED.
#include "mbed.h"
DigitalOut yellowled(p22);
DigitalOut greenled(p21);
DigitalIn button(p20);
201
202 202
char choice=5,select;
int main() {
while (1) {
if (button) {
// reward received, encourage the current behavior
if ((yellowled) && (choice <= 10)) choice = choice + 1;
if ((greenled) && (choice > 0)) choice = choice -1;
202 203
LED LED
common name f
220
220
Let's assume th
them is equally
look like the wh
if you spin the w
Figure 140. Schematic of the learning project.
50
50
James E. Bake
the Second Intern
Figure 141. Project on a breadboard. 14-21, 1987.
51
51
Bert
Bert van
van Dam,
dam,
KIJK magazine.
203
204 204
When you run the program the green and yellow LED will be switched on at at random.
random.
Select a color, and press the button when that particular LED is lit. Every time that this
happens the probability of that LED being lit is increased. Keep "rewarding" the
microcontroller and eventually the other LED will never go on. The microcontroller
microcontroller has
has
learned your favorite color.
The results of this program are quite impressive, so lets look at the theory behind this
project. The technique used for the ARM brain is called Roulette wheel. Roulette wheel
selection is a technique that is used to make decisions mainly in the field field of
of Genetic
Genetic
Algorithms. The official name is stochastic sampling with replacement.50 50
This technique
is also very suitable for designing self-learning programs. 51
51
Roulette wheel is of course an
incorrect term because roulette is the French word for a (small) wheel. It is however the
common name for this technique so we will use it too.
A B
B
C
If for some reason section A would be made smaller then choice A would
would be
be made
made less
less
often, but choice B and C would be made more often. So by changing the size of the
section for a particular option, the probability of that option being selected is also
influenced. This sounds very obvious, and of course it is. But it does
does mean
mean that
that the
the
decision making process can be influenced in an extremely simple way. All you need to
do is assign a value to each option that is equivalent to the size of the section on the
50
50
James E. Baker. Reducing Bias and Inefficiency in the Selection Algorithm, in Proceedings of
the Second International Conference on Genetic Algorithms and their Application (Hillsdale), pp.
14-21, 1987.
51
51
Bert
Bert van
van Dam,
dam, Self-learning wall avoider, Artificial Intelligence and Machine Learning, 1999,
1999,
KIJK magazine.
204 205
205
roulette wheel for that option. If you increase the value, you also increase that probability }
of selection.
// s
With a few small modifications to the program you can see this process in action. All we gre
need to do is add USB support and print the variable choice, as well as the random ye
number that was drawn. pc
wa
#include "mbed.h" }
}
DigitalOut yellowled(p22);
DigitalOut greenled(p21);
DigitalIn button(p20);
Serial pc(USBTX, USBRX);
char choice=5,select;
int main() {
pc.printf("\x1B\x48\x1B\x4A");
pc.printf(" ---===[ Learning program ]===--- \n\r");
while (1) {
if (button) {
// reward received, encourage the current behavior
if ((yellowled) && (choice <= 10)) choice = choice + 1;
if ((greenled) && (choice > 0)) choice = choice -1;
The previous F
// wait for the user to release the switch yellow. Once t
while (button) wait(0.01); your favorite co
} be used to puni
wait(0.01); but opposite to
205
206 206
The previous Figure shows the results of an actual run. The favorite color of the user is
yellow. Once the microcontroller has learned this, there is no mechanism to "unlearn"
your favorite color. This can easily be added by installing a "punishment" button that can
be used to punish the microcontroller for its selection by influencing the variable choice,
but opposite to the other button.
206 207
Note that just like with children inconsistent rewarding/punishing will not lead to useful #includ
results.
PwmOu
10.6 The blue LEDs of death int main
bulb.
Before you read on with this section built the following hardware. bulb
}
So what just ha
LEDs starting f
LPC1768
p19 GND
LED
220
In order to find
on the mbed. T
you receive an e
Then enter this program, predict what you expect to see, and then run it.
207
208 208
#include "mbed.h"
PwmOut bulb(p19);
int main() {
bulb.period_us(90);
bulb = 0.5;
}
So what just happened? Instead of the LED being lit at about 50% the four build-in blue
LEDs starting flashing in this pattern:
This is called "the blue LEDs of death". It is named after the "blue screen of death" that
Windows displays when it has encountered an unrecoverable error. Whenever you see
this pattern on the LEDs it means that even though the program compiled ok - and
apparently doesn't contain any syntax errors - there is still something horribly wrong with
it.
In order to find out what when wrong start HyperTerminal. Then press on the reset button
on the mbed. The blue LEDs of death appear again - obviously - but in HyperTerminal
you receive an error message.
208 209
This message means that there is something wrong with the pin assignment. Note that the pr
care of autom
HyperTerminal
#includ
PwmOu
int main
bulb.
bulb
wait(
error
}
Do remember t
entire message
printed.
Figure 147. The Pulse Width Modulation pins on the mbed.
In our example the problem is easy to find: pin 19 is not a PWM pin at all. C will accept
this pin as input to the PwmOut function because technically it is not a syntax error. The
mbed itself however has no clue what to do with this command.
The solution is simple: change p19 to p21 in both hardware and software and the program
will run as expected.
You can use the blue LEDs of death in your own programs as well, and on purpose. Let's
say your program has to perform a certain task. When something goes wrong with that
task you want to alert the user. Of course you could flash a LED manually but you can
also use the "error" command with a custom error message.
Command Description
Output error message x (in "printf format") to the
error(x) USB port - if available - and exit the program
with the blue LEDs of death.
This is an example of a program that uses the error command to print a message to
HyperTerminal. It will light a LED connected to pin 21 at about 50% brightness for three
seconds and then enter the fatal error mode and display the custom error message.
209
210 210
Note that the program doesn't need to declare USB pins for this to work, this will be taken
care of automatically - assuming of course the USB cable is connected and
HyperTerminal is running.
#include "mbed.h"
PwmOut bulb(p21);
int main() {
bulb.period_us(90);
bulb = 0.5;
wait(3);
error("My message \n");
}
Do remember to add "\n" to the string. This flushes the USB buffer ensuring that the
entire message is printed. If you forget this then only chunks of 16 characters will be
printed.
210 211
This book is the first book in a series of three about ARM microcontrollers. The next
book will deal with projects and techniques for intermediate users, and the last book will
be for experts. We will discuss lots of interesting projects in those books such as internet
connections, camera vision and how to take projects into commercial production. This
means we will not limit ourselves to the mbed but discuss other ARM microcontrollers as
well.
212 213
12 Appendix wa
}
}
This is the reference guide part of the book. You can use this section to check for
example the syntax of C commands or mbed functions. Examples can be found It is considered
throughout this book using the index. program does, a
#includ
12.1 C language reference
General // give t
DigitalO
This C language overview is not an extensive listing of all possible commands and
int main
options. Instead we will only discuss the part of the language used in this book. That
while
means we will skip several of the more advanced features, but the overview will match
// f
with what you have learned in this book.
my
wa
A typical C program starts with an include of the libraries that we want to use.
my
wa
#include "mbed.h"
}
}
The next step is to define the global variables, constants and pins that will be used
Binary
DigitalOut myled(LED1);
Normally speak
Then we list the functions that will be used in the program but are not part of the libraries
and thirty-five.
we use, if any. Inside each function local variables may be declared.
have a different
and represents f
void add(float var1, float var2) {
right) and repre
float answer;
You are as it w
answer = var1 + var2;
whereas you wi
pc.printf("\n\r Answer %f",answer);
}
position
The main function is the entry part of the program. This is the first function that the multiplier
microcontroller will execute. In this function local variables can be declared.
This is called th
int main() { ten:
float i;
while(1) { position
myled = 1;
multiplier
wait(0.2);
myled = 0;
wait(0.2);
}
}
It is considered good practice to add comments to the program that show what the
program does, and what it is intended for. So a complete program could look like this.
#include "mbed.h"
int main() {
while(1) {
// flash myled indefinitely
myled = 1;
wait(0.2);
myled = 0;
wait(0.2);
}
}
Binary
Normally speaking humans use decimal numbers. The number 135 means one hundred
and thirty-five. Actually it is just a list of three digits, but we have agreed that these digits
have a different meaning, depending on their position in the row. The 5 is at the far right,
and represents five. The 3 is on the second position (we start counting positions from the
right) and represents thirty. The 1 is on the third position and represents one hundred.
You are as it were using this table, except that computers see the first position as 0
whereas you will see it as 1.
position 3 2 1 0
multiplier times thousand times hundred times ten times one
This is called the decimal system, because the multiplication can be written in powers of
ten:
position 3 2 1 0
multiplier times 103 times 102 times 101 times 100
214 215
For computers counting with just two numbers is more convenient, 0 and 1, off and on, Another examp
low and high. This is called the binary system. two numbers fo
position 3 2 1 0
multiplier times 23 times 22 times 21 times 20
3 AND
In binary this is
0000 00
A logical opera
AND operator
true than the AN
The Windows c
An example of
conditions and y
It is very convenient if you can convert binary to digital and back by heart, but if math
isn't your forte you can also use the Windows Calculator which comes for free with
Windows. You must switch it to scientific mode (in Windows 7 in programmer mode) to
use these features.
Operators
There are basically two types of operators: mathematical and logical. An example of a The next table
mathematical operator is the "+" which means "add". Mathematical operators result in a have an identica
number.
215
216 216
Another example of a mathematical operator is &. This symbol, which means AND, adds
two numbers following the logic of the AND truth table.
The AND operation takes place on binary level with the full length of the variable. So if a
variable is defined a char the AND operation will be executed on all 8 bits. For example:
3 AND 7 = 3
A logical operator does not result in a number but in a true or false answer. The logical
AND operator is used to check two conditions at the same time. If both conditions are
true than the AND operator is true too.
The Windows calculator can perform mathematical operations like AND as well.
An example of a logical operator is &&. This symbol, which means AND, compares two
conditions and yields true or false based on the following truth table.
The next table shows a few examples of both logical and mathematical operators that
have an identical operator name.
216 217
Note that the "equal to" logical operator consists of a double "=" sign. A single "=" is a
mathematical operator. For example i=7 will give the variable i the value of 7.
Math
ope
The double sign is a logical operator. For example i==7 will result in true when i was 7
before this question was asked, and otherwise it will result in false. Remember that the
difference between a logical operator and a mathematical one is that the logical one will
result in either true of false and the mathematical one will result in a number.
The microcontroller will first check to see if i has value 7. If so it will increment i. Then it
will check again if i has value 7. This is no longer true so the program will continue.
Mathematical
Now take a look at this "while" statement:
In many C prog
while(i=7) i++; the case of cou
of i = i + 1. The
This statement contains the mathematical operator "=". So the first thing that the
microcontroller does is solve the mathematical operation: it will give i the value 7. Since
Abb
7 is equal to 7 the statement is regarded as "true". So the while statement is executed and i
is incremented. Then the mathematical operation is executed again, and i is given value 7,
at which point it is true again, ad infinitum. This is a very common mistake so beware.
52
Occasionally y
condition it mea
evaluate". You d
217
218 218
Mathematical
Description
operator
+ add
- subtract
= solve to
* multiply
/ divide by
% modulo
Mathematical abbreviations
In many C program mathematical calculations are abbreviated. This is most often used in
the case of counters that routinely are incremented by one using for example i++ instead
of i = i + 1. The next table shows the most common abbreviations.
52
Occasionally you may also encounter ++i. This means the same thing, however if you use it in a
condition it means "first evaluate then increment", while i++ means first increment and then
evaluate". You don't see ++i very often so we will not use it in this book.
218 219
The previous table shows some of the datatypes that we can use. In this context the word Pointers are us
"to" means "up to and including". The precision means that even though these variables around we leav
If someone asks
can just point at
53
The signed (positive and negative numbers) and unsigned (positive numbers only) indicator may
54
be omitted if it is shown between brackets. So a char is exactly the same as an unsigned char. There are two
Note that the default for char is unsigned but for short and int signed. variable, and to a
219
220 220
can hold very large numbers the precision is just 6 digits. Note that if you want decimals
you must choose either float or double, even if you use small values.
Pointers
When you declare a variable the microcontrollers reserves a part of memory where you
can store values, and gives that part of memory the name of that variable. So when you
declare a variable called "i" as an integer - using "int i" - a section of memory is reserved
and given the name "i".
Each location in memory has an address. A pointer doesn't hold a value, like a variable,
but it holds an address. So a variable is a memory location but a pointer is pointing to a
memory location - hence the name.
Lets say you live at 123 Walnut Street, you've put a sign on your house saying "The Nest"
and you have a family of four. The name of your house - the variable - is The Nest. The
number of people in your house - the value of the variable - is four. And the address of
your house - the pointer - is 123 Walnut Street.
If you have declared an integer called i then you can point to the memory location of i
using &i. So all you need to do is to preceed the variable with an ampersand. The scanf()
command for example expects a pointer to a variable rather than the variable itself. So
instead of using i we will use &i.
pc.scanf("%f",&i);
If you want to declare a pointer you need to use an asterisk (*) as a prefix. The next
command means that you have declared a pointer called ptri.
int *ptri;
ptri = &i;
Pointers are used because they save memory and time54. Rather than moving variables
around we leave them where they are and simply point to them. It is a bit like your house.
If someone asks you where you live you don't have to actually take her to your house, you
can just point at the address on a piece of paper and say "there".
54
There are two other, more advanced, reasons: to allow functions to "return" more than one
variable, and to allow dynamic memory allocation for arrays.
220 221
Array }
A variable can hold a single value. If you need more values you can use an array. An The while com
array is basically a whole series of values that are all assigned to the same name. In order brackets is true
to keep them apart an index is used. program encoun
so then the co
int myarray[3]; condition again
while the cond
The previous statement declares an array with the name "myarray" that can hold three while command
numbers. Each number has a different index, starting with zero. It is important to note
that computers start counting at zero, and not at one like we do. So if you declare an array This is an exam
for three numbers they will be indexed 0, 1 and 2. Values can be assigned to the since 1 is true
individual positions by referring to that index, for example if value 12 has to be assigned executed foreve
to index 0:
while(1
myarray[0] = 12; code
}
Optionally you can assign the values "in one go" if you do so during declaration. For
example: If the code secti
Arrays are also used to store strings - also called text. The principle is the same but rather Do
than separate letters you can enter the entire text in quotation marks and the type has to be
char. The "do" comm
syntax:
char myarray[17] = "This is a string" ;
do{
A string array has to be declared one digit larger than the text. This is because an invisible code
end-of-array character is added. If you make the array to small you will get a very } while
mysterious error message from the compiler.55
The difference
While executes the co
other way aroun
The "while" command has the following syntax: so you need to r
221
222 222
The while command will execute the code section as long as the condition between
brackets is true. This condition will be checked at the beginning of each loop. So if the
program encounters the while command it will first check to see if the condition is true. If
so then the code section is executed. Once completed the program will check the
condition again. If it is still true the code will yet again be executed. This will continue
while the condition is true. As soon as the condition is false the program will skip the
while command and jump to the next command in the program.
This is an example of the while command that is used very often. The condition is 1, and
since 1 is true this means that the condition is always true. The code will therefor be
executed forever.
while(1) {
code
}
If the code section contains just a single command the braces may be removed.
while(condition) command;
Do
The "do" command is almost identical to the while command and has the following
syntax:
do{
code
} while(condition);
The difference is that the do command will execute the code at least once, because it first
executes the code and only then checks the condition. The while command does this the
other way around. You can use the do command if the condition is dependent on the code
so you need to run the code before the condition can be checked.
If the code section contains just a single command the braces may be removed.
do command;
while(condition)
222 223
If-then For
The if-then command - also referred to as the if-then-else command - has the following The "for" comm
syntax:
for (sta
if (condition){ co
code if condition is true }
}
else{ What this mean
code if condition is false all the comman
} commands and
If the condition is true then the first set of code is executed, else - meaning the condition This is an exam
is false - the second set of code is executed.
for (i=0
It is possible that you do not need the "else" part. In that case you can omit it: co
}
if (condition){
commands if condition is true We begin with t
} or in this case 0
are executed an
If the code section contains just a single command the braces may be removed. still true we are
then commands
if(condition) command; smaller than 2
next commands
Or if you need the else part as well:
You could read
if(condition) command; each loop until
else other command;
Wait
This is an example of an if-then command that switches a LED on for 5 seconds when a
button is pressed: The "wait" com
if (button) { wait(sec
myled = 1;
wait(5); The delay is e
myled=0; minimum delay
}
223
224 224
For
What this means is: beginning with the start situation, as long as the condition is true do
all the commands and then take the action. If the condition is still true do all the
commands and take the action. Keep on doing this until the condition is no longer true.
This is an example.
for (i=0;i<2;i=i+1){
commands if condition is true
}
We begin with the start condition, so i=0. Then we check if the condition is true, so if i<2,
or in this case 0<2. Since 0 is indeed smaller than 2 the condition is true so the commands
are executed and the action is taken. The action is i=i+1, so i is now 1. If the condition is
still true we are to do all commands and then the action again. Since 1 is smaller than 2
then commands are executed again, and the action is taken, so i is now 2. Since 2 is not
smaller than 2 the for command is now finished and the program will continue with the
next commands.
You could read this command "for (i=0;i<2;i=i+1)" as "starting at zero increment i at
each loop until i is no longer smaller than 2".
Wait
wait(seconds)
The delay is expressed in seconds, with a maximum of 6 decimals. That means the
minimum delay is wait(0.000001) which takes 1 10-6 seconds or 1 uS.
224 225
The general format of a function is shown below, where "outboundtype" is the type of
variable that the function will return, "inboundtype and variable name" is the name of the This section co
variable with its type that the function requires, and name is the name of the function. by no means an
all declarations
outboundtype name(inboundtype and variablename){
commands Timer
}
A timer is basic
For example: normal stopwat
can have its ow
float threetimes(float question) {
return question*3; Timer t
}
The previous s
The previous function is called "threetimes". It expects to be called with a float variable, following comm
which inside the function will be referred to as "question". It will then multiply that float
by three, and return the answer as a float. The steps are shown in the next Figure as 1 to 4. Command
t.start()
1. call the function with a value, t.reset()
for example threetimes(3) ... t.stop()
t.read_us()
t.read_ms(
t.read_s()
float threetimes(float question){
return question*3; Note that if you
} 2. ... the function will call this value "question"
and use it in the calculation ...
Ticker (Timer
3. ... and return the answer ...
("question" multiplied by 3) A ticker is a m
function. Once
4. ... as a float.
Normally this f
Figure 151. How a function works. "hidden" inside
want. A ticker
alarm clock.
If we call this function as "threetimes(3)" the number 3 will be referred to as float
variable "question" inside the function. The calculation "question*3" will therefor have 9 56
For the exper
as an answer. This value will be returned, as a float, because the definition of the http://www.cplus
"threetimes" function is a float. 57
Note that 1 sec
58
The ticker inte
225
226 226
This section covers the sections of the mbed library that we have used in this book. It is
by no means an extensive listing, the library is much more powerful than this.56 Note that
all declarations are case sensitive, so for example timer is not the same as Timer.
Timer
A timer is basically a built-in stopwatch that can be started, stopped and read much like a
normal stopwatch. In the mbed we can use an "unlimited" number of timers. Each timer
can have its own name, just like a variable.
Timer t;
The previous statement declares a timer with name t. With this timer we can use the
following commands:
Command Description
t.start() Start timer t.
t.reset() Reset timer t to 0.
t.stop() Stop timer t.
t.read_us() Read the time of timer t in uS (microseconds)57
t.read_ms() Read the time of timer t in mS (milliseconds)
t.read_s() Read the time of timer t in S (seconds)
Note that if your timer is called mytimer than the start command is mytimer.start().
A ticker is a mechanism to stop a running program momentarily, and then run a special
function. Once the special function is completed the normal program resumes.
Normally this functionality is called a timer interrupt. In the mbed the timer interrupt is
"hidden" inside the ticker interface for ease of use. 58 You can use as many tickers as you
want. A ticker will interrupt a running program based on a certain timer, much like an
alarm clock.
56
For the experts: the libraries stdio.h, stdlib.h, string.h, math.h, time.h are also included, see
http://www.cplusplus.com/reference/clibrary/
57
Note that 1 second = 1,000 milliseconds = 1,000,000 microseconds.
58
The ticker interface uses the ARM timer 3.
226 227
Command Description or
The operator float functionality means that instead of a read() you can also perform a pc.putc
float read operation simply by referring to the analog pin name itself.
227
228 228
i = mypot.read()
or
i = mypot
Serial communications
A serial port must be created first. For example a port called pc using the USB connection
of the mbed.
Command Description
pc.putc() Write a character.
pc.getc() Read a character.
pc.printf() Write a formatted string.
pc.scanf() Read a formatted string.
pc.readable() Determines if there is something to read.
pc.writeable() Determines if it is possible to write.
pc.baud() Set the baudrate for the connection.
pc.format() Set the other communication properties.
Note that if your port is called for example myport than command to write a character is
myport.putc().
Writing a character requires a variable declared as int. Optionally you can send letters and
numbers if they are enclosed in single quotation marks. The next command will send the
+ sign over a connection called pc.
pc.putc('+');
228 229
In printf the following cursor control commands may be used. Note that the VT52 If you make the
commands can only be used if you are printing to an application that understands VT52, number, becaus
such as HyperTerminal with VT52 emulation enabled. number will be
zeros instead en
Cursor control Description Emulation
\b backspace Float
Print
\n newline Print
\r carriage return Print
\t tab
\x1B\x48 cursor home VT52 Pulse Width M
\x1B\x4A clear screen from cursor VT52 With PWM the
\x1B\x59\row\column go to location row,column59 VT52 and off rapidly
frequency of t
And the following format specifiers: character of its
constant, but va
Specifier Description Width Modulat
%d int, char
The next table s
%f float
%c character
Command
%s string
%u unsigned int PwmOut
write
Between the % sign and the "f" we can enter the total minimum length of the field, then a
point, and then the number of digits behind the decimal point. read
period
%6.2f
period_ms
2 period_us
123.45 pulsewidth
6
pulsewidth
pulsewidth
Figure 152. Formatting floats.
operator =
59
operator fl
Both row and column have an offset of 32, which means that you have to add 32 to the actual
row and column. If for example you want to go to location 1,12 you need to use (1+32),(12+32) so
33,44. Both row and column have to be entered in HEX.
229
230 230
If you make the total minimum field length too small the program will still print the full
number, because the filed length is the minimum value. If you make the field too long the
number will be printed with leading spaces. If you don't want leading spaces but leading
zeros instead enter a zero before the field length. For example:
Float 123.456789
Printf("%6.2f") 123.45
Printf("%8.2f") 123.45
Printf("%08.2f") 00123.45
With PWM the voltage remains constant - at the maximum level - but it is switched on
and off rapidly. The longer the on period the more power the consumer gets. If the
frequency of the pulses is high enough the consumer will not notice the pulsating
character of its power supply. We keep the frequency at which we give these pulses
constant, but vary the length, or rather the width, of the pulses. Hence the name Pulse
Width Modulation, abbreviated to PWM.
The next table shows the functions that you can use in relation to the PwmOut pins
Command Description
PwmOut Create a PwmOut connected to the specified pin.
write Set the output duty-cycle, specified as a percentage (float).
Return the current output duty-cycle setting, measured as a
read
percentage (float).
period Set the PWM period, specified in seconds (float).
period_ms Set the PWM period, specified in milliseconds (int).
period_us Set the PWM period, specified in microseconds (int).
pulsewidth Set the PWM pulsewidth, specified in seconds (float).
pulsewidth_ms Set the PWM pulsewidth, specified in milliseconds (int).
pulsewidth_us Set the PWM pulsewidth, specified in microseconds (int).
operator = An operator shorthand for write().
operator float() An operator shorthand for read().
230 231
Mathematics Command
There is a whole series of math functions available. The next table shows the most fputc ( i , n
important ones. fclose (nam
Of course ther
Local file system microcontroller
these instructio
The following table shows some of the commands related to the local file system - the problem. Witho
two MB drive on the mbed hardware. user is not able
231
232 232
Command Description
fputc ( i , name ) Write unsigned integer i to file name.
fclose (name) Close file name.
Random
The mbed uses a random number generator to produce pseudo random numbers. An
example to generator number from 0 up to and including 9 is:
c = rand()%10;
Function Description
rand() Generate a pseudo random number.
srand() Seed the random number generator.
This is a list of 100 numbers generated with rand()%10. It is not very obvious what
number will be generated after the last number 8
5 3 6 1 7 1 3 9 2 7 0
4 9 9 1 2 7 9 2 6 3 4
4 3 1 8 4 8 1 3 8 4 6
4 2 7 7 5 6 1 1 7 1 4
5 7 4 7 0 5 4 8 1 0 2
1 1 2 3 6 0 0 5 5 8 7
5 5 4 0 6 6 1 7 2 1 7
232 233
6 5 2 1 6 1 7 3 8 9 1 Command
4 1 4 2 1 6 9 9 8 8 8
error(x)
8
In case you are wondering, the next number was 4. 12.3 Mbed h
2. Check if all numbers are generated as often Most of the inf
datasheet. In th
The next Figure shows the distribution over the numbers 0 to 9 of the 1000 generated often.
pseudo random numbers. It would appear that each number is generated more or less the
same amount of time. Item
Maximum Vout
Figure 153. Distribution over the numbers 0 to 9 of 1000 pseudo random numbers.
So for practical hobby purposes the number generator does indeed generate random
numbers.
Error
This command can be used to make your own error messages. Make sure to terminate the
text with \n to force the USB buffer to be flushed.
233
234 234
Command Description
Output error message x ( in "printf format") to
error(x) the USB port - if open - and exit the program
with the blue LEDs of death.
234 235
235
236 236
236 237
237
238 238
3. Select a transistor from the table at the end Figure 155. NPN transistor
of this section that matches these criteria and
make a note of its properties Ic,max and
hFE(min)
Vc * hFE
RB = 5 * Ic
RB = 0.2 × RL × hFE
The PNP type works just the opposite way, where the transistor will conduct when the
base is connected to ground - low in microcontroller terminology. Since this is less
intuitive from the microcontroller's point of view - you would expect something to go on
when you make a pin high - you will not use a PNP type very often.
238 239
IC Case style
0V This is a diagra
this is a bottom
Figure 156. PNP transistor
BC179 PNP TO18 200mA 20V 180 600mW Audio (low noise) Maximum volta
BC327 PNP TO92B 500mA 45V 100 625mW Gen. purp.
TIP32A PNP TO220 3A 60V 25 40W Gen. purp. high power
TIP32C PNP TO220 3A 100V 10 40W Gen. purp. high power
239
240 240
Type
This shows the type of transistor, NPN or PNP. The polarities of the two types are
different, so if you are looking for a substitute it must be the same type.
Case style
This is a diagram showing the leads for some of the most common case styles. Note that
this is a bottom view, with the wires facing you.
IC max.
VCE max.
240 241
hFE
+1.
This is the current gain (specifically, the DC current gain). The guaranteed minimum
value is given because the actual value varies from transistor to transistor - even for those
of the same type!
Ptot max.
Maximum total power that the transistor can handle. Note that a heat sink will be required
to achieve the maximum rating. This rating is important for transistors operating as an
amplifier, where the power is roughly IC × VCE. For transistors operating as switches the
maximum collector current (IC max.) is more important.
Category
Chip Voltage
UA7805 5 volts
UA7806 6 volts
UA7809 9 volts
If you own a multimeter you may be better off building a variable power supply that can
handle a wide range of voltages. The next Figure shows a variable power supply that
delivers 1.2 to 13 volts. It will work perfectly for all projects in this book that need a
voltage other than 3.3 volts. In fact I use this myself. If you use a heat sink of about 10
cm2 this power supply can deliver a maximum of 1.5 A, more than enough.
The LM317 is
voltage drop w
63
Wall wart is el
electrical outlet.
241
242 242
470
100 nF + 100 uF
5 k LIN
0
Of course you need a multimeter to determine which position of the variable resistor
belongs to which voltage. If you put this project in a nice casing than you only have to
calibrate it once. This project is powered using a 15 volts DC wall wart.63 If you use a
different value you need to follow the explanation and change the other parts as
appropriate. If you want to use an AC wall wart you need to add a rectifier to turn it into
DC.
The LM317 is a 1.2 volts power regulator. That means that over the LM317 itself the
voltage drop will be constant at 1.2 volts. The maximum voltage we want to achieve is
63
Wall wart is electronic slang for a small transformer with a plug attached, that hangs off of your
electrical outlet.
242 243
about 13 volts, which should be possible with a 15 volts transformer. We will use a 5k
LIN variable resistor. That means the voltage drop over the variable resistor must be 11.8 Installation inst
volts (13 - 1.2), and thus the current through it 2.36 10-3 Amp.
1. Go to www
Vmax = 13 language to
Vvar = 13 - 1.2 = 11.8 v 2. Download t
Ivar = V/R = 11.8 / 5k = 2.36 10-3 Amps 3. Unzip the p
directory n
That current will not run through the LM317 so we need a bypass resistor. Since the documents
resistor is over the LM317 the voltage drop is 1.2 volts, and we just calculated the current documents"
so the desired numbers of ohms can now be calculated. documents\
4. For the too
Rfix = V/I = 1.2 / 2.36 10-3 = 508 ohm. moment yo
That resistor doesn't exist, we can choose from 470 and 510 ohm. We would rather have a
slightly larger maximum voltage so we select 470 ohm (yellow-purple-brown). If you 12.8 Parts lis
want to add a LED to see if the power is on or off use a 1 k resistor (brown-black-red) in
series with the LED and connect it directly to the 15 volts wall wart. This is a list w
sure you buy p
impossible, in
12.7 Content of the download
brute force to
permanently da
In the free download package you will find all software that is used in this book
conveniently put together in a single zip file. All software is free, you do not have to pay A starterpack c
anything. You don't even have to own this book in order to make use of this package. The you started wit
software is meant for Windows XP or similar Microsoft operating systems. details.
243
244 244
Installation instructions:
1. Go to www.boekinfo.tk (note the spelling of boek) and select the correct book and
language to get to the support page.
2. Download the software package to your PC.
3. Unzip the package to a location of your choice on the PC. If you unzip to c:\ then the
directory names in the previous table are correct. If you downloaded it to c:\my
documents then you need to replace "c:\" in the previous table with "c:\my
documents". So the sources can for example be found in "c:\my
documents\mbed\projects".
4. For the tools follow the instructions in the relevant sections of this book. At this
moment you do not have to do anything yet.
This is a list with parts that you need if you want to do all projects in this book. Make
sure you buy parts that can be used on a breadboard. For some components that is
impossible, in which case you can solder small pieces or wire to the parts. Never use
brute force to insert parts in a breadboard otherwise the internal contacts may bend
permanently damaging the board.
A starterpack can be obtained that contains the mbed and an assortment of parts to get
you started with this book. Check out the support page at www.boekinfo.tk for more
details.
Part Required
ARM mbed NXP LPC1768
Resistor (1/4 W) 0.5, 2x220, 270, 1k, 2x10k, 22k, 33k
Switch 3 x single change pushbutton
Variable resistor 1k LIN, 10k LIN, 100k LIN
LED Red, yellow, green
Speaker 8 ohm/0.4 W,
Capacitor 100 nF, 1 uF
244 245
245
246
Index
248
247
Index
248 249
Index
250
249
Index
250 251
AR
ARM Microcontrollers
The perfect book for hobbyists, students and engineers who want to learn C and how to use an mbed ARM
microcontroller in an easy and fun way, without the need for cumbersome software installations.
Cloud technology
The mbed NXP LPC1768 uses cloud technology, a revolutionary concept in software development. This means you do
not need to install software on your PC in order to program the mbed!
The only thing you need is a browser such as Microsoft Internet Explorer, and a USB port on your PC. You can get
Mi
access to your project from any PC anywhere in the world and continue working on it. When you are done a few
simple mouse clicks transfer the program to your mbed hardware. Of course you can optionally download the
projects and store them on your own PC.
35 p
ISBN 978-0-905705-94-1