Download Embedded lab Mannual and more Study Guides, Projects, Research Embedded Systems in PDF only on Docsity!
EEmmbbeeddddeedd CCoonnttrroolllleerrss
U Ussiinngg CC aanndd AArrdduuiinnoo // 22 EE
L Laabboorraattoorryy MMaannuuaall
J Jaammeess MM.. FFiioorree
This Laboratory Manual for Embedded Controllers Using C and Arduino, by James M. Fiore is
copyrighted under the terms of a Creative Commons license:
This work is freely redistributable for non-commercial use, share-alike with attribution
Published by James M. Fiore via dissidents
For more information or feedback, contact:
James Fiore, Professor
Electrical Engineering Technology
Mohawk Valley Community College
1101 Sherman Drive
Utica, NY 13501
www.mvcc.edu/jfiore
Cover art by the author
Introduction
This manual is intended for use in an introductory microprocessor or embedded controller course and is
appropriate for two and four year electrical engineering technology curriculums. It utilizes the C
programming language and the inexpensive, open-source Arduino hardware platform, specifically, the
Arduino Uno which uses an Atmel ATmega 328P processor. The manual contains sufficient exercises for
a typical 15 week course using a two to three hour practicum period. Some exercises may require more
than one period (in particular, the arbitrary waveform generator). The first portion deals strictly with an
introduction to the C language using standard desktop tools. Any reasonable compiler will do, and many
are available free of charge. The second portion (roughly 2/3rds of the total) addresses the Arduino
hardware. The Arduino system was chosen because the software is free, open-source, and multi-platform
(Windows, Mac and Linux). There are several choices for hardware, most of which are quite inexpensive
and open source. Although this manual focuses on the Uno board, other boards may be used with some
modifications to the lab text. Interface components are fairly common such as LEDs and seven segment
displays, switches, capacitors, diodes, low power resistors and switching transistors such as the 2N
or 2N2222. One unique element is an FSR (force sensing resistor), although the circuit may be
implemented with an ordinary momentary contact pushbutton switch. Another item of interest is a small
DC hobby motor.
Each exercise starts with an overview of the topics to be discussed. This usually includes some code
snippets for illustration. A programming application of interest is then developed with a pseudo-code. The
pseudo-code is then broken into appropriate C language code chunks. Where appropriate, hardware
interface issues are discussed. Finally, the entire package is fit together.
There is a companion OER (Open Educational Resource) text to accompany this lab manual. Other lab
manuals in this series include DC and AC Electrical Circuits, Computer Programming with Python,
Operational Amplifiers and Linear Integrated Circuits, and Semiconductor Devices. There is also an OER
text on Operational Amplifiers and Linear Integrated Circuits, and a Semiconductor Devices text is due in
early 2017. Please check my web sites for the latest versions.
A Note from the Author
This manual is used at Mohawk Valley Community College in Utica, NY, for our ABET accredited AAS
program in Electrical Engineering Technology. A key goal was to keep the student costs low so that
students could buy their own development system. Having full “any time” access to the development
hardware and software can be very motivating. I am indebted to my students, co-workers and the MVCC
family for their support and encouragement of this project. While it would have been possible to seek a
traditional publisher for this work, as a long-time supporter and contributor to freeware and shareware
computer software, I have decided instead to release this using a Creative Commons non-commercial,
share-alike license. I encourage others to make use of this manual for their own work and to build upon it.
If you do add to this effort, I would appreciate a notification.
“Resist corporate power”
- jmf
Table of Contents
- Introduction to C Programming
- Using Standard I/O
- Using Conditionals
- Using Loops
- Intro to Addresses, Pointers and Handles
- Hello Arduino
- Arduino Digital Output
- Arduino Digital Input
- Arduino Analog Input
- Arduino Reaction Timer
- Arduino Reaction Timer Redux
- Arduino Analog Output via PWM
- Arduino Event Counter
- Arduino Arbitrary Waveform Generator
Introduction to C Programming
The main objective of this initial programming exercise is to become familiar with using the
programming language tools. The programs in this exercise will be fairly trivial, but serve as a
springboard to later work. We will be using programs similar to the ones examined in lecture.
The precise C language package in use is not of extreme importance. Various companies will create
different programming tools and although the features and fine points may differ, the basics remain the
same. All C language tools need to compile C code and assemble it. Further, they need to link this
assembled code with other assembled modules and libraries in order to create a finished executable
program. In the simplest case, these tools will be in the form of command line utilities, i.e.; they run from
a DOS prompt or shell. Ordinarily, the tools are part of a graphical integrated development environment,
or IDE. IDE’s normally include a text editor. C compilers expect to work on raw text. Do not attempt to
“feed” them the output of a word processor, such as .doc file. If you are using simple command line tools
instead of an IDE, you will create your source files with a basic text editor such as Notepad.
C source code files utilize a “.c” extension. The output of the compiler is called an object file. It will
normally have a “.o” or “.obj” extension. In the Windows world, finished executables usually have a
“.exe” extension. Many IDE’s require that you create a project before you start entering your code. The
project includes many attributes such as the file names used for source code (there may be several in
larger projects), the appropriate libraries to link, the name of the finished executable, and so on. For
simple programming chores involving small amounts of source code, this can be a bit of a pain, however,
it is wonderful for larger endeavors. All the C source code of all of our exercises during this course can
easily fit on a single very modestly-sized (64 MB!) USB drive. This includes the project files that can
become much larger (many megabytes) than the C source. In networked labs on campus, project files and
source files can be saved to the student’s network storage area. For those performing labs off-campus, it
will probably be easiest to simply create new projects on your hard drive as needed.
This lab will use the Pelles C application. There is nothing magical about Pelles C though and other
systems are perfectly acceptable. We shall only be using Pelles C for the introductory exercises anyway.
Once we get rolling we shall shift our emphasis to the Arduino development board.
Our first exercise focuses on creating a project, editing source code, compiling and linking it, and testing
it. We shall then edit it and repeat the process. We shall also look at error reporting. If you’re using
command line utilities, see the note at the end of this exercise before continuing.
To begin, open the C language IDE. In Pelles C select “Start a new project” from the start pane. The new
project can be one of many things. We will not be creating Windows-GUI programs, but rather DOS shell
utilities, so select Win32 or Win64 Console Application (depending on your operating system) and give
the project a name. To create C source code, you will need to create a new text file. Select New>>Source
code under the File menu. A blank text edit window will pop open.
#include <stdio.h> /* Program three, with errors */ int main( void ) { int x, y; x = 10 y = x + 20; printf(The result is %d\n”,y); }
Note that we have left off the trailing semi-colon on x=10; as well as the leading quote on the printf()
function. Rebuild the project. This time you will receive a bunch of errors and warnings. They may differ
in wording from development system to development system, but you should see something about a
missing semi-colon before the y. You’ll probably also see an error concerning “The” being an undeclared
identifier. You may see many warnings as well. Usually, double clicking on the error message will
highlight the corresponding line in the code. Sometimes a single omission can cause the compiler to emit
dozens of error messages. This is because the compiler sort of “loses track” of where it is and starts
flagging perfectly good code as having errors. For this reason, if you get errors (and you will), always
look at the first reported error and fix it. Do not look at the last reported error as it may lead you on a wild
goose chase.
Finally, you may wish to save your code for backup. Simply select File>>Save as and choose an
appropriate name. Again, C source files should use a “.c” extension. Note that you can create, read, or edit
C source files without the IDE. All you need is a simple text editor. You won’t be able to compile or build
it, but you can at least get some work done on an assignment without a compiler handy.
For those using a command line system (no IDE), the process is similar to what has been described,
although less automatic. You will need to create your source file in a text editor. You then invoke the
compiler from a DOS shell window, usually with a command something like:
cc hello.c
This will create the object file. You then invoke the linker, usually with a command like:
ln hello.exe hello.obj stdio.lib
You will have to consult your documentation from the proper commands and syntax. Once the executable
is created, you test it from the shell by typing its name:
hello.exe
The appropriate output will be sent to the shell window. To edit the program, reopen the C source file in
the text editor, make the changes, save the file, and then repeat compile/link commands. If errors occur,
the error messages will be printed in shell window.
The Program
Here is the (first try) specification for the program:
The program will prompt the user for a DC voltage source value, a nominal resistor value and a resistor
tolerance. It will then print out the values for current and power dissipation based on the nominal,
minimum and maximum acceptable values of the resistor.
Not bad, but we need to refine it. First, command line programs usually need some form of start-up
message or print out of directions. Remember these are not GUI-driven programs with Help menus.
Second, always prompt for input values indicating expected units. If the program expects Ohms but the
user types in kilo Ohms, there’s going to be trouble. Unless there is a compelling reason not to, always
use base units (Ohms versus kilo Ohms for example).
Here’s our refined specification:
The program will first give appropriate directions/explanations of use to the user. The program will
prompt the user for a DC voltage source value in volts, a nominal resistor value in Ohms and a resistor
tolerance in percent. It will then print out the values for current in Amps and power dissipation in Watts
based on the nominal, minimum and maximum acceptable values of the resistor.
Note that we have specified tolerance as a percentage rather than as a factor. This is because the typical
user would be prepared to enter 10 for 10%, not .1. You can use this specification to create a pseudo
code or flow chart. Here is a possible pseudo code:
1. Print out directions for user.
2. Prompt user for voltage (in Volts) and obtain value.
3. Prompt user for resistance (in Ohms) and obtain value.
4. Prompt user for tolerance (in percent) and obtain value.
5. Determine maximum and minimum resistance values.
6. Calculate currents based on the three resistances.
7. Calculate powers based on the three resistances.
8. Print a heading for the values.
9. Print out the values.
You could of course choose an alternate algorithm or method of solution. For example, you might prefer
to print the heading before the calculations and then print values following each calculation. You might
prefer to change the format so that you get rows for each resistor rather than for the current and power.
You might even choose an entirely different approach using loops and/or arrays. There will be upsides
and downsides to each approach. Often, the question is not “Can I solve this problem?” but rather “What
is the most effective way of solving this problem?” Extend a little forethought before you begin coding.
Based on the above pseudo code, the following program should fit the bill. We will refine it later. Note
the use of double as we will most likely have fractional values to deal with.
#include <stdio.h> int main( void ) { double v, tol; double rnom, rlow, rhigh; double inom, ilow, ihigh; double pnom, plow, phigh; printf(“This program determines current and power.\n”); printf(“Please enter the voltage source in Volts.\n”); scanf(“%lf”, &v); printf(“Please enter the nominal resistance in Ohms.\n”); scanf(“%lf”, &rnom); printf(“Please enter the resistor tolerance in percent.\n”); scanf(“%lf”, &tol); tol = tol/100.0; /* turn tolerance into a factor / rlow = rnom – rnomtol; rhigh = rnom + rnom*tol; inom = v/rnom; ihigh = v/rlow; ilow = v/rhigh; pnom = v * inom; plow = v * ilow; phigh = v * ihigh; printf(“Resistance (Ohms) Current (Amps) Power (Watts)\n”); printf(“%lf %lf %lf\n”, rnom, inom, pnom ); printf(“%lf %lf %lf\n”, rhigh, ilow, plow ); printf(“%lf %lf %lf\n”, rlow, ihigh, phigh ); }
A word of caution here: Note that the variable ihigh is the highest current, not the current associated
with the highest resistor. This can make the print out code seem incorrect. This is a good place for some
comments! Also, the initial “directions” are skimpy at best. In any case, enter and build the code above
and verify that it works.
You may have noticed that there is a bit of repetition in this code in the form of calculations and printouts.
It may be more convenient if we created functions to handle these. For example, we could create a
function to calculate the current:
double find_current( double voltage, double resistance ) { double current; current = voltage/resistance; return( current ); } You could also do this in one step:
Note that the new function was added before main(). This is not required. We could also have added it
after main(), but in that case we’d have to add a function prototype so that the compiler would know
what to expect when it saw the function call in main(). It would look something like this:
#include <stdio.h> /* this is the prototype so the compiler can do type checking */ double find_current( double voltage, double resistance ); int main( void ) { .... } double find_current( double voltage, double resistance ) { return( voltage/resistance ); }
Alter the program to use this new current calculation function and test it. Once this is complete, alter the
program one more time to use a function to calculate the power and another to print out the three values.
Use the current calculation function as a guide. Finally, consider what might go wrong with the program.
What would happen if we the user entered 0 for the resistor value? How could you get around that
problem?
#define WALK_DOG 1 #define LET_OUT_CAT 2 #define COMB_WOMBAT 3 switch( choice ) { case WALK_DOG: /* c’mon poochie... / break; case LET_OUT_CAT: / there’s the door... / break; case COMB_WOMBAT: / first the shampoo... / break; / and so on */ }
In this exercise we’re going to make use of both constructs. The program will involve the calculation of
DC bias parameters for simple transistor circuits. We shall give the user a choice of three different biasing
arrangements (voltage divider, two-supply emitter, and collector feedback). The program will then ask for
the appropriate component values and determine the quiescent collector current and collector-emitter
voltage. It will also determine whether or not the circuit is in saturation. These values will be displayed to
the user.
One approach to this problem is to consider it as three little problems joined together. That is, consider
what you need to do for one bias and then replicate it with appropriate changes for the other two. The
three are then tied together with some simple menu processing. Here is a pseudo code:
1. Give the user appropriate directions and a list of bias choices.
2. Ask the user for their bias choice.
3. Branch to the appropriate routine for the chosen bias. For each bias,
a. Ask for the needed component values (resistors, power supply, beta).
b. Compute Ic and Vce and determine if the circuit is in saturation.
c. Display values to the user.
The appropriate equations for each bias follow. All biases use the following: Vcc is the positive supply.
Re is the emitter resistor while Rc is the collector resistor. beta is the current gain (hfe). The base-emitter
(Vbe) may be assumed to be .7 volts. Note that if Ic-saturation is greater than Ic, then the actual Ic is
equal to Ic-saturation and Vce will be 0.
Voltage Divider: also requires R1, R2 (upper and lower divider resistors).
Vth = Vcc*R2/(R1+R2)
Rth = R1*R2/(R1+R2)
Ic = (Vth-Vbe)/(Re+Rth/beta)
Vce = Vcc-Ic*(Re+Rc)
Ic-saturation = Vcc/(Rc+Re)
Collector Feedback: also requires Rb (base resistor).
Ic = (Vcc-Vbe)/(Re+Rc+Rb/beta)
Vce = Vcc-Ic*(Re+Rc)
Ic-saturation = Vcc/(Rc+Re)
Two-supply Emitter: also requires Vee (negative emitter supply) and Rb (base resistor).
Ic = (Vee-Vbe)/(Re+Rb/beta)
Vce = Vee+Vcc-Ic*(Re+Rc)
Ic-saturation = (Vee+Vcc)/(Rc+Re)
where Vee is an absolute value in all cases.
The Program
The program is presented in chunks, below, in the sequence you might write it. First comes the main
skeleton.
#include <stdio.h> #include <math.h> #define VOLTAGE_DIVIDER 1 #define EMITTER 2 #define COLLECTOR_FEEDBACK 3 #define VBE. int main( void ) { int choice; give_directions(); choice = get_choice(); switch( choice ) { case VOLTAGE_DIVIDER: voltage_divider(); break; case EMITTER: emitter(); break; case COLLECTOR_FEEDBACK: collector_feedback(); break; default: /* tell user they’re not so bright... */ printf(“No such choice!\n”); break; } }