again returns the unit to run mode.
This is a very simple thermostat, but it is now easy to
extend the design with more features, taking advantage
of the flexibility of the encoder and LCD display. You
can add a clock and time of day programs; you can set
the clock; you can add a fan on/off function; and so on,
without having to add any more hardware to your design.
Another application is a power controller, possibly to
control the temperature of a soldering iron. The pulse
width modulation feature of many microcontrollers is
ideal for power control of a resistive load, with the help
of a power MOSFET. The device could have a one or
two digit LED display showing the power level, and a
rotary encoder to turn the heat up or down. The
encoder’s pushbutton could be used as an on/off
switch. (In fact, the power would always be on to the
microcontroller, but turning the unit off instructs the
processor to set the output power level to zero and
disable the LED display.)
If you add hardware debouncing to the pushbutton
and connect it to an external interrupt pin, a press of the
button can be used to put the microcontroller into sleep
mode and the interrupt caused by another press used to
wake it up. Battery operated applications would benefit
from the decreased power consumption when the unit
The Demonstration Project
resistors are not needed. The PIC uses a 3. 58 MHz crystal
oscillator, but any crystal up to the maximum frequency
supported by the PIC is okay, as long as the timer0
interval parameters are adjusted accordingly. J1 is used for
in-circuit Flash programming (I use a Pickit24) and is not
required for operation. The buzzer and the LED display
are connected to the remaining I/O pins configured as
outputs. (If you don’t want to bother with a buzzer, just
replace it with an LED and 470 ohm limiting resistor.) U2
provides regulated five volts so that a battery or wall wart
can be used to power the project.
This simple project uses a PIC16F84A to manage a
rotary encoder as input and a single digit LED display and
buzzer as output. On power up, ‘0’ is displayed. Rotate
the encoder clockwise, and the number is incremented to
9, then back to zero again. Rotate counter-clockwise and
the display becomes ‘ 9’ and decrements down to 0.
Pressing the encoder pushbutton makes the buzzer sound.
The rotary encoder S1 is interfaced to U1 with three
I/O pins configured as inputs. The port B internal pullups
are used for each PORTB input port, so external pullup
■ Project top.
The hardware design of microcontroller projects is
deceptively simple, because so much of the work is done
in the software. Polling for input events is a major task,
which must be carefully coordinated with the other work
being done by the processor. Improper or poor design
may result in input events being missed or responded to
sluggishly. The way I manage this problem is to use the PIC’s
timer to do all the input polling and switch debouncing. It
then posts event flags to the foreground code, which is
free to respond to events as they occur.
This architecture works well when an event signals an
action that can be processed quickly. I do this for my
encoder inputs, where I am incrementing or decrementing
the display. Other kinds of events that require time to
perform can be more difficult to handle. For my button
press, I want to sound the buzzer for a period of time, but
I do not want to tie up the main code with a long delay.
In this case, the solution is to sound the buzzer in
response to the button press, and then schedule an event
to turn the buzzer off later (conveniently done in our
timer interrupt routine). The benefit is no time-wasting
delay loops at all in the program.
To see how the rotary encoder is managed in the
software, have a look at encoder_demo.c and
encoder_demo.h in the downloads available on the
Nuts & Volts website at
1) In function InitCPU, the
option register is loaded to
assign the prescaler to timer0
and set the prescaler to 16:1.
The timer0 counter TMR0 is
initialized to the value in define
TIMER0_INIT. Note also that
PORTB pull-ups are enabled.
Then timer0 and global
interrupts are enabled.
■ Project bottom.
2) An interrupt handling
function isr (PICC) or interrupt
(BoostC) is provided to handle
timer0 interrupts. The choice of