You are on page 1of 78

MICROBOARD MANUAL

Revised and edited by David Zeibin, Summer 2001


Based on documents by
Ben Bathgate, Mike Cumming, Patrick Pilarski, and Paul Bartosek
Special thanks to Dr Chris Backhouse

HOW TO USE THIS MANUAL


In an effort to enable students with the appropriate skill set needed to make this course as rewarding as possible, I have
divided this manual into five parts. There is a lot of material here but you may not to need use all of it for your project.
PARTS
I

The MicroBoard: Design, Assembly and Maintenance This section breaks down the parts of the MicroBoard
and explains what each does. An assembly guide and testing procedures follow this. Finally, the section finishes
off with a short tutorial to complete the initial programming of the MicroBoards onboard micro-controller.
Everyone will need this information, if only as a reference.

II

Getting Started: Hosted Mode The second part introduces operation of the MicroBoard in the Hosted mode and
will outline some of the methods you can use to test drive your board and also demonstrate some very simple
examples. This section will also introduce you to some very basic programming of the PIC, which will consist of
(typically) nothing more than cutting, pasting, and thus, utilizing code that has already been written for you. To
attain any sort of marks in the course, you will need to use this section. To attain great marks, it is possible to stop
with the documentation at this point; however, you will need to design some pretty fancy electronics to
complement the simple code.

III

Beyond Getting Started: Autonomous Mode & Advanced Programming Techniques This section opens a
new chapter that will allow you to unleash the full capabilities of the MicroBoard. Along with in-depth
programming documentation (allowing you to tailor the PICs program to suit your exact needs), this section
contains detailed examples and is complemented by bits of usable sample code, schematic diagrams, and board
layouts. The hand-holding ends with this section and those who venture beyond here will seldom find step-bystep procedures but will be applauded for their ambition and persistence!

IV

Examples: Both Simple and Complex Sample projects possessing some commonly used input/output traits
have been designed and documented for you. The documentation is available for your perusal, complete with
code, diagrams, and explanations.

Appendices These are referenced by the four previous parts. Feel free to detach the appendices from the bulk of
this manual; you will likely refer to them often.

Using this manual not only as a reference but also as a guide should make the journey much more interesting if not truly
enjoyable. I would sincerely recommend taking the time to read the entire manual from beginning to end; the things you
will learn along the way will be integral when it comes to designing your own project. Be aware, however, that
completion of this manual will merely lay the groundwork for more interesting, albeit more useful, applications of the
MicroBoard.
Keep in mind that the MicroBoard is just the central nervous system of your project. You are responsible for the design of
the extraneous circuits that your project will utilize (sensors, motors, etc). It would be prudent to make your initial circuit
designs on an SK10 board, then later transfer your design to a computer using EAGLE to have it milled into a clean PCB.
In general, rats nests of wires dont hold up very well and, in accordance with Murphys Law, will inevitably let you
down when you need them the most (during demonstrations of course!).
Good luck.

David Zeibin
August 2001

TABLE OF CONTENTS
Part I

The MicroBoard: Design, Assembly, and Maintenance

1
1.1
1.2
1.3
1.4
1.5
1.6

INTRODUCTION ................................................................................................................................2
Specifications ...............................................................................................................................2
Functional Description .................................................................................................................3
DC Power Supplies .......................................................................................................................3
RS-232 Serial Peripheral Interface (SPI).....................................................................................4
The Micro-Controller ....................................................................................................................5
PIC Micro-Controller Chip Diagrams (PIC16F873) ......................................................................6

MICROBOARD KIT ASSEMBLY GUIDE....................................................................................................7

WRITING YOUR PROGRAMS TO THE PIC ...............................................................................................9

Part II

Getting Started: Hosted Mode

4
4.1
4.2
4.3

HOSTED MODE ...............................................................................................................................12


Communicating with the MicroBoard (Windows system) .........................................................12
Communicating with the MicroBoard (HP-UX system)..............................................................13
Communicating with the MicroBoard (Unix flavours) ...............................................................13

5
5.1
5.2
5.3
5.3.1
5.4
5.5
5.6
5.7
5.8
5.9
5.10

HOSTED MODE COMMANDS...............................................................................................................14


General Commands ....................................................................................................................14
Pulse Width Modulator (PWM) Commands ................................................................................14
Analog-to-Digital Converter (ADC) Commands .........................................................................15
Maximum ADC Values.................................................................................................................. 15
Serial Peripheral Interface (SPI) Commands ............................................................................15
Infra Red (IR) Command ...........................................................................................................16
LCD Screen Interface Commands ..............................................................................................16
Delay Command .........................................................................................................................17
A Few Comments about Syntax .................................................................................................17
Utilizing Hardware Flow Control ................................................................................................17
Programming in C ......................................................................................................................17

6
6.1
6.2
6.3
6.4
6.5
6.5.1
6.5.2
6.5.3

HOSTED MODE EXAMPLES ................................................................................................................18


Flashing LEDs .............................................................................................................................18
Digital-to-Analog Converter using PWM ....................................................................................19
Using SPI Devices ......................................................................................................................20
Adding Additional Outputs Using Shift Registers and SPI.........................................................21
A Rudimentary Hosted Mode Project: The GrabberBot..............................................................22
Using the GrabberBot in Hosted Mode ........................................................................................... 22
Using the GrabberBot with Scripted Files ....................................................................................... 23
Using the GrabberBot with a C Program......................................................................................... 24

Part III
7
7.1
7.1.1
7.1.2
7.1.3
7.2
7.3

Beyond Getting Started: Autonomous Mode


& Advanced Programming Techniques

AUTONOMOUS MODE .......................................................................................................................27


PIC Programming.......................................................................................................................27
Register Operations..................................................................................................................... 27
Mathematical Operations ............................................................................................................. 28
Flow Control ............................................................................................................................... 28
Digital I/O Ports.........................................................................................................................29
Limitations .................................................................................................................................30

8
DEBUG.HEX ................................................................................................................................31
8.1
Code Map....................................................................................................................................31
8.2
Upper-Page Subroutines ............................................................................................................32
8.2.1
Global Subroutines ...................................................................................................................... 32
8.2.2
UART Module Subroutines............................................................................................................ 32
8.2.3
ADC Module Subroutines.............................................................................................................. 32
8.2.4
PWM Module Subroutines ............................................................................................................ 32
8.2.5
SPI Module Subroutines (Master Mode Only).................................................................................. 33
8.2.6
LCD Module Subroutines .............................................................................................................. 33
8.2.7
Programming Module Subroutines (only available on the PIC16F877)................................................ 33
8.2.8
Programming Utility Subroutines ................................................................................................... 34
8.2.9
Help Function ............................................................................................................................. 35
8.2.10
IR Module Subroutines ................................................................................................................ 35
9
9.1
9.2

YOUR FIRST PIC ASSEMBLY CODE PROJECT ........................................................................................36


Getting Started with MPLAB ......................................................................................................36
The PIC16F87x Assembly Template...........................................................................................38

10
10.1

MPLAB SIMULATOR .......................................................................................................................41


Using the Simulator to Test Code...............................................................................................41

11
11.1

USING THE DEBUG.HEX CODE ........................................................................................................44


The ADC Lines.............................................................................................................................44

Part IV
12
12.1
12.1.1
12.1.2
12.2
12.2.1
12.2.2
12.3
12.4

Examples: Both Simple and Complex

WORKING EXAMPLES .......................................................................................................................49


Servo Motors ..............................................................................................................................49
Testing a Servo in Hosted Mode ................................................................................................... 49
Testing a Servo in Autonomous Mode............................................................................................ 50
SPI Bar Graph.............................................................................................................................51
SPI Bar Graph in Hosted Mode ..................................................................................................... 51
SPI Bar Graph in Autonomous Mode.............................................................................................. 52
Motor Speed Controller ..............................................................................................................54
Shaft Encoder .............................................................................................................................57

13 MEDULLA: THE SOUND-SENSING ROBOT ...................................................................................................61


14 SNAKE TURRET (MKII AUTONOMOUS VERSION).................................................................................... 633
15 LINE FOLLOWER ................................................................................................................................. 635
16 RF CONTROL (RC LINK) ..................................................................................................................... 637

Part V
APPENDIX A.
APPENDIX B.
APPENDIX C.
APPENDIX D.

Appendices
MICROBOARD SCHEMATIC DIAGRAM .........................................................................................69
COMPONENT AND SOLDER SIDE OF BOARD..................................................................................70
ASSEMBLING A MILLED BOARD (PLUS HOW TO SOLDER)...............................................................71
CHECKLISTS: COMPONENTS, POWER, AND INTEGRATED CIRCUITS..................................................73

Part I
The MicroBoard: Design, Assembly, and Maintenance

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 1

1 INTRODUCTION
The first-generation MicroBoard is a compact low-power controller board based on the Microchip Technologies
PIC16F873 micro-controller. The PIC is the heart and soul of the MicroBoard, acting as the central processing unit for the
board. The MicroBoard is used in the EE401 project course and will be common to most projects, while the addition of
student-designed-and-built circuits combined with customized software will complete individual projects.
Realized by way of an in-house design, the MicroBoard is an inexpensive alternative to the previously used Handy Board.
However, this does not mean the MicroBoard is inferior to its predecessor. In fact, the onboard PIC can perform up to 1
MIPS (million instructions per second) making the MicroBoard nearly 1000 times faster than the Handyboard, which
operated on a millisecond time scale (due to the fact that the Handyboard executed commands through interpreted C).
Every MicroBoard comes loaded with the following features:
Support for Three Built-in Motor Drivers: Each capable of driving a stepper motor, two bi-directional DC
motors, or four unidirectional DC motors.
Communication Interfaces: RS-232 communication with a PC; SPI and I2C buses for communicating with other
chips; and standard 5V CMOS digital I/O for anything else.
Extra Features: Five-channel analog-to-digital converter and two pulse-width-modulated outputs for servo
motors or other uses.
Two modes of operation are available for the MicroBoard:
Hosted mode: The MicroBoard runs a program allowing control of most of its functions through a serial link to a
desktop PC (see Part II). HyperTerminal is used to communicate with the MicroBoard in a command-prompt
fashion. It is also possible to write and compile a C program that will communicate with the MicroBoard for you
using commands you have defined (see Section 5.10).
Autonomous mode: More powerful than hosted mode, autonomous mode uses assembly code you have
compiled and then burned onto the PIC (see Part III). The code need not be hand-written from scratch; there
are many available subroutines you can call directly from the main portion of DEBUG.HEX, the Hosted mode
control program.
Complete with a relatively powerful processor and large I/O capability, the MicroBoard is an impressive control system.
The range of projects is virtually limitless: you can control robotics, perform wireless communication, carry out digital
signal processing, or even connect your MicroBoard to the Internet. The only real limit is your own imagination.

1.1 SPECIFICATIONS
This table lists the electrical characteristics of the MicroBoard; exceeding maximum or minimum values may damage
your board very quickly:
Maximum Input Voltage

18 Vdc

Minimum Input Voltage

6 Vdc

PIC Clock Speed

4 MHz (Upgradeable to 20 MHz)

PIC Digital I/O Pins

22

PIC Analog-to-Digital Channels

5 (multiplexed)

PIC Pulse-Width-Modulated Pins

Power Consumption with all ICs

140 mA @ 7.2 Vdc

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 2

Power Consumption with no L293s

20 mA @ 7.2 Vdc

Max current drawn from +12Vdc connector

500 mA

Max current drawn from +5Vdc connector

500 mA

Max current drawn from -12Vdc connector

50 mA

Max current per pin on PIC

20mA

Max current per L293 chip

1A

1.2 FUNCTIONAL DESCRIPTION


The MicroBoard is designed in a modular manner. Please refer to Appendix A MicroBoard Schematic Diagram and
Appendix B Component and Solder Side of Board as necessary to improve your understanding.

PIC16F873
Micro-Controller

Digital Interface Support &


H-bridge Drivers

Interface
Connectors
to the Rest
of Project

RS-232 Serial Interface

Analog/Digital Interface Support

Analog Supply Inverter

DC Power Supplies

Figure 1-1: PIC MicroBoard Block Diagram

1.3 DC POWER SUPPLIES

Figure 1-2: Power Supply Circuitry


DC power is supplied to the board through a 2.1mm coaxial barrel connector with center-positive polarity. Normally, this
power comes from a 9Vdc 500mA wall adapter plugged into the barrel connector. However, a 12Vdc 1A wall adapter or
suitably sized battery array can also be used.

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 3

Diodes D1 and D2 provide some reverse polarity protection and power supply transient isolation. Capacitors C1 and C2
provide power supply bulk charge storage while C3 - C6 provide additional power supply transient isolation for their
respective supplies.
IC1 regulates the bulk supply to the +5Vdc needed for the PIC micro-controller and logic devices (logic side of the L293 and
MAX232). IC2 and its associated components regulate the bulk supply for the voltage inverter, IC3, and are only installed
if IC3 is to be used. IC3, an ICL7662P, and capacitors C9-C14 provide a negative voltage for analog circuits (dual supply
op-amps).
You will notice that the polarized capacitors have a non-polarized capacitor in parallel with them. This is not always
necessary in designs but is here. The reasoning is that real capacitors are not ideal capacitors: larger capacitors tend to have
greater amounts of intrinsic inductance associated with them due to their construction. This greater inductance gives them
poorer high frequency performance. Smaller capacitors tend to have better high frequency performance. Therefore,
multiple real capacitors are used to approximate the required ideal capacitor performance.

1.4 RS-232 SERIAL PERIPHERAL INTERFACE (SPI)

Figure 1-3: RS-232 Serial Circuitry


The RS-232 circuitry consists of a DB09 female connector, the MAX232 chip, and related circuitry. The DB09 connector is
configured for an IBM PC-style 9-pin RS-232 connection. The MAX232 (sometimes called a HIN232) converts the RS-232
+/-12V signals to logic levels for the micro-controller. Resistors R31 and R32 (330 each) limit line slew rates and provide
some short-circuit protection. Resistors R23, R24 (not shown here; see Appendix A MicroBoard Schematic Diagram),
R33 and R34 provide output contention protection (a possible short circuit is created if the digital I/O pin of PIC is
incorrectly configured as an output and connected to the output of the MAX232).

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 4

1.5 THE MICRO-CONTROLLER

Figure 1-4: Micro-Controller


IC4 is the PIC16F873 micro-controller. Most of the pins, when configured as outputs, can source and sink 20mA of current
directly. The maximum voltage on any pin should not exceed the bounds of VDD and VSS.

CAUTION! This device is static sensitive.


The combination of SW1, R1 and R2 provides a reset switch. Note that R1 must be on the order of ten times greater than
R2 for pin 1 on the PIC to reach a reset level when SW1 is closed.
The arrangement of Y1, C15 and C16 provides the oscillator circuitry for the micro-controller. Y1 may be a quartz crystal, a
two-pin ceramic resonator, or a three-pin ceramic resonator with internal capacitors. Capacitors C15 and C16 are sized
according to the manufacturers data sheets (typically 10 to 15pF). NOTE: If a three-pin ceramic resonator with internal
capacitors is used, C15 and C16 should not be used (this is the case for the supplied MicroBoard kits).
Resistors R3 through R24 (all 470) are used to limit input and output currents to the micro-controller, thus affording
some limited protection. If a pin is used for either digital or analog input, no resistor is required but a 1.0k resistor will
provide some static protection. If the H-bridges are connected directly to the micro-controller, no resistors are required
between the L293 and the PIC16F873. Otherwise, the resistors may be used to limit output current from the PIC to drive
LEDs and other output devices.

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 5

1.6 PIC MICRO-CONTROLLER CHIP DIAGRAMS (PIC16F873)


The PIC16F873 is shown at right. The diagram
is a modified version of that found in the
MicroChip
PIC16F87x
data
sheet
(http://www.ee.ualberta.ca/~ee401/datasheets/
PIC16F87x.pdf). Modifications have been
made to reflect the preprogrammed
capabilities.
The A bank (pins 2 through 7) is ADC capable
with the exception of pin 6. If not used as ADC
inputs, the entire A bank can be used for digital
I/O. With a bit of programming, various
combinations of digital I/O pins and ADC pins
can be attained.
The B bank (pins 21 through 28) is comprised of ready-to-use digital I/O pins. If you choose to enable your board with
hardware flow control, RB1 and RB2 (pins 22 and 23) cannot be used a regular digital inputs or outputs (see Section 5.9 for
more details on hardware flow control).
The C bank (pins 11 through 18) has various capabilities. RC1 and RC2 (pins 12 and 13) can be set as PWM outputs while
RC3, RC4 and RC5 (pins 14 through 16) are used in SPI communications. RC6 and RC7 are reserved for the DB09 serial
connection.

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 6

2 MICROBOARD KIT ASSEMBLY GUIDE


You will receive a small kit containing all the parts youll need to assemble the basic MicroBoard. The kit includes
components to fill the 5V regulator circuit, one H-Bridge interface circuit, the RS-232 connection, and the required PIC
circuitry (refer to Appendix A MicroBoard Schematic for complete details).
For designing circuits or modifying your MicroBoard, certain parts are kept on hand at all times, while others will be
supplied especially for EE401 projects. Check out the EE401 web site for complete part listings
(http://www.ee.ualberta.ca/~ee401/).
To begin assembly of the board, youre going to need a few things:
soldering iron
63/37 electronic-grade rosin-core solder NOTE: Do NOT use the cheap solder that comes with the
tool kits; get good solder from a TA.
needle nose pliers for forming leads
small wire cutters for trimming leads
If youre not familiar with soldering and circuit board assembly, you may want to digest Appendix C Assembling a
Milled Board (plus How To Solder) before continuing. If you have any questions about the MicroBoard assembly dont
hesitate to ask a TA; thats what theyre there for. You can waste a lot of time and effort simply finding and repairing a bad
solder joint; do it right the first time and life will be much more pleasant.
As mentioned previously, the component and solder side diagrams of the board are contained in Appendix B.

2.1 MICROBOARD ASSEMBLY (A FEW SIMPLE GUIDELINES)


Remember these axioms whenever working with electronics:
Keep it clean.
It is easier to keep electronics clean than to clean electronics. Contamination can cause many problems: a simple
fingerprint will etch a copper trace and foul a solder connection; a fingerprint or leftover flux residue can act as an
undesirable resistor.
Keep it cool.
Use the correct soldering techniques and soldering temperatures; high temperatures will destroy components or
shorten life times.
Minimize stresses.
Miniaturization means less mechanically robust component packaging. Allow for thermal expansion, mechanical
flexing, and component movement. Do not pull leaded components too tight against the board.
To begin, refer to Appendix D Checklists: Components, Power, and Integrated Circuits; make certain you have all the
parts in your kit. If youre missing anything, hassle a TA.
Using the same checklist, assemble the board, checking off components as you go. Solder the components that sit closest to
the board first, then those that stand higher after.

WARNING! Do NOT solder ICs directly into the board!

Solder the IC sockets into the board; plug the ICs into their sockets.
Part I The MicroBoard: Design, Assembly, and Maintenance

Page 7

Before installing any ICs, test the board for proper power connections. Continue with the Power Checklist in Appendix
D. Once all the power checks have been tested and are correct, continue with the IC Checklist.
After your board is completely assembled, the next section will aid you in actually installing some software on to the
PIC.

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 8

3 WRITING YOUR PROGRAMS TO THE PIC


To actually make your MicroBoard do anything, it needs to be running a program. Since youve probably not written
anything yet, a basic but multi-talented program has been supplied for you (called DEBUG.HEX). In this section, you will
install DEBUG.HEX onto the PIC. In the next section, youll be able to take the PIC for a test drive.
The PIC has flash-type program memory, which can be written, erased, and rewritten; this is very useful for debugging
(you can test out the capabilities and connections of your circuitry before letting your project run amuck). Typically the
flash memory can go through several thousand of these cycles so you dont need to worry about it breaking down on you.
You will need to use a computer in the EE401 lab with a PICSTART Plus Development Programmer connected to it (see
Figure 3-1).
In the future, you will likely want to use the subroutines in DEBUG.HEX as part of your own program. If you modify
DEBUG.HEX or write your own program from scratch, youll need to follow these procedures to burn the new,
modified program onto the PIC.
But, first things first:
Start MPLAB (Start>Programs>Microchip MPLAB>MPLAB).
1

Ensure that the PICSTART Plus is connected to the


computer and that the power cord is plugged in (see
Figure 3-1).

Put your PIC chip into the uppermost position in the


socket on the PICSTART Plus with the notch on the PIC
pointing to the top (refer to Figure 3-1).

WARNING! Do NOT put your chip in


the PICSTART upside-down or you will
permanently damage the programmer
or destroy your chip!

Figure 3-1: PICSTART Plus programmer

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 9

Click on PICSTART Plus>Enable Programmer. A window will


pop up if the programmer is attached correctly (Figure 3-2). If the
box does not appear, check the connections and try again.

Select PIC16F873 from the Device drop box in the PICSTART


Plus Device Programmer window (Figure 3-2).

Choose File>Import>Import To Memory and select your


programming file (DEBUG.HEX). You may need to download
the
file
from
the
EE401
web
site:
http://www.ee.ualberta.ca/~ee401/debug/debug.hex.

Figure 3-2

Click on the Configuration Bits button. A new window should open; select the following options from each of the
drop boxes:

Figure 3-3 Configuration Bits window

Finally, click Program in the PICSTART Plus Device Programmer window to burn your program onto the PIC.

The program will tell you if the program was transferred onto the chip successfully.

Take the chip out of the programmer, plug it into your MicroBoard, and youre ready for business.

Part I The MicroBoard: Design, Assembly, and Maintenance

Page 10

Part II
Getting Started: Hosted Mode

Part II Getting Started: Hosted Mode

Page 11

4 HOSTED MODE
DEBUG.HEX allows you to control most of the functions of the MicroBoard without writing a single line of code. You can
even automate operations using Hosted mode by writing C programs for the PC that will control the MicroBoard (see
Section 5.10). DEBUG.HEX provides only the bare essentials available on the MicroBoard. To really make use of the
MicroBoard, youll need to write your own code (using DEBUG.HEXs pre-written subroutines or from scratch if youre up
to the challenge) and burn it onto the chip.
You will use a terminal program (HyperTerminal on the Windows systems and Seyon on the HP-UX systems) to
communicate with the MicroBoard through the serial port. DEBUG.HEX uses a command prompt interface; all the
commands available to you are outlined in Section 5.

4.1 COMMUNICATING WITH THE MICROBOARD (WINDOWS SYSTEM)


Before beginning, make sure that you have exited MPLAB; HyperTerminal and MPLAB cannot be running at the same time.
1

Connect a straight-through serial cable to the MicroBoard.

Open a HyperTerminal session with the desktop icon EE401.ht. If the icon isnt there, you can start HyperTerminal using
the Start Menu (Start>Programs>Accessories>Communications>HyperTerminal).

Connect power to the


MicroBoard. You should be
greeted with the Help
Screen (Figure 4-1). This
screen will also be shown
every time you type help
at the command prompt.

Should you need to


configure HyperTerminal
(if you need flow control
enabled, for example), select
File>Properties and click on
the Configure button in
the window that opens.

Select the COM2 port and


configure it to use 9600bps,
8 data bits, no parity, and 1
stop bit (8-N-1). Choose
flow control depending on
how youve configured
your board (see Section 5.9).

Figure 4-1: The Help Screen

Part II Getting Started: Hosted Mode

Page 12

4.2 COMMUNICATING WITH THE MICROBOARD (HP-UX SYSTEM)


There are HP systems running HP-UX also available in the lab space; most students will be familiar with operating these
terminals. Use your EE-department student-user logon and password to gain access. Open a terminal session (select
Terminal from the arrow menu) and enter the following to start up Seyon, the HP system equivalent of HyperTerminal:
seyon nodial modem /dev/tty0p0

When Seyon starts up, the Seyon Command Center will pop up. To configure Seyon, click on SET and select
CTS/RTS. Seyon should already be configured properly, but to make sure, choose the appropriate settings under each
button: 9600bps, 8 data bits, no parity, 1 stop bit (8-N-1), hardware flow control disabled (unless your MicroBoard has
hardware flow control enabled; refer to Section 5.9), etc.
NOTE: To change the flow control, go to the SET menu and choose RTS/CTS (hardware flow control) or None (no
flow control).
Connect the power and the serial cable to the MicroBoard; you should be greeted with the Help Screen. Like in
HyperTerminal, this screen will be shown if you type help at the command prompt.
NOTE: Only one Seyon terminal session can be launched on a machine at a time.

4.3 COMMUNICATING WITH THE MICROBOARD (UNIX FLAVOURS)


The terminal program should (no guarantees though!) work with various Unix-based operating systems. Using a similar
variant of HyperTerminal, connect using ttycua0 or ttys0.
Unless you need to, however, its probably best to stick to the tried and true methods in Sections 4.1 and 4.2.

Part II Getting Started: Hosted Mode

Page 13

5 HOSTED MODE COMMANDS


The Help Screen (refer to Figure 4-1 above) lists the preprogrammed commands available to you. Using these commands
you are able to control the MicroBoard, from the lowest level digital I/O to high level LCD screen control.
There are 22 general purpose I/O pins on the MicroBoard, many capable of multiple functions (refer to Section 1.6 for more
details). However, two of them are used by the serial interface leaving 20 available pins for your use. Five of these pins can be
used as inputs to the built-in ADC (note that all five of them must be configured the same, either digital or analog I/O). Two
of the pins can be independently configured as outputs for the built-in PWM.

5.1 GENERAL COMMANDS


General-purpose I/O pins can be set as either inputs or outputs. To specify which state you want the pin to be in, use the
commands input or output followed by a pin identifier (A0 to A5, B0 to B7, or C0 to C5 for example). Realize that if any of
the ADC, PWM, LCD, or SPI is using the pin, it wont be accessible as an I/O pin.
When a pin is configured as an input, the read command will return 0 or 1 depending on the input voltage at the pin
(thus determining whether the pin is on or off). If a pin is configured as an output, the commands set and clear will
change the output to a 0 or 1, 0V or +5V respectively.
>> input c3
>> read c3
Pin=1
>> output c2
>> set c2
>> clear c2

turns pin c3 of the PIC into an input


reads the value of pin c3 of the PIC
which happens to be 1 in this case
turns pin c2 of the PIC into an output
outputs a logical 1 (+5V) on pin c2
outputs a logical 0 (0V) on pin c2

5.2 PULSE WIDTH MODULATOR (PWM) COMMANDS


PWMs can be extremely useful if you would like to use servomotors in your project. Refer to Section 11.1 for a brief
introduction to servos and a tutorial on connecting and testing your servo using a three-wire connection. The PWM outputs
can also be used to drive stepper motors. Be sure to do some research on stepper motors before trying to hook anything up;
there are many resources scattered throughout the Internet.
The two built-in PWM modules are started using the commands pwmstart1 and pwmstart2. Different duty cycles (the ratio
of high-output time to low-output time) can be set but both PWMs must have the same period. The commands pwmperiod,
pwmduty1 and pwmduty2 control the period and respective duty cycles. All three commands take an 8-bit number as a
parameter (hexadecimal 00 to ff).
How the PWM works: A counter begins at zero and counts up to the value specified by pwmperiod. The counter then resets
to zero and begins counting again. At the beginning of each period, the output is set high and only goes low when the counter
reaches the value specified by pwmduty1 or pwmduty2. If the pwmduty1 or pwmduty2 value is greater than the pwmperiod
value, the output will remain high always and never go low. (Note that one of the PICs built-in timers, Timer 2, controls the
PWM period for both PWMs. See the Advanced MicroBoard Manual for details.)
The actual period can be calculated using the pwmperiod value and this formula:
Actual period = (pmwperiod value + 1) x 16s

Part II Getting Started: Hosted Mode

Page 14

Use pwmstop1 or pwmstop2 to stop the PWM.


>>
>>
>>
>>

pwmstart1
pwmperiod ff
pwmduty1 40
pwmstop1

starts the PWM module connected to pin c2


sets the PWM period to approximately 4ms
sets the duty cycle to about = 1ms (40/ff)
stops the PWM output on pin c2

NOTE: On the PIC, pin c2 corresponds to PWM1 while pin c1 corresponds to PWM2.
If you hook up an LED to the PWM, you can change the brightness by varying the duty cycle and period.

5.3 ANALOG-TO-DIGITAL CONVERTER (ADC) COMMANDS


There is a five-channel ADC built into the PIC; all of these channels are available for you to use with DEBUG.HEX. The ADC
pins are in the A bank on the PIC and are referenced by a0 through a3 and a5 (a4 is used as a digital I/O1).
To use the ADC you must initialize it with the adcinit command. After initializing, you can read a value from the ADC
using the command adcread followed by a channel number (0 to4; one of the five ADC channels). The program will return a
10-bit number (0000 to 03ff) corresponding to the voltage level on the input pin:
>> adcinit
>> adcread1
Val=0155

- starts the analog-to-digital converter


- reads an analog voltage on pin a1 (pin 3)
- in this case (155/3ff) x 5V = approximately 1.67V

NOTE: After running adcinit, all five channels are enabled. You may have problems if you want to turn only one of the five
off. By running an input or output command on any of the five pins (thus turning a pin into a digital line), all five ADC
channels will turn off automatically.
5.3.1 MAXIMUM ADC VALUES
All five ADC ports have a limited amount of diode protection to
prevent input voltages outside of the Vdd to Vss range. A better way to
make sure your PIC doesnt get fried by stray analog voltages though,
is to set up a small circuit before the signal reaches the ADC pin similar
to the one to the right. This circuit will not let any voltage hit the ADC
pin unless it is between 0 and 5V and doesnt depend on the PICs
limited protection.
The PIC16F87x data sheet also recommends that the maximum input
impedance of an analog source be less than 10k and that any current
on any pin should not exceed 20mA.

+5V
1k

4.7k

ADC line

PIC16F873
MicroBoard

5.4 SERIAL PERIPHERAL INTERFACE (SPI) COMMANDS


Many electronic components are capable of communication via SPI; the MicroBoard can communicate with these devices
using the built-in SPI module. Use the spiinit command to enable SPI communications. Transfers in SPI mode are done
synchronously: when the MicroBoard sends a byte using SPI, it then receives a byte from the device it is communicating with.
Begin a transfer using the spitrans command. The MicroBoard will send a byte and then print out the byte that it received.

On older MicroBoards, a pull-up resistor is required between the a4 pin and the power.

Part II Getting Started: Hosted Mode

Page 15

>> spiinit
>> spitrans 28
val=92

starts the SPI module


sends the value 28 out the SPI port
and returns the value 92 from the selected SPI device
NOTE: if the SPI device is one-way (such as a 595 shift
register or an LCD screen) spitrans will return val=00

To use the SPI, you must use pins c0, c3, and c5 on the PIC. Pin c5 sends data out while pin c3 takes care of the SPI clock.
Pin c0 is used to send a clock pulse out to the SPI devices, usually used to update the data sent through pin c5. Pin c4 is used
as an SPI input if your SPI device returns pertinent data. For a more detailed explanation of the SPI refer to Sections 6.3 and
6.4. For an example using the SPI input, see Section ELSEWHERE.

5.5 INFRA RED (IR) COMMAND


DEBUG.HEX contains a usable IR command that will return three 8-bit values from a universal TV remote (note that the
irread function may not give consistent values or work at all with any remote control). When the external IR circuit (see
Figure 5-1 below) is connected up to pin b0 (through Vout), run the irread b0 command. The pin will wait for some sort of
response (meaning the command will stay active until it receives a signal). Once the signal is received, irread returns three
lines, each containing an 8-bit hexadecimal value.
>> irread b0
Val3=AF
Val2=FF
Val1=FF

- begins waiting for IR data


spits out three sets of data once a signal is
received

Vcc

47 5%

5V

47F
GND

Vout

GND

Vout

IR Receiver
(IS1U60

Figure 5-1:

Infra Red Receiver Schematic Diagram

5.6 LCD SCREEN INTERFACE COMMANDS


DEBUG.HEX can make controlling an LCD screen extremely easy. The screen typically used in projects is a 2x20-character (2
rows of 20 characters each for a total of 40 characters) DMC-50218 Optrex display. DEBUG.HEX uses the MicroBoards SPI
interface (see Sections 6.3 and 6.4) to communicate with an external helper board containing a 595 shift register and the LCD
screen. This circuit board, however, will need to be built by the student, making LCD screens an advanced topic. For more
information on LCD screens, refer to Section 2 in the MicroBoard Advanced Manual.
To start the LCD interface use the commands lcdinit and lcdclear. The command lcdput followed by a string of text
writes to the LCD. To switch between lines on the display, use the lcdline1 or lcdline2 commands.
>>
>>
>>
>>
>>

lcdinit
lcdput hello
lcdline2
lcdput world!!
lcdclear

Part II Getting Started: Hosted Mode

initializes the LCD screen


writes hello to the LCD
move cursor to the first character on second line
writes world!! on the second line
clears the contents of the LCD screen

Page 16

5.7 DELAY COMMAND


This command is not terribly useful when you are connected to the MicroBoard through HyperTerminal since you, as the
operator, can wait as long as you like between sending commands. The delay command will, however, be of use if you are
planning to send a script of commands to a hardware-flow-control-enabled MicroBoard (see Section 5.9). The command
expects an 8-bit hexadecimal number and will wait (hh x 10)ms before returning to the prompt.
>> delay 10
>> delay 8f
>> delay ff

- waits 10 x 10ms = 160ms


- waits 8F x 10ms = 1430ms
- waits FF x 10ms = 2550ms

5.8 A FEW COMMENTS ABOUT SYNTAX


DEBUG.HEX will only accept commands up to 20 characters long. The only time this limitation may arise is when writing
text to the LCD. Also, keep in mind that the program expects numbers to be in hexadecimal (base 16) format and will return
numbers in hexadecimal as well. DEBUG.HEX ignores upper-case commands, letters, and hexadecimal numbers.

5.9 UTILIZING HARDWARE FLOW CONTROL


The MicroBoard has been designed such that it is possible to enable hardware flow control (the boards default state is
disabled). This means that a string of commands can be sent to the PIC all at once (like a script) and the PIC will execute the
commands in the order they were received. In the past, this was not possible and the PIC, when sent a script, would only
perform a command if it could be taken care of before the next command arrived.
Enabling hardware flow control is a simple matter:
1
2
3

Add two 470 resistors at positions R33 and R34 beside the
MAX232 chip.
Solder a wire between the end of the resistor closest to the DB9
connector in R34 and pin b1 on the PIC
Solder a wire between the end of the resistor closest to the DB9
connector in R33 and pin b2 on the PIC.

To create a script, simply save to a text file the set of commands in the
order you would like them carried out. Start a HyperTerminal session
and select Transfer>Send Text File. Choose your saved script. The
commands will be sent to the PIC and performed one by one (see
Section 6.1 for a scripted example).

Please note that this diagram is incorrect. The wires are crossed.

5.10 PROGRAMMING IN C
An interface program has been written that, when executed, is able to communicate with the MicroBoard using nearly all of
the commands available in Hosted mode. Since logic structures can be developed in C much more easily than in assembly
language, projects that dont require extreme mobility and thus, dont require Autonomous mode programming, can simply
use DEBUG.HEX pre-programmed on the PIC and a C program running on an HP-UX terminal (refer to Patrick Pilarskis
Guide to the HP-UX Systems for a quick tour of the system).
The skeleton interface program was originally written by Dr Chris Backhouse but has gone through various stages of
debugging and development. If you run into any problems with the original code, please report the problem immediately so
that it can be remedied as soon as possible.
Get the code here: http://www.ee.ualberta.ca/~ee401/debug/both.c
Part II Getting Started: Hosted Mode

Page 17

6 HOSTED MODE EXAMPLES


As mentioned previously, Hosted mode is a good way to run your MicroBoard through the motions of normal operation. Its
a good idea to make sure that, for example, a certain input will result in the desired output. Or, even simpler, just make sure
that your MicroBoard is working. This section has four examples including schematics and the Hosted mode commands to
make it all happen. At the end of this section, there is a short write-up on the GrabberBot, an extremely simple project that can
be run in the Hosted mode.

6.1 FLASHING LEDS


By hooking up some LEDs and attempting to turn them on and off, you can check to make sure your MicroBoard is working
correctly. To connect an LED to your board, youll need to remove the L293 H-bridge chip closest to the serial port. Insert the
positive lead (it is typically longer than the negative lead) of the LED into pin 10 of the now vacant IC socket; the negative lead
(the side with a small flat portion on it) goes to ground (pin 5 of the same socket is fine). This procedure can be used for all of
the I/O pins on the MicroBoard to test it to ensure the wiring and soldering has been done correctly.

WARNING! Always make sure that you connect a 470 currentlimiting resistor in series with an LED! Simply solder an LED onto a
resistor so that you have two free leads. Not using a resistor in series
will surely destroy the LED and will likely damage the MicroBoard!
Connect your MicroBoard to a PC, start up HyperTerminal, and power up your MicroBoard in Hosted mode. To flash the
LED you need to turn pin c0 into an output using the output command, then you can switch the LED on and off using the
set and clear commands:
>> output C0
>> set C0
>> clear C0

- sets pin c0 as an output


- turns the LED on
- turns the LED off

Still using Hosted mode (and ensuring that your board has hardware flow control enabled; see Section 5.9), you can use a
script to perform the same task. Make a *.txt file containing the following commands and send it to the MicroBoard using
the Transfer>Send Text File command. Add as many repetitions as you see fit (dont include the comments on the right;
those are there for your understanding only):
output c0
set c0
delay 96
clear c0
delay 96

sets
turn
wait
turn
wait

pin
LED
for
LED

c0 as an output
on
1.5 seconds
off

set c0
delay 96
clear c0
delay 96

turn LED on again


wait
turn LED off
wait

set c0
delay 96
clear c0
delay 96

- repeat ad nauseum

When you send the file, youll see each command pop up in the terminal window as they are processed (if you leave a line in
the script blank, the MicroBoard will simply skip to the next command).
Part II Getting Started: Hosted Mode

Page 18

To finally beat this example to death, the LED can be controlled using a C program as an interface between you, the user, and
the MicroBoard. Using the general C interface program, both.c (http://www.ee..ualberta.ca/~ee401/debug/both.c), written
by Dr Backhouse, plop in this main function to automate the process completely:
main () {
// begin initialization routine
long t; int j;
struct termios oldtio;
Initialize(&comm_port,&oldtio);
// end initialization routine
// begin main code
output("c0");

// set pin c0 to output

// this small loop will flash the LED 10 times


for (j=0;j<10;j++) {
set_pin("c0");
// turn
my_delay(1);
// wait
clear_pin("c0");
// turn
my_delay(1);
// wait
}

on LED
one second
off LED
again

6.2 DIGITAL-TO-ANALOG CONVERTER USING PWM


When you have verified that all of the I/O pins on the MicroBoard function properly, you can check to see if the PWM
module is working by making a simple digital-to-analog converter. Connect the simple RC circuit below with a 10F
capacitor and a 1.0k resistor:
1.0k

RC1
or
RC2

Analog
Output
10F

PIC16F87x

Figure 6-1:

Circuit schematic for DAC using PWM

Choosing two components with the appropriate values forms a low-pass filter with the necessary time constant for creating
an analog signal from the PWM output. The values shown are merely a suggestion; youll need to make sure that the PWM
period is sufficiently short compared to the RC time constant or ripple will be evident. The output of this signal is controlled
by the duty cycle of the PWM signal: to increase the voltage, increase the duty cycle and vice versa. Shown below is a set of
commands that will control the output of the PWM DAC:
>>
>>
>>
>>
>>

startpwm1
pwmperiod ff
pwmduty1 00
pwmduty1 80
pwmduty1 ff

Part II Getting Started: Hosted Mode

- output will be 0 volts


- output will be 2.5 volts
- output will be 5 volts

Page 19

6.3 USING SPI DEVICES


SPI is a very versatile interface. It is possible to connect multiple SPI devices (DIO, ADC, DAC, DSP, shift registers, etc, etc)
to your MicroBoard and individually communicate with each of them.
Simply connect all the clock lines together, all the input lines to the output of the MicroBoard (pin c5) and all the output lines
to the input of the MicroBoard (pin c4) to complete the SPI bus. To choose which device you want to communicate with, you
will need to use the chip select line of the device (connected to a free output pin on the PIC).
To better explain how to do this, we will go through an example using an SPI digital-to-analog converter, specifically the
LTC1448, which should be available for you to use. The chip should be connected to the MicroBoard using the following

PIC16F873
+5V

LTC1448
1 CLK
2 D
in
3 CS
4
VREF

14
SCK C3
16
SDO C5
13
Chip Select C2

VoutB
Vcc
GND
VoutA

8
7
6
5

schematic:
Figure 6-2: LTC1448 circuit schematic
The LTC1448 is a 12-bit, 2-channel DAC utilizing an SPI interface. When you write to the DAC you have to update both
channels at the same time, which means you have to write 2 x 12 (or 24) bits, with the upper 12 bits corresponding to VoutA and
the low 12 bits corresponding to VoutB. The PIC transfers 8 bits at a time in SPI mode so you will need three write cycles to set
the DAC.
Below is a sequence of Hosted mode commands that will select the DAC, write 24 bits to it, and then deselect it:
>>
>>
>>
>>
>>
>>
>>

spiinit
output c2
clear c2
spitrans 12
spitrans 34
spitrans 56
set c2

initialize the SPI


sets pin c2 as an output for chip select
select the LTC1448 (chip select is active low)
send first 8 bits
send next 8 bits
send last 8 bits (for a total 24 bits)
deselect the LTC1448

Notice that the chip select line on the DAC is active low so you need to clear it when you want to select the DAC. Once you
have typed in these commands, the outputs VoutA and VoutB should be 0x123 (1.35V) and 0x456 (0.35V) respectively.
There are many SPI devices available from digital signal processors (ADCs and DACs for example) to memory (RAM and
EEPROMs) to other micro-controllers. There is even an MP3 decoder chip available that uses an SPI interface. Since SPI is an
easily implemented interface, many companies find it advantageous to use it.

Part II Getting Started: Hosted Mode

Page 20

6.4 ADDING ADDITIONAL OUTPUTS USING SHIFT REGISTERS AND SPI


By way of the PICs SPI interface, you can add additional outputs using 595 shift register chips (eight outputs per chip). There
are two clever ways to connect and utilize the 595s: one a series setup and the other a parallel setup (and of course the
combination of the two). The parallel method allows you to perform a chip select command to choose which chip (or
series array of chips) you want to control.
The diagram below shows two chips in parallel and a third series array also in parallel with the other two chips.
RB3
RB4
RB5

24
25
26

RC0

11

RC3/SCK

14
+5V

+5V
16
10
14

RC5/SDO

11 12

8
11 12

15

8
11 12
9

74HC595
15

16
10

13

14

74HC595

+5V

16
10

13

14

74HC595
15

16
10

13

11 12

PIC16F873

+5V

13

14

74HC595
15

16

Figure 6-3: 595 Shift Register Schematic


We want to select a chip (or array of chips), send the desired output values (in the form of an 8-bit number, each bit
corresponding to an output pin), then finally activate those values by sending a clock pulse to the chip (or array). Output RC3
(pin 14) is the SPI clock and connects to every chip in parallel. Using any available output on the PIC (here we use pins b3, b4,
and b5), we can select a chip by making that output low (the 595s enable pin is active low). Output RC5 is where well
send a byte of data to the chip we chose. That byte is merely stored in the shift register and does not activate the eight outputs
immediately. To update the outputs, we send a clock pulse to the shift registers by turning output RC0 on and then off.
If there is only one shift register per parallel connection, the byte that is sent moves directly to that chip. If more than one are
connected in series though, the first byte you send moves into the first shift register and the old contents is carried over to the
next shift register. The next byte you send moves into the first register and its old contents (the stuff you just sent in the
previous command) moves to the next one, pushing the really old stuff onto the next chip, or into oblivion if that chip is the
last in the array (as would be the case in the above diagram).
Here are some sample commands to demonstrate how you would control each shift register:
>> spiinit
>> output c0
>> clear c0

- initializes the SPI


- set pin c0 to an output
- make sure c0 is off

>> output b3
>> output b4
>> output b5

- set pin b3 to an output (chip select line)


- set pin b4 to an output (chip select line)
- set pin b5 to an output (chip select line)

>> set b3
>> set b5
>> clear b4

- deselect the first register


- deselect the last two registers
- select the second register

>> spitrans 9f
>> set b4
>> set c0
>> clear c0
Part II Getting Started: Hosted Mode

send a byte (10011111) to second register


deselect the second register
send clock pulse to update all registers
stop clock pulse
Page 21

>> clear b5
>> spitrans b2
>> spitrans 0d
>> set b5

select the two-chip array


send a byte to the third register (10110010)
send a byte to the third register (00001101)
the previous byte gets bumped to the fourth
deselect the two-chip array

>> set c0
>> clear c0

- update the registers


- make sure c0 is off for subsequent spitrans

Using pin c4, the SPI input line, one could hook up SPI input devices and use a similar process to select an input device on
the SPI bus and clock data in on the SDI line (pin c4).

6.5 A RUDIMENTARY HOSTED MODE PROJECT: THE GRABBERBOT


Using only DEBUG.HEX without any additional
programming, you can design a simple robot that can move
around, grab an object, and move the object to another location.
All of this is performed using a few simple commands in the
Hosted mode. Rig up a robot using the diagram on the right as
a reference.

Grabber
Motor

12 RC1
13 RC2

6
3
11
14

The following sets of commands control the robot; simply type


them in during a HyperTerminal session and, provided youve
hooked everything up properly, the robot should respond
accordingly. Check out the EE401 web site for photos and
movies of the GrabberBot.

GND
L293D
-

11 RC0
14 RC3

7
2

21 RB0
24
RB3
PIC16F873
MicroBoard

Right
Motor

NOTE: In all these examples, hh is a hexadecimal number from


00 to ff.

10
15

Left
Motor

6.5.1 USING THE GRABBERBOT IN HOSTED MODE


Initialization
>>
>>
>>
>>
>>
>>
>>
>>

pwmstart1
pwmstart2
pwmduty1 00
pwmduty2 00
output b0
output b3
output c0
output c3

Move Forward
>>
>>
>>
>>

pwmduty2 00
set c0
set c3
pwmduty2 hh

Move Left
>>
>>
>>
>>

pwmduty2 00
clear c0
set c3
pwmduty2 hh

Move Right
Part II Getting Started: Hosted Mode

Stop Motion
>> pwmduty2 00

Open Grabber
>>
>>
>>
>>

pwmduty1 00
set b0
clear b3
pwmduty1 hh

Close Grabber
>>
>>
>>
>>

pwmduty1 00
clear b0
set b3
pwmduty1 hh

Stop Arm
>> pwmduty1 00

NOTE: Reverse motion is not possible with this setup.


However, by setting up motor circuits similar to that of the
Page 22

>>
>>
>>
>>

pwmduty2 00
set c0
clear c3
pwmduty2 hh

grabber arm, you can switch the direction of rotation by


reversing the polarity of the leads to the motor.

6.5.2 USING THE GRABBERBOT WITH SCRIPTED FILES


The setup of GrabberBot for scripted file control is simple. Most importantly, make sure your MicroBoard is equipped with
hardware flow control; if its not, refer to Section 5.9 for instructions.
Create *.txt files containing the commands outlined above and name the file appropriately. You will want to replace the "hh"
in the code with a reasonable value. You can change the speed of your motors by sending individual text files configured for
different PWM settings.
To send a script to the MicroBoard, connect to the board as you normally would using HyperTerminal. Once the Help Screen
appears, select Transfer>Send Text File Choose the script you want to send and click OK. Once that script finishes
executing, you can follow the same procedure to execute the next script.
A possible call sequence could look like this: FORWARDfull.txt; LEFTmed.txt; FORWARDmed.txt; STOP.txt;
GRABBERopen.txt; FORWARDslow.txt; STOP.txt; GRABBERclose.txt. The robot would move forward, turn a bit
left, slowly crawl toward its target, stop, open its claw, inch forward until the object is in its reach, and then close the claw.
Using delay calls and good timing, this could be done with a single large script.
Each script outlined below performs one task, moving the GrabberBot left or right or forward, or controlling the Grabber arm:
INITIALIZATION.txt
pwmstart1
pwmstart2
pwmduty1 00
pwmduty2 00
output b0
output b3
output c0
output c3

MOVEFORWARD.txt
pwmduty2 00
set c0
set c3
pwmduty2 hh

MOVELEFT.txt
pwmduty2 00
clear c0
set c3
pwmduty2 hh

STOP.txt
pwmduty2 00

OPENGRABBER.txt
pwmduty1 00
set b0
clear b3
pwmduty1 hh

CLOSEGRABBER.txt
pwmduty1 00
clear b0
set b3
pwmduty1 hh

STOPGRABBER.txt
pwmduty1 00

MOVERIGHT.txt
Pwmduty2 00
Set c0
Clear c3
Pwmduty2 hh

Part II Getting Started: Hosted Mode

Page 23

6.5.3 USING THE GRABBERBOT WITH A C PROGRAM


Implementing a C program to control the GrabberBot is likely the easiest and most efficient method. In conjunction with the
code below (get the source file here), youll need to be familiar with the HP-UX to MicroBoard interface code, both.c (refer to
Section 5.10 for more details).
This is the main code youll want to use. Its effectively a simple user interface similar to that of the HyperTerminal
environment, although now tailored to the GrabberBot specifically.
main {
// begin spi initialization
long t; int j;
struct termios oldtio;
Initialize(&comm_port,&oldtio);
// end spi initialization
// GrabberBot code begins here
output("c0");
// set pins for output
output("c3");
output("b0");
output("b3");
startpwm1();
startpwm2();

//start PWM modules

pwmduty1(0);
pwmduty2(0);
int choice=0;
int motorspeed=0;
int clawspeed=0;
while(1) {
printf("Select an option:\n");
printf("-----------------\n");
printf("1: Forward\n");
printf("2: Stop\n");
printf("3: Left\n");
printf("4: Right\n");
printf("5: Open Claw\n");
printf("6: Close Claw\n");
printf("7: Stop Claw\n");
printf("8: Change Wheel Speed\n");
printf("9: Change Claw speed\n");
printf("0: Exit\n\n")
printf("What is your choice?");
cin >> choice;
if ( choice == 0 ) break;

// exit on 0

switch (choice) {
case 1:
pwmduty2(0);
set_pin("c0");
set_pin("c3");
pwmduty2(motorspeed);
break;
case 2:
pwmduty2(0);
break;
case 3:
pwmduty2(0);
clear_pin("c0");
set_pin("c3");
pwmduty2(motorspeed);
Part II Getting Started: Hosted Mode

//set duty cycle to 0


//set pins
//set motor speed pwm
// stop motors
// move left

Page 24

break;
case 4:
// move right
pwmduty2(0);
set_pin("c0");
clear_pin("c3");
pwmduty2(motorspeed);
break;
case 5:
// open grabber
pwmduty1(0);
set_pin("b0");
clear_pin("b3");
pwmduty1(clawspeed);
break;
case 6:
// close grabber
pwmduty1(0);
clear_pin("b0");
set_pin("b3");
pwmduty1(clawspeed);
break;
case 7:
// stop grabber
pwmduty1(0);
break;
case 8:
// change motor speed
printf("\nWhat speed (0-100)?");
cin >> choice;
motorspeed=choice;
break;
case 9:
// change grabber speed
printf("\nWhat speed (0-100)?");
cin >> choice;
clawspeed=choice;
break;
default:
printf("unknown command");
break;
}
}
}

Hook up the HP-UX's serial cable, compile the interface program (with your new main function shown here) with g++ or
another compiler, and run the new executable. Enter the commands to operate the GrabberBot.

Part II Getting Started: Hosted Mode

Page 25

Part III
Beyond Getting Started: Autonomous Mode
and Advanced Programming Techniques

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 26

7 AUTONOMOUS MODE
Using the MicroBoard in Autonomous mode is a much more powerful manner of doing things and will let you unleash
its full potential, but youll likely need to get your fingers a little bit dirty and play around with some real, live assembly
code. Before reading any further, you are advised to browse through the PIC16F87x data sheet
(http://www.ee.ualberta.ca/~ee401/datasheets/PIC16F87x.pdf); what follows is intended to supplement that data sheet.
Use MPLAB (Start>Programs>Microchip MPLAB>MPLAB) to write and compile your code. If youd like to download
MPLAB, it is available on the EE401 web site at http://www.ee.ualberta.ca/~ee401/software/microchip/MPL51100.exe.
The following will introduce several concepts involved in developing systems using the PIC, specifically assembly
language code structure and intricacies using MPLAB, digital I/O, and downloading your code to the PIC itself.
Before parsing through this section, make sure you are familiar with assembly language basics and the PIC instruction set,
available in the aforementioned data sheet.
Notes:

bold words denote registers, bits, and op-codes


foo and bar can be any built-in or user-defined register

Fosc is the global clock frequency

7.1 PIC PROGRAMMING


The PIC micro-controller uses a RISC-based architecture with only 35 commands (described in detail in the PIC data
sheet). There are three distinct memory regions onboard the PIC: register memory, program memory, and EEPROM
memory. Register memory is used in virtually every operation; program and EEPROM memory are generally not
accessed by user programs.
There are six important sections of memory in the PIC16F873:
Memory Section

Address Range

Notes

Bank0 Registers

000h-07Fh RMem

Use RP1=0 and RP0=0 in STATUS register to select.

Bank1 Registers

080h-0FFh RMem

Use RP1=0 and RP0=1 in STATUS register to select.

Bank2 Registers

100h-17Fh RMem

Use RP1=1 and RP0=0 in STATUS register to select.

Bank3 Registers

180h-1FFh RMem

Use RP1=1 and RP0=1 in STATUS register to select.

Page0 Program Memory

0000h-07FFh PMem

0000h is RESET vector; 0004h is INTERUPT vector

Page1 Program Memory

0800h-0FFFh PMem

Use PCLATH to switch between program memory pages.

Table 7-1: Memory Sections and Address Ranges


7.1.1 REGISTER OPERATIONS
All but eight of the available assembler op-codes utilize register memory. There are 512 addressable registers (memory
locations) available on the PIC. These registers are divided into four 128-byte-sized pages. The pages are selectable using
the RP0 and RP1 bits in the STATUS register (as shown above).
Although there are 512 addressable registers, several special registers are available on all four pages to simplify
programming: W, INDF, PCL, STATUS, FSR, PCLATH, and INTCON.
There is also a section of general purpose RAM available on all four pages in the range 70h to 7Fh as well as F0h to FFh,
170h to 17Fh, and 1F0h to 1FFh.
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 27

NOTE: Many of the register locations are reserved and should not be used by the users program and general-purpose
storage. See the memory map in Figure 2-3 of the PIC data sheet for more details.
There are two methods of addressing memory: direct and indirect mode. Direct mode is bound by the values of the RP0
and RP1 bits and can only address the currently selected register page. This is the normal mode where individual
operations can access separate registers using commands such as
clrf

foo

; set all bits of variable foo to 0

The other method of accessing registers does not depend on the value of RP0 or RP1, instead IRP is used to select either the
range 00h to FFh or 100h to 1FFh. Using the indirect addressing method, the lower byte of the address of the register to be
accessed is written into the FSR register. On the next instruction cycle the contents of the selected register are available in
the INDF register, ready for reading or writing.
To access a variable using this method you could use the following code:
movlw
movwf
clrf

bar
FSR
INDF

; put address of bar into W


; copy address of bar to FSR
; clear contents of bar

Obviously, the direct addressing method is faster. When it is necessary to move data from one page to another, however,
the indirect method is much faster than the direct method.
7.1.2 MATHEMATICAL OPERATIONS
Since the PIC is RISC-based, there are very few mathematical operations available. For example, there are no hardware
floating-point operations, or even multiplication or division for that matter. Two add and two subtract instructions are
available though. If you require this functionality in your code, Microchip does offer some software emulation libraries for
these operations (check out the subset of pertinent project ideas on the Project Suggestions page of the EE401 web site).
One tricky part when using the built-in math operations lies in the subtraction op-codes sublw and subwf. Care must be
taken when using these operations to ensure that the operation performed is indeed the operation desired.
Example:
subwf
sublw

foo,W
d30

; W = foo - W
; W = 30 W

The first command is fairly straightforward; the second, on the other hand, can be counterintuitive.
An alternative to actually performing the calculations is a look-up table. For example, instead of performing the same
calculation over and over, a Celsius to Fahrenheit conversion table could be made listing all the corresponding Fahrenheit
temperatures for 0 to 100C. Choose a method that will work best for your particular application.
7.1.3 FLOW CONTROL
There are four op-codes that provide conditional branches: btfss, btfsc, incfsz, and decfsz. The first two test a single
bit in a register and skip the next instruction depending on the instruction used and the value of the bit. The last two
increment and decrement the operand, respectively, and skip the next instruction if the value of the register after the
operation is zero.
Three examples of code are shown below to demonstrate commonly used comparison operations:
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 28

To test foo == bar:


movf
subwf
btfss
goto
goto

foo,W
bar,W
STATUS,Z
FALSE
TRUE

;
;
;
;
;

load foo into W


subtract foo from bar
check if result is zero
condition is false
condition is true

;
;
;
;
;

load foo into W


subtract foo from bar
C is clear if borrow occurred
condition is false
condition is true

;
;
;
;
;

load foo into W


subtract foo from bar
C is set if borrow didnt occur
condition is false
condition is true

To test if foo > bar:


movf
subwf
btfsc
goto
goto

foo,W
bar,W
STATUS,C
FALSE
TRUE

To test if foo <= bar:


movf
subwf
btfss
goto
goto

foo,W
bar,W
STATUS,C
FALSE
TRUE

The values of foo and bar are being compared: if the condition being tested is true, the program will jump to the label
TRUE; otherwise, it will jump to the label FALSE.

7.2 DIGITAL I/O PORTS


Eventually, when you want the PIC to communicate with other hardware, the I/O ports will come in handy.
The PIC you are using has one 6-bit data port (PORTA) and two 8-bit data ports (PORTB and PORTC) for a total of 22 generalpurpose I/O lines. Each port is controlled using two registers: TRISx determines the data direction and PORTx is the data
transfer buffer (where x is one of A, B, or C). By setting a bit in a TRISx register the associated pin becomes a highimpedance input; the input can be read using the corresponding bit in the PORTx register.
Clearing a bit in the TRISx register turns the pin into an output; the output level can be changed by writing to the related
bit in the PORTx register. These registers can be written to/read from using both single bit and word length operations.
Shown below is a table describing the data registers used for I/O operations:

Address

Name

Bit 7

Bit 6

Bit 5

Bit 4

Bit 3

Bit 2

Bit 1

Bit 0

05h

PORTA

RA5

RA4

RA3

RA2

RA1

RA0

85h

TRISA

06h, 106h

PORTB

RB7

RB6

86h, 186h

TRISB

07h

PORTC

87h

TRISC

PORTA Data Direction Register


RB5

RB4

RB3

RB2

RB1

Transmit/Receive Selection
RB0

PORTB Data Direction Register


RC7

RC6

RC5

RC4

RC3

RC2

PORTC Data Direction Register

Function
Data Transfer
Data Transfer
Transmit/Receive Selection

RC1

RC0

Data Transfer
Transmit/Receive Selection

Table 7-2: I/O Port Registers

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 29

The following code demonstrates I/O operation using the same example as in the hosted mode: turning an LED on and
off. Unfortunately, the human eye will not be able to see the LED flashing since the frequency is about 250 kHz. You can
use an oscilloscope to view the output though:
start
bsf
bcf
bcf

STATUS,RP0
TRISC,0
STATUS,RP0

; switch to register page 1


; make RC0 an output
; switch back to page 0

loop
bsf
bcf

PORTC,0
PORTC,0

; turn LED on
; turn LED off

goto

loop

end

7.3 LIMITATIONS
As mentioned previously, the PIC has a limited set of functions. There are no multiply or divide instructions available and
there is no floating-point math either.
The PICs you were given are rated to run at 4MHz; this may prove to be too slow if you are making any processor
intensive applications. A 20MHz version is available, however.
There are 192 bytes of RAM and 128 bytes of EEPROM available on the PIC. For most applications that should be plenty,
but it may not be enough for storing large amounts of data. Additional memory chips can be connected to the PIC should
the need arise.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 30

8 DEBUG.HEX
If you require Autonomous mode (many will), youll need to either write your program from scratch, or modify an
existing program. DEBUG.HEX contains many subroutines that you can reuse in your own project. As long as youre
familiar with the PIC instruction set and the basics of assembler language, programming the PIC to suit your needs should
be a relatively painless procedure: just simply call the subroutines that have already been written for you. The majority of
the grunt work has been done; its up to you, however, to design the logic structure of your program.
DEBUG.HEX is described below. You can get the full source code
(http://www.ee.ualberta.ca/~ee401/debug/debug.asm).

on

the EE401

web site

8.1 CODE MAP


DEBUG.HEX is divided up into four main parts:
1

Variable and constant declarations: It will be important to look at this section in conjunction with any code
samples from DEBUG.HEX you choose to copy to make sure you also copy any required variables and constants
into your code.
Command input subroutines (user interface display and parsing): This code displays a prompt on the terminal
screen, allows a user to type in a command and input data, then calls for its execution. If the command is
recognized then the appropriate calls are made to command subroutines in the next section of code to execute the
command. The interface section contains general interface code and a set of subroutines starting with the word
parse_. If a command is not recognized then Unknown Command is displayed on the terminal screen and
the prompt is redisplayed. This code is useful to examine, but unless you are planning an interactive user interface
for your project, it is unlikely you will need to understand the details of this section. Given that a valid command
is entered, the command is stored in ASCII format in a set of variable locations starting at the input variable
location in the first bank of register memory.
Command execution subroutines: The names of these subroutines each begin with the letters cmd_. These
subroutines serve two purposes: The first is to parse the input data included with many of the commands to
identify incorrect input data and to use that data to make the appropriate call to the implementation subroutines
in the next section. The second is to display the results of the call to the implementation subroutines. Though you
will probably want to write your own code to call the implementation subroutines, the code here will give you a
good example of what youll need to do to call commands in an appropriate order and set variables to required
values.
Low-level device implementation subroutines: These routines initialize and manipulate the registers and data
necessary to perform a desired process in the PIC processor. All these subroutines are located in the upper page of
program memory. Though most of the code in this section does not need to be changed to include it into a users
program, several of the routines contain display components that the user may want to change or delete. Note
that the routines putUART and putHexByteToTerm sends data contained in W to the terminal and can be
replaced by user code that performs operations on this data or transfers it to other variables for later use.

Parts 1 through 3 are located in the lower memory page (page 0 for both devices), and part 4 is located in the upper
memory page (page 1 for the PIC16F873 and page 3 for the PIC16F877).
Keep in mind that DEBUG.HEX contains much programming dedicated to receiving and parsing input in Hosted mode.
Thus, there is a lot in DEBUG.HEX that you simply will not need since a project running in Autonomous mode doesnt
receive any user input. Make sure you understand what something does before you cut it out of the program though;
everything can be pieced back together if you lose something, but this is time consuming and, of course, causes unwanted
frustration. You can safely cut Parts 2 and 3 without any lost functionality (save for communication via Hosted mode). If
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 31

you are planning to do a lot of low-level programming, you may consider starting with the Autonomous flashing LED
code outlined in Section 9.2.

8.2 UPPER-PAGE SUBROUTINES


These are the subroutines you will be calling. Each is listed with its description, what it receives, what it uses, and what it
returns.
8.2.1 GLOBAL SUBROUTINES
initializeChip
Sets specific registers on startup. Sets port A to all digital Receives: nothing
I/O. Clears and sets all ports to digital output.
Uses: W
Returns: nothing
8.2.2 UART MODULE SUBROUTINES
initializeUART
Initializes the UART.

getUART
Gets a byte from the Rx line and stores it in W.

putUART
Puts the byte in W on the Tx line.

Receives: nothing
Uses: W
Returns: nothing
Receives: nothing
Uses: W
Returns: W (ASCII value read from terminal)
Receives: W (ASCII value read from terminal)
Uses: W
Returns: nothing

8.2.3 ADC MODULE SUBROUTINES


initADC
Initializes RA0 as an ADC input. Sets the (right justified) Receives: nothing
data flag.
Uses: W
Returns: nothing
readADCX
Initiates a read of AN<X> as an ADC which stores its value Receives: W (port pin to read)
in ADRESH, and ADRESL (right justified). The X value is a Uses: W
number from 0 to 4 and is located in W prior to call.
Returns: nothing
8.2.4 PWM MODULE SUBROUTINES
The X in these commands can be either 1 or 2, referring to one of the two PWM outputs (PWM1 is on RC2 while PWM2
is on RC1).
startPWMX
Starts output on PWM1 (pin RC2) or PWM2 (pin RC1). Receives: nothing
Defaults the period and duty cycle to ff/50% respectively.
Uses: W
Returns: nothing
stopPWMX
Stops output on the PWM1 (pin RC2) or PWM2 (pin RC1).

Receives: nothing

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 32

Uses: W
Returns: nothing
setPWMDutyX
Sets the value of the duty cycle on the PWM1 (pin RC2) or Receives: W
PWM2 (pin RC1). The value must be less than the value of Uses: W
the period or the duty cycle will be 100%. The duty cycle is Returns: nothing
determined by the ratio:
duty/period = % duty cycle

setPWMperiod
Sets the value of the period on both PWM pins. The value Receives: W
can be 0 to 0xFF and is the value of the period of both Uses: W
PWM pins. This is because the PIC circuit uses Timer 2 to Returns: nothing
set the period for both pins.
8.2.5 SPI MODULE SUBROUTINES (MASTER MODE ONLY)
initializeSPI
Initializes the SPI pins. The communication protocol is set to Receives: nothing
perform data transfer on a rising edge clock. See the Uses: W
PIC16F87x data sheet and the Mid-Range PIC Manual to Returns: nothing
see how to modify code to other protocols.
transferSPI
Performs concurrent send and receive data transfer over Receives: W (data to be sent)
the SPI pins.
Uses: W
Returns: W (data received)
8.2.6 LCD MODULE SUBROUTINES
initializeLCD
Initializes the LCD to run an Optrex 2x20 LCD display over Receives: nothing
the SPI. Refer to Section 4.1 of the MicroBoard Advanced Uses: W, temp
Manual for hookup diagrams and other important details. Returns: nothing
sendLCDChar
Sends an ASCII character contained in W to the SPI.

Receives: W
Uses: W, char, temp
Returns: nothing

sendLCDCmd
Sends a command byte contained in W to the LCD on the Receives: W
SPI.
Uses: W, char, temp
Returns: nothing
LCDDelay
Performs delays during LCD initialization.

Receives: W (multiplier of the 1ms delay)


Uses: W, DCOUNT1, DCOUNT2, DCOUNT3
Returns: nothing

8.2.7 PROGRAMMING MODULE SUBROUTINES (ONLY AVAILABLE ON THE PIC16F877)


initializeProgrammer
Initializes the chip to program an external application PIC Receives: nothing
(refer to the MicroBoard Advanced Manual for more Uses: nothing
information on programming).
Returns: nothing
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 33

setHighVoltageProgrammingMode
Places an external application PIC connected to the Receives: nothing
MicroBoard into programming mode using the standard Uses: W, temp
ICSP (In-Circuit Serial Programming) method. See the Returns: nothing
Microchip application notes on ICSP for more information.
setLowVoltageProgrammingMode
Places an external application PIC connected to the Receives: nothing
MicroBoard into programming mode using the low- Uses: W, temp
voltage ICSP (In-Circuit Serial Programming) method. See Returns: nothing
the Microchip application notes on ICSP for more
information.
programmingPrompt
Displays a Send File prompt on the terminal when Receives: nothing
waiting for a *.HEX file during programming.
Uses: nothing
Returns: nothing
clearProgrammingMode
Sets the external application PIC (the one that was just Receives: nothing
programmed) into a standard running mode after Uses: W, temp
programming.
Returns: nothing
beginProgramming
Decodes a *.HEX file and transfers it to the program Receives: nothing
memory of an external application PIC.
Uses: W, temp, appPCLow, appPCHigh, byteCount,
lineCheckSum, addressHigh, addressLow, recordType,
DCOUNT1,
DCOUNT2,
addrIncrementLow,
addrIncrementHigh, hexOutDataHigh, hexOutDataLow,
hexDataHigh, hexDataLow
Returns: W (1 on error)
sendProgrammerData
Sends a 14-bit word (plus start and stop bits) to the memory Receives: hexOutDataHigh, hexOutDataLow
of an external application PIC.
Uses: W, temp, hexOutDataHigh, hexOutDataLow
Returns: nothing
receiveProgrammerData
Receives a 14-bit word (plus start and stop bits) to the Receives: nothing
memory of an external application PIC. NOTE: This Uses: W, temp, hexOutDataHigh, hexOutDataLow
function is not yet implemented in the user interface.
Returns: hexInDataHigh, hexInDataLow
sendProgrammerCommand
Sends a 6-bit word to an external application PIC.

Receives: hexOutDataLow
Uses: W, temp, hexOutDataLow
Returns: nothing

8.2.8 PROGRAMMING UTILITY SUBROUTINES


getHexByteFromTerm
Reads two ASCII bytes from the terminal and creates a hex Receives: nothing
byte, which is stored in W.
Uses: W, temp
Returns: nothing
setProgHex
Converts an ASCII hex value in W to a binary value and Receives: W
return it in W.
Uses: W
Returns: W
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 34

putHexByteToTerm
Converts a two-digit hex value in W into 2 ASCII values Receives: W
and send them to the terminal.
Uses: W, temp
Returns: W
programmerDelay
The programmer delay is a fixed delay used only by the Receives: nothing
programming subroutines.
Uses: W, DCOUNT1, DCOUNT2
Returns: W
8.2.9 HELP FUNCTION
help
Displays the Help Screen to the terminal. Reads = as row Receives: nothing
of - and 0 as END.
Uses: W, DCOUNT1
Returns: nothing
8.2.10 IR MODULE SUBROUTINES
getIR
Function subroutine to do an example of reading the input Receives: nothing
from a universal TV remote on RB0 and displaying it to the Uses: W, IRCOUNTER, BYTE1, BYTE2, BYTE3
terminal. NOTE: The program will wait indefinitely until Returns: BYTE1, BYTE2, BYTE3
some signal is received.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 35

9 YOUR FIRST PIC ASSEMBLY CODE PROJECT


To get you started writing code as quickly as possible, step-by-step instructions are given describing how to create a new
project. You will also find a skeleton code template for your use.

9.1 GETTING STARTED WITH MPLAB


1
2

Start MPLAB (Start>Programs>Microchip MPLAB>MPLAB).


Select File>Open and select c:\progra~1\mplab\template\code\f873temp.asm.

Figure 9-1: The MPLAB IDE environment.


3

Select File>Save As and save the template as your own file. You will be editing the code in this file and coming
back to it often so choose an appropriate file name and directory.

Select Project>New Project. Choose a file name and save it to the same directory as in Step 3. The project and the
projects files must be in the same directory.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 36

In the Edit Project window, click the Change button


next to Development Mode. Under the Tools tab, choose
MPLAB-SIM Simulator. For Processor choose
PIC16F873. Click OK.

Click on your file in the Project Files window (it will be


yourfilename [.hex]) and click Node Properties.

Figure 9-2: The Edit Project window


7

Set all the options in the Node Properties window as shown in Figure 9-3. Click OK when youre finished.

Figure 9-3: The Node Properties window


8

Select the file you created and click Add Node to add your file to your project.

Click OK to leave the Edit Project window.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 37

You now have a working piece of code that you can build onto. When you are ready to assemble your program click on
Project>Build All.

9.2 THE PIC16F87X ASSEMBLY TEMPLATE


We will write a program in assembler that will flash an LED on and off whenever a push button is pressed. The LED will
be connected to RC0 (PORTC, bit 0) in series with a resistor (refer to Section 6.1), and the push button will be connected to
RC1, (PORTC, bit 1). Let us start by examining the code template you saved earlier. The first block contains notes on using
this template, identifies the code and other files used with this file, and includes a section for notes (the complete source
code, without interjections, can be found at http://www.ee.ualberta.ca/~ee401/examples/ee401a.asm).
***********************************************************************
;
This file is a basic code template for assembly code generation
*
;
on the PICmicro PIC16F873. This file contains the basic code
*
;
building blocks to build upon.
*
;
*
;
If interrupts are not used all code presented between the ORG
*
;
0x004 directive and the label main can be removed. In addition
*
;
the variable assignments for 'w_temp' and 'status_temp' can
*
;
be removed.
*
;
*
;
Refer to the MPASM User's Guide for additional information on
*
;
features of the assembler (Document DS33014).
*
;
*
;
Refer to the respective PICmicro data sheet for additional
*
;
information on the instruction set.
*
;
*
;
Template file assembled with MPLAB V4.00 and MPASM V2.20.00
*
;
*
;**********************************************************************
;
*
;
Filename: EE401a.asm
*
;
Date:
June 6, 2001
*
;
File Version: 1.0
*
;
*
;
Author: Ben Bathgate
*
;
Company: UofA EE401 project course
*
;
*
;**********************************************************************
;
*
;
Files required: p16f873.inc
*
;
*
;**********************************************************************
;
*
;
Notes: This program will turn on and off a LED connected to RC0 *
;
if RC1 is at a logic high
*
;
*
;**********************************************************************

Take a look at p16f873.inc to see how the assembler converts labels to register addresses and arguments.
list p=16f873
#include <p16f873.inc>

; list directive to define processor


; processor specific variable definitions

When you programmed your PIC with the Host program in Part II, you were shown how to manually set the
configuration bits. This is how to set them in your code. Change your code as below (note the changes made):
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC & _WRT_ENABLE_ON &
_LVP_OFF & _CPD_OFF
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 38

; '__CONFIG' directive is used to embed configuration data within *.asm file.


; The labels following the directive are located in the respective *.inc file.
; See respective data sheet for additional information on configuration word.

These are variables and their register address assignment. w_temp resides in register memory location 0x20. This is the first
location of the General Purpose Registers (data RAM). Add three more variables as shown (temp0, temp1, and
temp2):
;***** VARIABLE DEFINITIONS
w_temp EQU 0x20
status_temp EQU 0x21
temp0 EQU 0x22
temp1 EQU 0x23
temp2 EQU 0x24

; variable used for context saving


; variable used for context saving

;**********************************************************************
ORG
0x000
; processor reset vector
clrf
PCLATH
; ensure page bits are cleared
goto
main
; go to beginning of program

Comment out this section or delete it (it has been deleted in the source code file):
;
;
;
;
;

ORG
movwf
movf
bcf
movwf

0x004
w_temp
STATUS,w
STATUS,RP0
status_temp

isr code can go here or be located as a call subroutine elsewhere

;
;
;
;
;
;

bcf
movf
movwf
swapf
swapf
retfie

STATUS,RP0
status_temp,w
STATUS
w_temp,f
w_temp,w

;
;
;
;
;

interrupt vector location


save off current W register contents
move status register into W register
ensure file register bank set to 0
save off contents of STATUS register

; ensure file register bank set to 0


; retrieve copy of STATUS register
; restore pre-isr STATUS register contents
; restore pre-isr W register contents
; return from interrupt

main

This is where our code goes. Fill-in the following:


bsf
bcf
movlw
movwf

STATUS,RP0
STATUS,RP1
b11111110
TRISC

bcf

STATUS,RP0

LOOP
btfsz
bsf
call
bcf
call
goto

PORTC,1
PORTC,0
onesec
PORTC,0
onesec
LOOP

; change to register bank 1


;
;
;
;

binary value, 1 bit per port bit


RC0 set to digital output,
all other PORTC as inputs
change to register bank 0

;
;
;
;
;
;

test status of bit1 of PORTC


if high, set PORTC bit 0, turn on LED
call one second delay routine
clear PORTC bit 0, turn off LED
call one second delay routine
loop infinitely turning LED on and off

End of main program code, one second delay subroutine follows:


onesec
; one second delay subroutine
movlw
d100
; decimal value one hundred
movwf
temp0
; load value d100 into variable temp0
movlw
d13
movwf
temp1
; load value d13 into variable temp1
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 39

movlw
movwf
onesec_a
decfsz
goto
decfsz
goto
decfsz
goto
return
END

d250
temp2

; load value d250 into variable temp2

temp2,F
onesec_a
temp1,F
onesec_a
temp0,F
onesec_a

;
;
;
;
;
;
;

decrement temp2 by 1, result in temp2


innermost loop
decrement temp1 by 1, result in temp1
middle loop
decrement temp0 by 1, result in temp0
outer loop
return from subroutine

; assembler directive 'end of program'

After the END directive, the assembler stops looking at the file. Any code after this point is ignored. Save and compile this
program.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 40

10 MPLAB SIMULATOR
MPLAB has a built-in microprocessor simulator. If you compile assembly code you can test its operation by simulating
what it does. The simulator is designed to step through your code to view registers, stimulate pins, etc to debug your
code. Remember, however, the simulator does have limitations.

10.1 USING THE SIMULATOR TO TEST CODE


1

After starting up MPLAB, select menu


Options then Development Mode.

Set the development mode to MPLAB-SIM


Simulator.

Select menu Window then Program


Memory. This shows the current program
memory.

Figure 10-1: Development Mode Dialog Window


A quick breakdown of Figure 10-2:
The first column (1-27 shown here) is the line
number.
The second column, 0000 through 001A, is the
program memory address.
The third column is the machine code, the
binary microprocessor control code and passed
parameter.
The fourth column is for labels (currently
truncated to six characters).
The fifth column
instruction.

shows

the

assembler

The last column shows the parameters passed


to the machine instruction in hexadecimal.

Note that the first memory location, 0000, holds


an instruction to clear location hexA. The
second memory location holds a goto main
(main is at memory location 0002). Memory
location 0014 holds a goto onesec_a. See that
the first part of the instruction 28 of 2813 is the
goto and the second half is the memory location
0013.

Figure 10-2: Program Memory Window

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 41

From the pull-down menu, select Window>Special


Function Registers to open the Special Function
Register Window (Figure 10-3). This window allows
us to see the PORTC port.

Figure 10-3: Special Function Register Window

Select Debug>Simulator Stimulus>Asynchronous


Stimulus to open the Asynchronous Stimulus
Dialog window. This window enables you to assign
a pin to a button.

Right-click on the Stim 1 (P) button and select Assign


Pin. The Pin Section window will appear. Doubleclick on RC1. You have just assigned a pin to the
button.

Now we want to assign an action to the button. Rightclick on the RC1 (P) button in the Asynchronous
Stimulus Dialog window and select Toggle.

Move both the Special Function Registers and


Asynchronous Stimulus Dialog windows to allow
you to view these along with your source file.

Figure 10-4: Asynchronous Stimulus Dialog

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 42

Figure 10-5: MPLAB Simulator environment


9

Next, well start stepping through your code. Press F6 (Reset) or select Debug>Run>Reset. If you feel you need to
start over at any time, just press F6.

10 In your source file a line is highlighted indicating the next instruction to be executed. The highlighted text should be
clrf PCLATH.
11 In the Debug>Run>Step window you will notice F7 single steps through your program. Slowly step through your
program by repetitively pressing F7. Note that the PCL register is highlighted in red as the simulator steps through the
program memory and changes to the program memory location (the value is the location highlighted in the Program
Memory Window).
See menu Debug>Run for running, stopping, single stepping, and reset commands.
Set breakpoints by right clicking on a line of code, and selecting Breakpoint.
The stopwatch under Window>Stopwatch is useful for timing how long code takes to run. Set breakpoints before and
after, then run it.
Other important areas not covered here include Trace, Arm Counter, Stimulus from a File, and Environment Setup.
These items are explained in the MPLAB Users Guide, the MPLAB Help Files, and on the Microchip web site
(http://www.microchip.com). The simulator is also discussed in Microchips PICSTART PLUS Mechatronics Getting
Started Guide (http://www.ee.ualberta.ca/~ee401/reference/PICmech.pdf).
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 43

11 USING THE DEBUG.HEX CODE


The best way to think about designing your project should include a very minimal amount of programming. The
following are two examples using the ADC input and the SPI respectively. Only a few changes have been made to
DEBUG.HEX providing you with full functionality.

11.1 THE ADC LINES


Writing a program to access the analog-to-digital converter will require you to read the section in the PIC16F87x data
sheet. There is a simple method that must be followed to set registers so the required pin is set as an analog input. Unlike
setting a single pin as a digital input or output, the entire port A must be configured all at once which allows some but not
all pin combinations. The ADCread command takes the value in W as the AN port number where the input is read. The
changes to the original routines are have been colour coded: the original code is shown in pink and the replacement code
is shown in green. Other notable changes that may not be obvious are highlighted in red. The following is a code example
using the provided ADC subroutines in the debug code.

;************************************************************************
;
Program Header
;
- Documentation about your program is very important for not
;
only your information but also to guide the person marking your project
;
through your thought process.
;
;
The following program is a simple version of a volt meter. The
;
program takes analog input from RA1 and displays a binary readout on
;
the 8 Port B pins. The input is a voltage from any supply between GND
;
and VCC. It is wise to use a current limiting 470 Ohm resistor on the input.
;
The output from each pin can be run through a 470 Ohm resistor- LED pair
;
or collectively as the input to an LED digit display.
;
;************************************************************************
;
Filename:
ADCsample.asm
;
Start Date:
July 10, 2001
;
Last Revision Date:
July 11, 2001
;
File Version:
1.0
;
;
Author:
Michael Cumming
;
Company:
University of Alberta
;************************************************************************
;
Files required:
P16F873.inc
;
16F873.lkr
;************************************************************************
;
Notes:
;************************************************************************
list p=16f873
#include <p16f873.inc>

; list directive to define processor


; processor specific variable definitions

; '__CONFIG' directive is used to embed configuration data within .asm file.


; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _XT_OSC &
_WRT_ENABLE_ON & _LVP_OFF & _DEBUG_OFF & _CPD_OFF
errorlevel -302
errorlevel -305
errorlevel -306

; These remove unwanted warnings


; from the compile information listing

;***** VARIABLE DEFINITIONS


;**** General Variables
char
EQU
0x20
newData
EQU
0x21
Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 44

;********* CONSTANTS *************


;** Directive Data Constants
BANK0
EQU
0x0000
BANK1
EQU
0x0080
BANK2
EQU
0x0100
BANK3
EQU
0x0180
PAGE0
PAGE1
PAGE2
PAGE3

EQU
EQU
EQU
EQU

0x0000
0x0800
0x1000
0x1800

TRUE
FALSE

EQU
EQU

1
0

;**********************************************************************
ORG
0x000
; processor reset vector
clrf
PCLATH
; ensure page bits are cleared
goto
main
; go to beginning of program
main
start
banksel
clrf
banksel
clrf

BANK1
TRISB
BANK0
PORTB

; Port B is used as an output display

pagesel
call
pagesel

PAGE1
initADC
PAGE0

; Call to ADC init. routine in Page1 of Program memory

mainLoop
pagesel
movlw
call
pagesel

PAGE1
0x01
readADC
PAGE0

movf
movwf

newData,W
PORTB

; The newData value is displayed on Port B

mainLoop

; Repeat main loop

goto

; An AD conversion is done on AN1 and the result


; is returned in the newData variable.

;****************************************************************
;***
PAGE 1 Subroutines
;****************************************************************
org
PAGE1
;****************************************************************
;*******************************************************************
;
ADC Module Subroutines
;*******************************************************************
;*******************************************************************
;
Function subroutine to initialize RA0 as an ADC input.
;
Sets the (right justified) data flag.
; receives: nothing
; uses: W
; returns: nothing
;*******************************************************************
initADC
banksel
BANK1
; Move to Bank 1
;

movlw

0x82

movlw

0x02

; Set all AN pins on Port A as analog


; and right justify data in ADRESH and ADRESL
; Set all AN pins on Port A as analog

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 45

; and left justify data in ADRESH and ADRESL


; See page 111 and 112 of the PIC16F87x data sheet for
; details on ADCON0 and ADCON1
movwf

ADCON1

banksel

BANK0

; Move to Bank 0

movlw
movwf

0x01
ADCON0

; Shutoff all ADC function and set default


; selected channel to A0
; Also selects: A/D clock = Fosc/2

movf
andlw
movwf

PORTA,W
0x10
PORTA

; Initialize Port A values to 0

banksel
bcf

BANK1
PIE1,ADIE

; Set to bank1
; Disable A/D interrupt

movf
iorlw
movwf

TRISA,W
0x2f
TRISA

; Initialize Port A Analog ANs to inputs

banksel

BANK0

; Move to Bank 0

bcf

PIR1,ADIF

; Clear A/D interrupt flag

return
;*******************************************************************
;
Function subroutine to initiate a read of ADC port pins
;
which stores its value in ADRESH, and ADRESL (right justified)
; receives: W - <0 to 4> pin to read
; uses: W, char
; returns: nothing
;*******************************************************************
readADC

;
;
;
;
;
;
;
;
;
;
;
;

movwf

char

swapf
bcf
rrf
bsf
movf

char
STATUS,C
char
char,0
char,W

movwf

ADCON0

bsf

ADCON0,GO

; Start A/D conversion (sets bit 2)

btfsc
goto

ADCON0,GO
$ - 1

; Repeat until the GO bit is automatically


; set low by hardware

bcf

PIR1,ADIF

; Clear A/D interrupt flag


; Values are now stored in ADRESH and ADRESL

movlw
call
movlw
call
movlw
call
movlw
call
movlw
call
movlw
call

d'13'
putUART
d'10'
putUART
'V'
putUART
'a'
putUART
'l'
putUART
'='
putUART

; Move input value into the ADC


; pin selection bits
; Set the enable bit 0

; Print Carriage return


; Print Line Feed

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 46

movf

ADRESH,W

; ADC value is10 bits and is


; stored in the ADRESH and ADRESL
; The top 8 bits of the value are moved to W

call

putHexByteToTerm

; registers when a read is


; conducted.

;
;
;

banksel BANK1
movf ADRESL,W
banksel BANK0

call

putHexByteToTerm

return
END

; Directive 'end of program'


; Code reaching this point may perform erratically.

Part III Beyond Getting Started: Autonomous Mode and Advanced Programming Techniques

Page 47

Part IV
Examples: Both Simple and Complex

Part IV Examples: Both Simple and Complex

Page 48

12 WORKING EXAMPLES
This is the beginning of the last section. Contained are a number of examples with code available for your use as either a
complete operational module or a starting point for your own ideas.
With the exception of the Motor Speed Controller and the Shaft Encoder, all of these examples should be functional in
both Hosted mode and Autonomous mode.

12.1 SERVO MOTORS


Using the PWM output of the MicroBoard, it is
possible to control a servo. Most servos operate
safely when the period of the input signal is
between 10 to 30ms; unfortunately, the built-in
PWMs on the MicroBoard can only output a
maximum 4ms period. Normally, one would use
an actual servo controller to attain the desired
period. This setup should work with some servos
but may produce undesirable effects with others. If
youd like to use servos in your project and have a
guarantee that theyll work properly, design your
own functions and timers such that the servo will function within its safe operating range.
The servo receives a 0.5 to 2.5ms pulse every 10 to 30ms (or 4ms in this case). The values between 0.5 and 2.5 correspond to
a different angle of the servo arm. The 0 point is at approximately 1.5ms and a change of 0.5ms will cause the servo arm to
move by about 45. A normal servo will have a 200 range of motion and will start to scream if you attempt to exceed
this (by setting a duty cycle outside the 0.5 to 2.5ms range). If your servo starts to grind, remove the power immediately or,
at very least, quickly return the servo to a normal duty cycle.
12.1.1 TESTING A SERVO IN HOSTED MODE
NOTE: This example is fairly straightforward, but keep in mind that servos are delicate; any deviation from the
procedure can damage your servo beyond repair very quickly!
1

Connect the servos red wire to the 5V source on the auxiliary power connector on the MicroBoard (these are the six
pins near the top of the board. Pin 6 is the 5V source). Connect the servos black wire to ground (pin 2 or 3 on the
auxiliary power connector). If youre worried about causing a brownout, use an external 5V source to supply the
servo with power.

Connect the PWM1 output (PWM1 is RC2 on the PIC which corresponds to pin 13) to one end of an orange wire.

Start a HyperTerminal session and execute the following commands:


>> pwmstart1
>> pwmperiod ff
>> pwmduty1 75

- sets the PWM to a 4ms period


- sets the duty cycle to about 1.5ms

Tap the free end of the orange wire against the yellow servo control wire. If the servo jumps to it's maximum range
and starts screaming, remove the wire immediately! Check your duty cycle to make sure that its within the
allowed range.

Part IV Examples: Both Simple and Complex

Page 49

If the servo moves to the 0 point (the desired response), plug the orange wire in all the way.

You can change the servos position by changing the duty cycle using the pwmduty1 command:
>> pwmduty1 hh

- where hh is a value from 30 to a0

Any value outside this range could damage the servo.


12.1.2 TESTING A SERVO IN AUTONOMOUS MODE
Steps 1 to 3 are the same as above, except now the MicroBoard will take input from the B port to position the servo.
1

Burn the supplied servocontroller.hex file (http://www.ee.ualberta.ca/~ee401/examples/servo/servocontroller.hex) to


the PICs memory. The important bits of the source code (http://www.ee.ualberta.ca/~ee401/examples/servo/
servocontroller.asm) are shown below:
main
start
pagesel
call
pagesel

PAGE1
initializeChip
PAGE0

pagesel
call
pagesel

PAGE1
startPWM1
PAGE0

; Start the PWM on line RC2

pagesel
PAGE1
movlw h'75'
call
pagesel

setPWMDuty1
PAGE0

banksel
bsf
bsf
bsf
bsf
banksel

BANK1
PORTB,4
PORTB,5
PORTB,6
PORTB,7
BANK0

; initialize the entire Chip to known state

;
;
;
;

set duty
h'7f' is
h'30' is
set PWM1

cycle to servos 0 position


about 0
the servo min, h'a0' is it's max
Duty

; set last 4 ports of B to inputs

mainLoop
; NOTE: These values may be nowhere NEAR the actual angles!
; They are, however, within the safe movement range of h'30' - h'a0'
; Exceeding these values will blow up your servo!
movlw
btfsc
movlw
btfsc
movlw
btfsc
movlw
btfsc
movlw
movwf

h'75'
PORTB,4
h'35'
PORTB,5
h'5C'
PORTB,6
h'84'
PORTB,7
h'9f'
temp

pagesel
movf

PAGE1
temp,W

; set servo position to roughly 0

; set servo position to about 180 via temp


; set servo position to about 90

via temp

; set servo position to about +90

via temp

; set servo position to about +180 via temp

call

;
;
;
;
setPWMDuty1 ;

pagesel

PAGE0

Part IV Examples: Both Simple and Complex

via temp

select upper memory to call duty function


moves temp to W to be passed to duty-change
function (pagesel clears the W register,
so don't try and tranfer to W too soon)
set PWM1 period based on the W register value

; back to lower memory


Page 50

goto

mainLoop

; repeat main loop

Connect power to the MicroBoard. Connect the orange wire to the yellow input as before (again, if the servo begins to
scream, remove the wire). The servo should move to the 0 position. If not, unplug everything and examine your
setup thoroughly.

The servo position can be changed by setting pins b4 to b7 high using the set and clear commands or by taking
inputs from an external circuit. The servo will remain in position as long as the line is held high, returning to 0 when
the input stops.

12.2 SPI BAR GRAPH


Use of a shift register in conjunction with the PIC creates the opportunity for more digital outputs. This setup uses a shift
register to create eight extra digital outputs each accessed using the SPI unit. The schematic below outlines the necessary
connections (note that you will need eight LEDs and eight 470 resistors in addition to the 74HC595 shift register chip):
Circuit Diagram

470

Logic Diagram
+5V

16

15

14
13
1
12

11

16 RC5
21 RB0
11 RC0
14 RC3

6
7
8

595
Shift
Register

10

ALL
RED ON

h07

RED +
YELLOW

h3F

ALL
ON

hFF

RED +
YELLOW

h3F

PIC16F873
MicroBoard

NOTE: Remember to connect a resistor in series with all outputs of the PIC to limit current and protect the PIC.
12.2.1 SPI BAR GRAPH IN HOSTED MODE
1

Connect the shift register and LED array using the above diagram.

Connect the serial cable and power and begin a HyperTerminal session.

Type the following (this will initialize the SPI unit and make sure all the LEDs are off):
>>
>>
>>
>>
>>
>>

spiinit
output c0
clear c0
spitrans 00
set c0
clear c0

initializes the SPI unit


selects the clock pulse pin
make sure its off
set all eight 595 outputs to zero
sends the clock pulse
resets the clock pulse pin

Cycle through the light levels as you wish. Try out different hexadecimal values:
>> clear c0
>> spitrans hh
>> set c0

Part IV Examples: Both Simple and Complex

; Where hh is a hexidecimal value


; send clock pulse
Page 51

>> clear c0

For a bar-graph-esque illumination, use the values 00, 01, 03, 07, 0f, 1f, 3f, 7f, and ff. This will light all the LEDs
in order from red to green (calculate it out if you can't figure out why these values work: 1 hex digit = 4 binary digits.
Example: h03 = b00000011, h1f = b00011111, etc).

12.2.2 SPI BAR GRAPH IN AUTONOMOUS MODE


The Autonomous code is a basic program that cycles through three preset light levels. The code is fairly bulky and not that
functional, yet it proves to be a nice example. The MicroBoard will light all the red LEDs, then it will add the yellow LEDs,
and finally will light the green LEDs. This is accomplished by calling the cmdSPIInit command and the transferSPI
function in the original DEBUG.HEX source code. Watch the use of the PAGESEL command: using it clears the W register,
so don't pass your values too soon!
******** NEW VARIABLE DECLARATIONS ********
COUNTH
EQU
0x56
; variables for delayA and delayLong functions
COUNTL
EQU
0x57
COUNTH2
EQU
0x58
******** MAIN CODE *************
main
start
pagesel
call
pagesel

PAGE1
initializeChip
PAGE0

; Initialize the entire Chip to known state

cmdSPIInit
temp

; initialize the SPI device on lines b0,c0,c3,c5


; clear the temporary register

movlw
movwf

h'07'
temp

; move light value to the W register


; set the temp register to W

pagesel
movf
call
pagesel

PAGE1
temp,W
transferSPI
PAGE0

;
;
;
;

bsf
bcf

PORTC,0
PORTC,0

; latch the data to the shift registers

call

DelayLong

movlw
movwf

h'1f'
temp

; move value to the W register


; set the temp register to W

pagesel
movf
call
pagesel

PAGE1
temp,W
transferSPI
PAGE0

;
;
;
;

bsf
bcf

PORTC,0
PORTC,0

; latch the data to the shift registers

call

DelayLong

movlw
movwf

h'ff'
temp

; move value to the W register


; set the temp register to W

pagesel
movf
call

PAGE1
temp,W
transferSPI

; select upper memory


; moves temp to W to be passed to the SPI
; Set SPI period based on the W register vlaue

call
clrf
mainLoop

Part IV Examples: Both Simple and Complex

select upper memory


moves temp to W to be passed to the SPI
Set SPI period based on the W register vlaue
back to lower memory

select upper memory


moves temp to W to be passed to the SPI
Set SPI period based on the W register vlaue
back to lower

Page 52

pagesel

PAGE0

; back to lower

bsf
bcf

PORTC,0
PORTC,0

; latch the data to the shift registers

call

DelayLong

movlw
movwf

h'1f'
temp

; move value to the W register


; set the temp register to W

pagesel
movf
call
pagesel

PAGE1
temp,W
transferSPI
PAGE0

;
;
;
;

bsf
bcf

PORTC,0
PORTC,0

; latch the data to the shift registers

call

DelayLong

goto

mainLoop

select upper memory


moves temp to W to be passed to the SPI
Set SPI period based on the W register vlaue
back to lower

; Repeat main loop

;**********************************************************************
DelayA
TenMs
movlw
movwf
movlw
movwf

d'13
COUNTH
d'250'
COUNTL

Ten_1
decfsz
goto
decfsz
goto

COUNTL,F
Ten_1
COUNTH,F
Ten_1

; Inner Loop
; Outer Loop

return
;**********************************************************************
DelayLong
LongMs
;movlw
;movwf

d'3'
COUNTH2

; 10ms * value in quotes is duration of Long

Ten_2
decfsz
goto

COUNTH2,F
Ten_3

; Loop

return
Ten_3
call
goto

DelayA
Ten_2

A much better algorithm can be made by applying a logical shift operation (LSL to fans of the 68000-series processors),
using the PIC's rotate function and a bsf command like so:
clrf
call
bsf
call
rlf

temp
LightItUp
temp,0
LightItUp
temp,F

; temp set to 0000 0000


STATUS,C = 0
; turn on lights based on temp
; temp is now 0000 0001
STATUS,C = 0
; turn on lights based on temp again
; temp is rotated left, and stored back in itself
; (hence the ,F)
Part IV Examples: Both Simple and Complex
Page 53

bsf
call
rlf

temp,0
LightItUp
temp,F

bsf
call

temp,0
LightItUp

;
;
;
;
;
;
;

temp
temp
turn
temp
temp
temp
turn

= 0000 0010
STATUS,C = 0
= 0000 0011
STATUS,C = 0
on lights based on temp
is rotated left, and stored back in itself
= 0000 0110
STATUS,C = 0
= 0000 0111
STATUS,C = 0
on lights based on temp

Get the idea? This would sequentially light the first two LEDs in your array. Use rrf to reverse the process.
If a 1 is shifted out of the register (either left or right) it will be moved to the carry register. This allows you to test if the
register is full and execute operations accordingly (if your bar graph is maxed out, then start decrementing values). The
value of the carry register is rotated to the front of the register, so keep this in mind if you have other operations that might
affect the STATUS register. You can implement a technique similar to this to light only one LED and have it move back and
forth along the row (PIC-LED Pong perhaps?).

12.3 MOTOR SPEED CONTROLLER


Using a looping routine, one can monitor a value and adjust another based on that input. The motor speed controller
repeatedly checks the ADC value and adjusts the PWM duty cycle accordingly.
Start Up

Init PWM
Init ADC

Main Loop

Duty
Down

Read
ADC

ADRESH - 02
C=1

C=1

Z=1

ADRESL - 00
Z=1

C=0
C=0

Duty
Up

Done
<2.5V
Increase
Duty Cycle

>2.5V
Check
ADC

Decrease
Duty Cycle

=2.5V

Check ADC
Flow Chart

Output
Speed

Figure 12-1: Motor Speed Controller Flow Charts


Attach PWM2 output (RC1, pin 12) to the motor's positive terminal through the H-bridge on the MicroBoard (into the Hbridge through pin 7 and out to pin 6. Refer to Appendix A MicroBoard Schematic and the L293 Motor-driver chip
data sheet).
The positive terminal of the motors analog output is connected to the PICs RA0 input (ADC line). Connect two LEDs to
pins RC2 and RC3 (dont forget to add a couple pull-up resistors to limit current. 470 ones will work just fine).

Part IV Examples: Both Simple and Complex

Page 54

7
L293D

Motor _
In

Motor _
+ Out

12 RC1/PWM2
13 RC2
14 RC3

21 GND
2 RA0
PIC16F873
MicroBoard

Figure 12-2:

Motor Box (with inputs and outputs) and Motor Speed Controller Schematic

The program below checks the voltage on the ADC port, samples it against a hexadecimal value that should be equivalent
to 2.5V, and then adjusts the duty cycle such that it brings the ADC value closer to the 2.5V mark. The code assumes that
the motor will output 0V (hexadecimal 0000) at its stopped speed, and 5V (hexadecimal 03ff) at its maximum speed. If the
motor only outputs to a certain ADC range (say 0100 to 02ff), the code would need to be modified to check for that.
The code also assumes that the delay is long enough to allow the ADC to catch up with the changes in the motor speed;
this may not be the case. In terms of writing the output to the screen, the adcread command automatically prints to the
UART when it is called.
**** ADDED VARIABLE DECLARATIONS ****
COUNTH
COUNTL

EQU
EQU

0x56
0x57

**** MAIN CODE ********


main
start
pagesel
call
pagesel

initializeChip
initializeChip
PAGE0

; Initialize the entire Chip to known state

pagesel
call
pagesel

initializeUART
initializeUART
PAGE0

; Initialize the serial port

pagesel
call
pagesel

PAGE1
startPWM2
PAGE0

; do PWM with CCP2(RC1)


; (intitialize the PWM on RC1)

pagesel
movlw
call
pagesel

PAGE1
0xff
setPWMperiod
PAGE0

; set long PWM period into W, pass it to setter


; set PWM period

pagesel
call

PAGE1
initADC

; initialize the ADC

Part IV Examples: Both Simple and Complex

Page 55

pagesel

PAGE0

banksel
bcf
bcf
banksel

BANK1
TRISC,2
TRISC,3
BANK0

; set RC2,3 to output (monitor motor correction)


; green LED to RC2 / red LED to RC3
; green is duty up / red is duty down

mainLoop
bcf
bcf
call
call

PORTC,2
PORTC,3
Delay
cmdADCRead

; clear status lights


; read data on ADC line, output it to the UART
; and store data in ADRESL and ADRESH registers

testhi
movlw
subwf

h'02'
ADRESH,W

; move h'02' to W (upper byte of h'0200')

btfsc
goto
btfss
goto
goto

STATUS,Z
testlo
STATUS,C
DUTYup
DUTYdown

;
;
;
;
;

check to see if high byte is equal to h'02'


if equal, check lower byte
check if high byte is greater/less than h'02'
if less (c=0) increase duty cycle of PWM
if greater than (c=1) decrease PWM duty cycle

testlo
banksel
movlw

BANK1
h'00'

subwf
banksel

ADRESL,W
BANK0

btfsc
goto
goto

STATUS,Z
mainLoop
DUTYdown

;
;
;
;

bsf
pagesel
movlw
addwf
pagesel

PORTC,2
PAGE1
d'1'
CPR2L,F
PAGE0

; set green light on


; put '1' in the W register
; increment 8 MSBs of PWM2 duty cycle

goto

mainLoop

; Repeat main loop

bsf
pagesel
movlw
subwf
pagesel

PORTC,3
PAGE1
d'1'
CCPR2L,F
PAGE0

; set red light on

goto

mainLoop

; move h'00' to W [lower byte of h'0200'


; approx 0.5 * h'03ff' (2.5 volts)]

check to see if high byte is equal to h'00'


if equal, return to top
if not, low byte MUST be greater than h'00'
must decrease PWM duty

DUTYup

DUTYdown

; put '1' in the W register


; decrement 8 MSBs of PWM2 duty cycle
; Repeat main loop

This entire routine can be performed step-by-step in Host mode. Read the ADC line using the adcreadx command
(where x is and ADC line 0 to 4), and then modify the PWM duty cycle accordingly using pwmduty2 hh:
>> pwmstart2
>> pwmperiod ff

- starts the PWM connected to RC1


- sets full period with 50% duty cycle

>> adcinit
>> adcread0

- initialize the ADC


- read the ADC line on RA0

Part IV Examples: Both Simple and Complex

Page 56

1f0
>> pwmduty2 82
>> adcread0

- which is less than 50% (1f0/3ff = 48%)


- so increase PWM duty slightly
- check again and adjust accordingly, etc...

12.4 SHAFT ENCODER


The shaft encoders mechanical workings consist of a rotating disk
with a half circle open space and two IR LED/detector sensors, one
at the disks side and the other at the bottom. Upon some careful
investigation, you will notice four pins coming out of each sensor.
Two will be connected together on each and a brown wire ties the
two connections together and also to ground.
By testing the impedance of each of the other two pins with respect
to ground, you will notice that one will give an infinite resistance
while the other gives a reasonable reading. By process of
elimination, you can conclude that the infinite side is the transistor
side (orange lead) while the reasonable side must be the IR LED
(yellow lead). Apply a 5V load to the LED side (dont forget a
resistor in series with it; 330 will do) and test various values of resistance on the transistor side until you can achieve an
on/off value that switches from 0V to 5V. You should find that a 10K resistor will work just dandy.
As per Figure 12-3, solder the wires and resistors in place. Hook the transistor-side outputs to pins b0 and b1 (on a board
without hardware flow control enabled; see Section 5.9). It may be a good idea to add a couple current-limiting resistors to
these lines to protect the PIC. Connect the appropriate pins to 5V or ground. You can hook up two LEDs to pins b2 and
b3 to monitor the status of the wheel.
+5V
330

10k

Close-up of Sensor Wiring

330
Top

10k

Bottom

LED

phototransistor

21 RB0
22 RB1
23 RB2
24 RB3

Vout
330

PIC16F873

10k

+5V

MicroBoard

Figure 12-3: Shaft Encoder Schematic

Part IV Examples: Both Simple and Complex

Page 57

Figure 12-4:

Shaft Encoder Flow Chart

The code below checks the status of the top and bottom switches and stores them in the two least significant bits of the
W_STAT_NEW register. It checks these against the same bits of the W_STAT register. They are compared following the flow
chart in Figure 12-4. The W_STAT register is then set with the values in the W_STAT_NEW register, and the direction
calculated is stored in the third bit (bit 2) of W_STAT.
******* NEW VARIABLE DECLARATIONS *******
COUNTH
COUNTL
W_STAT

EQU
EQU
EQU

0x56
0x57
0x58

W_TURNS
W_POWER
W_STAT_NEW

EQU
EQU
EQU

0x59
0x5A
0x5B

; delay function variables


;
;
;
;
;
;
;
;

status register of wheel:


0 is top switch
1 is bottom
2 is wheel direction
# of turns made by wheel (not implemented)
absolute value of turns (not implemented)
new status temp register
(same bit config as W_STAT)

******* MAIN CODE **********


main
start
pagesel
call
pagesel

initializeChip
initializeChip
PAGE0

;
; Initialize the entire Chip to known state

banksel
bsf
bsf
bcf
bcf

BANK1
TRISB,0
TRISB,1
TRISB,2
TRISB,3

; set RC1,0 to input (1 btm, 0 is top switch)


; monitors the LED/transistor switches
; set light outputs green if W_STAT,2 = 1

bcf

TRISC,1

; intialize ground pins when PWM's not active


;
(not implemented)

Part IV Examples: Both Simple and Complex

Page 58

;
;

bcf

TRISC,2

; set motor direction output grounds on


;
(not implemented)

banksel

BANK0

bcf
bcf

PORTC,1
PORTC,2

; motor ports (not implemented)

clrf
clrf
clrf

W_TURNS
W_POWER
W_STAT

; turns the motor has made


; absolute power of motor (duty cycle)
; stat bits 3=Motor Direction, 2=Wheel
;
Direction, 1=Btm Sw 0=Top Sw

bcf
bcf

PORTB,2
PORTB,3

mainLoop
call
call
call

CheckSensors
DirectionDisp
Delay

goto

mainLoop

; call sensor check routine; set W_STAT register


; turn on LEDs to indicate direction

CheckSensors
clrf

W_STAT_NEW

; clear temp register

btfsc
bsf
bcf

PORTB,1
W_STAT,1
W_STAT,1

; test status of btm SW


; set registers btm switch flag s1
; else clear it

btfsc
bsf
bcf

PORTB,0
W_STAT_NEW,0
W_STAT_NEW,0

; test status of top SW


; set temp registers top switch flag s0
; else clear it

btfsc
goto
goto

W_STAT_NEW,0
NewTopOn
NewTopOff

; check condition of top switch vs last value

btfss
return

W_STAT,0

; if old off and new off, return

bcf

W_STAT,0

; set old top equal to new top

btfsc
bsf
bcf

W_STAT,1
W_STAT,2
W_STAT,2

; check new s1 to set direction


; set D = 1 if s1 on
; clear D if s1 is off

goto

checkend

; goto end of checking routine

btfsc
return

W_STAT,0

; if old on and new on, return

bsf

W_STAT,0

; set old top equal to new top

btfsc
bcf
bsf

W_STAT,1
W_STAT,2
W_STAT,2

; check new s1 to set direction


; clear if s1 on
; set D if s1 is off

goto

checkend

; goto end of checking routine

NewTopOff

NewTopOn

Part IV Examples: Both Simple and Complex

Page 59

checkend
return
DirectionDisp
bcf
bcf

PORTB,2
PORTB,3

btfsc
bsf
bsf

W_STAT,2
PORTB,2
PORTB,3

; check the wheel direction status bit


; set green light if d=1
; set red light if d=0

return
DUTYchange
pagesel

PAGE1

movf
btfsc
movwf
movwf

W_POWER,W
W_STAT,3
CCPR2L
CCPR1L

pagesel

PAGE0

; put '1' in the W register


; test wheel direction (which Duty to change?)
; increment 8 MSBs of PWM 2 duty cycle

return
;**********************************************************************
Delay
TenMs
movlw
movwf
movlw
movwf

d'13'
COUNTH
d'250'
COUNTL

Ten_1
decfsz
goto
decfsz
goto

COUNTL,F
Ten_1
COUNTH,F
Ten_1

; inner Loop
; outer Loop

return

This example leaves a turn counter to be implemented (fairly trivial, just increment/decrement the W_TURNS register
every time the W_STAT,2 bit is calculated). One could also use this program to control the speed and direction of a motor
using the PWM, the full code to do this is not included but some functions and registers have been set up and commented
out. Also, it is assumed no debouncing is needed; this may be something to investigate.

Part IV Examples: Both Simple and Complex

Page 60

13 MEDULLA: THE SOUND-SENSING ROBOT


This is the final milled version of the Medusa
sound-sensing robot. It is designed to detect 38kHz
IR beacons, loud sounds, and bumps to the front of
its chassis. It has three onboard op-amps, six sensor
inputs with pull-up resistors, and an external 7.2Vdc
battery unit for the PIC and the motors (which
draw 3V).

13.1 SENSORS AND PSP BOARD


The bot has three types of sensors: bump sensors, IR sensors, and sound sensors. All three run off the PSP board (Portable
Sensor Platform).
The microphones are each activated individually by the code, and a reading is sampled from them. This signal is filtered
to remove any DC signal, amplified by an op-amp, filtered again, and then passed over a reverse-biased diode to rectify
the signal and limit the voltage to about 5.1V maximum.
The bump sensors feed directly into PORTB, and the IR sensors are connected to the PSP.
The IR sensors detect a 38kHz pulse from an infrared beacon (actually works best at 41kHz, but factory specs say 38kHz),
and will track this beacon quite well at close range. For long-distance tracking, a better beacon must be used,
implementing at least three emitting diodes to increase the photon count. Additionally, the sensors should be wiped
down with alcohol swabs to remove grease from human hands. The PSP board connects both power and signals to the
MicroBoard and, as such, is a great method to test multiple platforms without resoldering or reconfiguring the sensor
arrays each time.
Medula has three sensor priority levels, sound being the lowest. If the robot is chasing a noise, it will leave its target to
pursue a recognized IR signal. If it hits an obstacle at any time, it will avoid the obstruction before resuming its normal
program.
An addition to the PSP is the microphone assembly board. This board contains the basic circuit to multiplex the
microphones and rectify the output. The input from the MicroBoard selects the active microphone; the signal of this unit is
then sent to the op-amp for magnification. Next, the signal is passed back to the microphone board where it is stripped of
its DC component, rectified, and clipped to ensure a nice 0 to 5V signal for the ADC input on the MicroBoard. If you
would like to improve performance, use a diode bridge to perform full-wave rectifying on the output signal.

13.2 BATTERY POWER


Medulla runs off a single 7.2V NiCd battery pack located between the MicroBoard and the two motors for the treads. This
battery supplies the regulators with voltage to power the board and the motors. Thus, both 5V and 7.2V are available for
use.
Part IV Examples: Both Simple and Complex

Page 61

A modified H-bridge mounting assembly allows the 7.2V input voltage to be converted to a 3V steady power source for
the motors. It is possible that 5V motors could be inserted in place of the 3V, in which case you would need to modify the
resistor ratio on the 3V-regulator board. This board employs an LM317 chip (variable voltage regulator) which takes an
input voltage and converts it to a Vout between 1.25V and 30V. The ratio of the two resistors on the board determines what
this value will be. Check the LM317 or LM117 data sheet for more information.
The capacitors between the input and output voltages and the ground help keep a nice accurate output voltage. The Hbridge plugs into a socket on this board, which in turn plugs into the MicroBoards H-bridge socket (piggyback style).
Pin 8 (the supply voltage pin) connects to the 3V regulator output, thus bypassing the MicroBoards H-bridge supply
voltage trace.

13.3 THE PROGRAM


The Autonomous code for Medulla is based on DEBUG.HEXs monolithic code modules (the Hosted mode program).
The main function has been deleted and replaced with a new set of routines. The main routine checks the status of the
sensors inputs and sets a corresponding bit in the neurons register. The program then checks the neurons and calculates
which motor neurons need to be activated. Finally, the program checks which motors are pending activation and switches
them on. A delay is then called and the process is repeated indefinitely. This code could be greatly improved with multiple
ADC lines and an interrupt- or multi-tasking-based system.
The main program is quite large so it is not included here. It is, however, available on the EE401 web site:
http://www.ee.ualberta.ca/~ee401/examples/medulla/phoenix.asm

13.4 QUIRKS
There is a threshold value in the sound recognition function, which allows you to cut out all lower power noise and not
use it in the evaluation process. Currently, the entire sound system runs by comparing only the eight most significant bits
of the input; this will be improved in the next version by checking all 16 input bits. The sound equipment also produces a
fair amount of noise, which could possibly be removed with more advanced filtering hardware.
3V motors are a little too weak for the current application. A 5V motor of the same size could easily replace the current
motors and provide a much stronger and more versatile locomotion system.
You may notice that three of the PSP pull-up resistors have been attached at only one end. This mainly serves to bridge the
gaps in the very small IR sensor output traces. Connecting these resistors puts far too great a load on the IR sensors,
causing erratic behaviour.

13.5 REFERENCE FILES


All relevant files for this project are available on the EE401 web site:
3v_regulator.brd
3v_regulator.sch

Eagle board and schematic files for the 5V to 3V H-bridge supply board

microphone_setup.brd Eagle board and schematic files for the microphone multiplexing/rectifying
microphone_setup.sch
pspboard.brd
pspboard.sch

Eagle board and schematic files for the sensor expansion board

phoenix.brd
phoenix.sch

assembler/hex files for primitive version of final PIC code (pin-outs for sensors in this file under
their declarations)

Part IV Examples: Both Simple and Complex

Page 62

14 SNAKE TURRET (MKII AUTONOMOUS VERSION)


NOTE: An artificial neural network (ANN) version of this robot is
available also. Please see the MicroBoard Advanced Manual for
various ANN examples.
Snake turret is a stationary robot that moves its head to track the
signal from a 38kHz infrared beacon. Its head is made up of five
IR sensors and a mercury switch. The PWM lines of the MicroBoard
are each connected to a motor. When the middle IR sensor sees
light, the PWMs are set to half speed. This allows slow correction
when the beacon is near the center of the bot. In all other cases, the
PWM lines are set to a 100% duty cycle resulting in much quicker
motion.
The red light on the head of the robot will be active when it senses no
IR signal. When it is tracking, the yellow light will be illuminated,
and when it finally centers on the beacon, the green light and buzzer
will activate. This device will sense good beacons at distances up
to or exceeding 1.5m.
The mercury switch (not implemented on the MkII version yet) is a
basic example of a position sensor or shaft encoder. If the turret tilts
to a dangerous level, the switch will shut off its motors and restrict its vertical motion preventing the wrapping of cables
and pulling of wires. A real shaft encoder setup would allow the bot to sense the position of its body and correct for any
external forces applied to it, thus improving the accuracy of the device. Two or more snake turrets with shaft encoders
could be used to accurately calculate the position and velocity of any beacon between them.

14.1 EXTERNAL CIRCUITRY


Snake Turret uses two additional milled boards. The board located at the top of its chassis provides a mounting point for
the ribbon cable, some additional power connections, and a mounting plate for the three lights. The head of Snake Turret
is a simple milled board that holds the five IR sensors. For more accuracy, a 47F capacitor should be added between the
5V and ground pins. Additionally, small capacitors may be needed between the power and ground pins of each IR
detector.
Power is supplied to the Snake Turret via a NiCd 7.2V battery pack. The sensors will behave erratically if the battery
power wanes so keep it well charged.

14.2 QUIRKS
One major problem with Snake Turret is the power consumption of the large base motor. This motor cannot take
advantage of the turrets PWM correction for small beacon angles. A 50% duty cycle does not provide enough juice to
keep the big motor going.

14.3 POSSIBLE IMPROVEMENTS


A nice future addition might be the implementation of a search mode. Like a radar dish, the robot could pivot until it
detects an IR signal. When it loses the signal, it will resume its scanning. The code for this is included in the main program
but is currently commented out until it has been tested properly.
Part IV Examples: Both Simple and Complex

Page 63

The skeleton robot is not limited to IR beacons; it could be made to track magnetic field strength, sound, light, TAs,
whatever your imagination can devise. All it requires is a little sensor building on your part, and a few small changes in
the assembler code. Experiment!

14.4 SENSOR-TO-PIC CONNECTIONS


Infrared Sensors
Top
Left
Middle
Right
Bottom

Pin #
RB0
RB1
RB2
RB3
RB4

21
22
23
24
25

Motors
Up
Down
Left
Right

Pin #
RC3
RC2
RC0
RC1

14
13
11
12

Lights
Red
Yellow
Green

Pin #
RB5
RB6
RB7

26
27
28

Buzzer

RA1

14.5 REFERENCE FILES


All relevant files for this project are available on the EE401 web site:
snake.asm
snake.hex

program files for autonomous turret operation (assembler and hex)

snakehead.brd

turret head mounting board layout

snakerouter.brd

router board layout

Part IV Examples: Both Simple and Complex

Page 64

15 LINE FOLLOWER
The Line Follower is capable of following a set path given that the line it is to follow is somewhat reflective compared to its
background (for example, white tape on black or dark grey floor). And since this robot has been programmed with short
term memory, it will interpolate between breaks in the line and follow turns that are too sharp for its turning radius.

15.1 MODIFYING THE CHASSIS


The main vehicular portion of Line Follower is a modified radio-controlled Dodge Viper. The MicroBoard replaces the RC
cars original control mechanism by connecting the h-bridge (pins RC0 through RC3) to the car's motor and steering line.
The steering is digital, and by reversing the polarity on the steering lines, the MicroBoard can cause the car to turn left or
right. The rear motors that drive the vehicle are pulsed-width modulated to control the speed of the robot. In future
models, the PWM could also be used to control the angle of the steering mechanism allowing for much more accurate
navigation.

15.2 THE SENSOR UNIT


The sensor unit is composed of 5 IR transmitter/receiver pairs. The first half of each pair is an IR diode placed in series
with a 220 resistor, allowing about 20mA to flow through diode. This light reflects off the surface below Line Follower,
and is received by the unit's phototransistors (bluish black diode-shaped components). The phototransistors are placed in
series with a 2.2k pull-down resistor. The MicroBoard receives voltages from this array and coordinates output based on
the input. A white patch on the ground will yield approximately 5V, while a black surface returns 0V.
The only concern with this setup is the parallel connectivity. To reduce the current draw of the sensor board, one may
consider connecting several of the emitter diodes in series.

15.3 LINE FOLLOWERS CODE


The sensors read five values from the IR phototransistors into the register inLR: bit 4 is the left sensor, bit 3 is the middle
left, bit 2 is the middle, bit 1 is the middle right, and bit 0 is the right sensor. The program compares this register to
previously stored outcomes, and decides where to move based on the comparison. It sets the bits of an output register (the
outALL register): bit 3 turns right, bit 2 turns left, bit 1 is half speed, and bit 0 is full speed. The output register is then
tested, and depending on the bits that are set, different subroutines are called to control the four output lines (c0 and c3 for
steering and PWM1 and 2 for speed).

15.4 SENSOR-TO-PIC CONNECTIONS


Infrared Sensors
Left (blue wire)
Middle Left
Middle
Middle Right
Right

Pin #
RB0
RB3
RB4
RB5
RB6

21
24
25
26
27

Motors
Pin #
Brown to blue RC0
White to green RC1
Steering
Pin #
Blue to blue
RC3
White to green RC4

11
12

14
15

Power
Sensor 5V
Sensor GND

Pin #
6 aux power conn
2 aux power conn

Power Switches
Side 1
TYCO 6V to NiCd 7.2V
Side 2
barrel connector (+)
Batt GND
TYCO GND to barrel (-)

Other connections made: vias to H-bridge from lines c0, c1, c2, c3

Part IV Examples: Both Simple and Complex

Page 65

15.5 REFERENCE FILES


All relevant files for this project are available on the EE401 web site:
linefollower.asm
linefollower.hex

program files for autonomous line follower operation (assembler and hex)

lineboard.brd
lineboard.sch

EAGLE board layout of sensor board


EAGLE schematic of sensor board

Part IV Examples: Both Simple and Complex

Page 66

16 RF CONTROL (RC LINK)


If someone has only utilized the chassis and motors of an RC car (or
youd like to control the car from a computer), you can use the RC
transmitter/receiver pair.

16.1 PREPARING THE TRANSMITTER


The first step is to get the transmitter case open. Take out the one
screw in the back and remove the battery. Next, begin to pry open
the back plate. This may take a little work and ingenuity. The clips
that hold the two pieces together must be dislodged from their
moorings (try a flat-blade screwdriver). Lastly, dislodge the
pyramid-shaped piece at the base of the antenna. Once this is free,
the case should come apart rather easily.
Remove the blue buttons from the circuit board. Youll notice a small donut of metal beneath each end of the two Vshaped pieces of metal. In normal operation, the ends of the V must contact the donut to send the signal for the car to
move. Using a multimeter, youll find that the donuts are at 8.6V while the Vs are grounded.
1

1 Cut four pieces of blue (or any other colour except red or black) wire. These will be your control lines.

Solder one end of each wire to each of the four donuts. Make sure your solder joints do NOT contact the rockers .

Cut a piece of black wire and solder one end to the ball of solder directly above the ground plate of the battery
connector.

16.2 PREPARING THE MICROBOARD


1

Solder vias between your PIC and the PORTC H-bridge (resistor locations R17, R18, R19, R20)

Solder the other end of one of the blue wires to the RC0 output of the H-bridge. Do the same for RC1, RC2, and RC3.

Solder the black wire to the ground of the MicroBoard. This creates a common ground

16.3 PREPARING THE RECEIVER


If youre simply going to drive the car around, you can bypass this section, otherwise cut the control lines going from the
receiver to the RC car.
1

Connect a 6V battery or power supply (your choice) to the red and black wires protruding from the receiver board.

Make sure the antenna is securely fastened to the board with a screw.

Solder your output circuitry to the steering and motor power wires. The motor power lines are the thick brown and
white wires, while the thin blue and white wires control the steering.

When there is no signal there will be no voltage drop across these wires. When a signal is received from the transmitter,
there will be a 6V drop across the affected pair, the polarity determined by the nature of the signal. The demo example has
LEDs connected across the wire pairs to indicate polarity.
Part IV Examples: Both Simple and Complex

Page 67

16.4 USING THE TRANSMITTER/RECEIVER IN HOSTED MODE


1

Burn the DEBUG.HEX file onto the PIC16F873. Connect the serial cable and power to the MicroBoard.

Type the following in HyperTerminal:


>>
>>
>>
>>
>>
>>
>>
>>

output
output
output
output
set c0
set c1
set c2
set c3

c0
c1
c2
c3

This will set up the board for use by setting PORTC to output. Since the donuts are active low (the rockers are
grounded) we set all the output lines to 9V (the power supply voltage going through the H-bridge. 12V might ruin
the transmitter, so stick to 9V or less). This step ensures that the transmitter is in the off state.

Put the 9V battery into the transmitter unit. If you do this step before initializing the board, the H-bridge output will be
low and the transmitter will begin sending signals with unpredictable results.

To activate individual outputs on the receiver, simply clear the desired PORTC output line. On the demo example you
can control the steering by clearing lines RC0 and RC1, and the motor power with lines RC2 and RC3. You can
deactivate the receiver outputs by setting the desired PORTC line in HyperTerminal.
>> clear c0
>> set c0

- activates the steering lines of the receiver


- deactivates the steering lines

If your MicroBoard is set up with hardware flow control, you can run script files. Try the blinking light example over the
RC link.

Part IV Examples: Both Simple and Complex

Page 68

Appendix A. MICROBOARD SCHEMATIC DIAGRAM

Section V Appendices

Page 69

Appendix B. COMPONENT AND SOLDER SIDE OF BOARD

Section V Appendices

Page 70

ASSEMBLING A MILLED BOARD (PLUS HOW TO SOLDER)

Appendix C.

If you have to drill holes in the PCB


You should only have to drill holes if you are using an in-house milled board; the manufactured boards should already be
drilled. Start off by locating the component side of the printed circuit board. Note that all components will be installed on
this side and most of the soldering will be done on the other side (solder side).
Suggested hole sizes:

DB9 connector mounting holes and 2.1mm power connector #32 (0.116 inch)
Diodes, voltage regulators and SIP connectors #60 (0.040 inch)
All other component holes #67 (0.032inch)

After using the drill, clean up the mess you have created.

Installing and soldering components


Before soldering, trial fit all components to ensure all hole sizes are correct and components will fit properly.
You will likely need to clean the copper on a milled board of tarnish and oils. Cleaning can be accomplished by lightly
abrading the surface with a kitchen, non-detergent pad (Scotch/Brillo pad), fine steel wool, or fine sandpaper. Care must
be taken not to damage the board. Be careful not to touch the copper surfaces with you hands; fingerprints will
contaminate the clean copper surface. Some boards may be tin-plated for greater durability.
Install components from the shortest first to the highest last. With this in mind, solder the vias first, then install the resistors
and diodes, followed by the IC sockets and monolithic capacitors and then lastly the electrolytic capacitors and connectors.
Install vias using short pieces of solid wire such as the leads from the resistors. On the milled board, the resistors, diodes
and mono-caps are used as electrical feed-throughs from circuit board top to bottom. Solder both sides where appropriate.
Ensure that the diodes and electrolytic capacitors are installed correctly. If they are not installed properly, this will cause
you unnecessary grief and time spent unnecessarily troubleshooting the board.
When installing the IC sockets, ensure that the notched section matches with the orientation of the ICs. The notch
designates the end of the IC that pin 1 is at. For the 28-pin PIC, you will be given two 14-pin IC sockets. Once again, ensure
that both notched sections are facing the same direction prior to soldering them to the circuit board.

Soldering
Turn soldering iron on and allow time for the iron to heat up. While the iron is heating up, ensure that the sponge is damp
as youll need to clean the tip of the iron prior to soldering. To clean the soldering iron tip, simply wipe the heated tip of the
soldering iron against the damp sponge. The tip should have a bright silvery appearance after you have cleaned it.
1

Insert the component lead into the proper position on the printed circuit board. Dont pull the component too tight
against the board; the component must be able to expand as the temperature changes.

Section V Appendices

Page 71

Use the hot soldering iron held at a 45 angle. The irons tip should come in contact with both the component lead and
the circuit board. Let the iron heat up the component lead and component pad.

Try not to touch the solder to the soldering iron. Touch the solder to the component lead and let the heated lead melt
the solder. Allow the solder to melt and spread around the entire connection. After the solder flows around and
adheres to the part being connected, remove the soldering iron.

Examine the solder connection. If the connection appears to be cone shaped, the proper temperature was reached; bad
solder appears grayish and round.

Cut the components wire lead, leaving a bit of wire protruding from the solder.

Examine the area around the connection and remove any excess solder.

Testing the assembled board Power Check


Please refer to Appendix D Checklists: Components, Power, and Integrated Circuits. Before installing any ICs, test the
board for proper power connections. Use a DMM set to measure resistance to check for short circuits across power supply
connections. Connect the power supplies and use a DMM on DC volts to check the supply voltages at the IC sockets.

Section V Appendices

Page 72

Appendix D.

CHECKLISTS: COMPONENTS, POWER, AND INTEGRATED CIRCUITS

Your MicroBoard kit should include the following (do a quick check to make sure):
Qty
1
6
2
5
1
1
1
1
1
1
1
4
3
2
1
2
2
1
1
1

Description

Part Number

100F 25V electrolytic radial lead (100-220F 25V or greater)


001F 50V mono-cap
10F 25V electrolytic radial lead (10-22F 25V or greater)
01F 50V mono-cap
2.1mm barrel power connector
9-pin female right angle DB connector
1N4000 1A 50V rectifier (1N4000-1N4007)
LM7805 5V 1A TO-220 voltage regulator
PIC16F873-04
L293 dual H-bridge driver
MAX232A RS-232 interface chip
4.7k -watt resistor
470 -watt resistor
330 -watt resistor
4.00MHz 3-pin ceramic resonator with integral capacitors
14-pin IC sockets
16-pin IC sockets
red LED
9Vdc 500mA wall adapter
MicroBoard printed circuit board

C1
C2, C5, C7, C17, C22, C23
C3 plus one for testing
C24-C28
CN1
CN6
D1
IC1
IC4
IC5
IC8
R1, R29, R30 plus one for testing
R23, R24 plus one for testing
R31, R32
Y1
sockets for IC4
sockets for IC5 and IC8
plus one for testing

The assembly checklist begins here (soldering the components in this order would be a good idea):

Description

Part Number(s)

Notes

IN400x diode

D1

White band toward Y1

4.7k -watt resistors

R1

Yellow violet red gold

R29

You will have one extra for testing purposes

R30
470 -watt resistors
330 -watt resistors

R23

Yellow violet brown gold

R24

You will have one extra for testing purposes

R31

Orange orange brown gold

R32
01F 50V mono-caps

C24

Marked 104 for 10x104pF

C25
C26
C27
C28
001F 50V mono-caps

C2

Marked 103 for 10x103pF

C5
C7
C17
C22
C23
Two 14-pin IC sockets for IC4

Section V Appendices

Sockets for IC4

Notches away from DB9/CN6 connector


Page 73

16-pin IC socket for IC7, IC8

Sockets for IC7 & IC8

Do NOT solder DIP ICs directly into the PCB

4.00MHz 3-pin ceramic resonator

Y1

2.1mm barrel power connector

CN1

9-pin DB female connector

CN6

100F 25V

C1

Negative to edge of PCB

10F 25V

C3

Positive to edge of PCB

Tabs may need to be bent to fit holes in PCB

You will have one extra for testing purposes

LM7805

IC1

Before installing any ICs, test the board for proper power connections:
Probe connections

Desired
Value

Aux power: pin 1 to pin 3

> 500k

Use a DMM to measure the voltage Vcc with reference to ground.

Aux power: pin 1 to pin 3

Vcc

Measure the +5Vdc supply with reference to ground.

Aux power: pin 6 to pin 3

+5Vdc

Measure voltage on MCLR on the PIC socket with respect to ground.

IC4: pin 1 to pin 19

+5Vdc

Measure the supply voltage on the PIC socket.

IC4: pin 20 to pin 19

+5Vdc

Measure the supply voltage on the RS-232 interface socket.

IC8: pin 16 to pin 15

+5Vdc

Measure the drive supply voltage on the L293D driver socket.

IC7: pin 8 to pin 4

Measure the logic supply voltage on the L293D driver socket.

IC7: pin 16 to pin 13

+5Vdc

Measure the ENA voltage on the L293D driver socket.

IC7: pin 1 to pin 4

+5Vdc

Measure the ENB voltage on the L293D driver socket.

IC7: pin 9 to pin 12

+5Vdc

IC8: pin 16 to pin 15

+5Vdc

IC8: pin 2 to pin 15

+10Vdc

IC8: pin 6 to pin 15

-10Vdc

9 Test
Use a DMM to measure resistance. Check for a short circuit from Vcc to
ground (auxiliary power connection pin 1 to pin 3; the auxillary power
connector is the collection of six pads on the top side of the board).

Plug the wall adapter in and connect it to the 2.1mm barrel connector.

Vcc

If, and only if, all the power checks are correct, continue on:

Disconnect the power and allow the supply voltages to drain to 0V


before inserting any ICs.

Insert the MAX232 in the IC8 socket. Pin 1 is furthest away from the
DB9 serial connector.

Connect power through 2.1mm barrel connector.


Use a DMM on DC volts to check Vcc on the MAX232 with reference to
ground.

Measure V+ on the MAX232 with reference to ground.


Measure V- on the MAX232 with reference to ground.
You are now ready to program a PIC16F873.

Section V Appendices

Page 74

You might also like