Using an LCD Display with your Robot.
Having a display in your robot can very helpful in developing and debugging
the hardware and software of the robot. In the
first article I covered the various modes the
display works in, how to wire it up, and how to initialize the display with
software. Now I'll go over the actual implementation I used in Master Mazer, my
advanced/expert maze runner.
Concept
My first maze robot used an LCD display driven directly off the main
processor. I noticed during development that the processor spent too much time
writing to the display. A typical write cycle would take 1.5us for one
character and if I cleared the screen, that took 2ms. While this may seem like a
small amount of time, it was cutting into the scan times of the sensors and the
overhead needed to keep the robot going straight. I had several options at this
point:
Use a serial display module.
|
A very expensive option, but it would free up processor cycles.
|
Develop a background task to control the display.
|
Another good option and much cheaper then buying a display. My problem
with this approach was all my timers were in use, which would be needed
to implement the background task. I also felt it would add too much
development time to the software, something I didn't have as the event
date was getting closer.
|
Develop my own serial display module.
|
A good idea, but I didn't have room on the circuit board for another processor.
|
Don't use the display while running.
|
My final solution for that first development.
|
I decided to simply not update the display while the robot was running the maze.
For the next development I planned to use a dedicated micro just for the display
and send data to it from the main processor, using a serial interface at
115kbaud. Very similar to the serial display modules you can buy, but much
cheaper and faster. An AT90S2313 micro runs about $4 and I picked up 4x20 LCD
display for less then $10 from B.G. Micro.
Hardware Interface
The majority of these LCD displays use the Hitachi HD44780 or equivalent
controller. This controller can use a 4-bit or 8-bit interface scheme. The 8-
bit interface is faster, since you send an entire byte at once, instead of
sending a pair of 4-bit nibbles. Since the 2313 micro has 15 I/O lines, there's
no reason not to use the 8-bit interface. My final port allocation has 8 data
pins, 3 control pins, and 2 pins used for the serial interface. You need to
give some thought as to the crystal frequency you select for this display micro,
since the baudrate is derived from this crystal and it needs to match the serial
port being used by the main processor. In my previous robot, I used 4mhz
crystals for each micro since that was the maximum rating for the micro. I also
knew the UARTs would not be talking to anything else, so standard baudrates were
not required, as long as the baudrate was the same for each UART. For my newest
robot, I planned to include a serial port that could talk to a PC, so the main
processor needed to run with standard baudrates. This would also require the
display micro to use standard baudrates, and thus a crystal that would produce
standard baudrates with minimal error. The Atmel datasheets have a nice chart
that shows you the baudrates for all the common crystals, as well as the error
percentage. Since both the main processor and the display micro were rated to
8mhz, I went with a pair of 7.3728mhz crystals, which would give me all the
standard baudrates with 0% error. Here's the display portion of schematic used
on the new robot.
The signals used are as follows:
DB0-DB7
|
Databits 0-8, used to read and write information to the display.
|
|
RS
|
Register select is an input to the display. Set it high to access the data
memory, or low to access the control registers.
|
R/W
|
Read/Write control. Set it high to read from the display, or low to write
to the display.
|
CE
|
Chip Enable for the entire display. Set it high to access the display.
|
DisplayTXD
|
UART transmitter output from the main processor.
|
DisplayRXD
|
UART receiver input to the main processor.
|
Reset
|
Display micro reset line. Since I had multiple processors and some other logic
that required a reset, I had a common reset signal to use. If you don't have a
reset signal to use here, you can use a 4.7K pullup resistor instead.
|
Software
The software in the display micro is pretty straight forward. Upon reset the
display gets initialized, a revision banner is displayed, then the serial
receiver is started and any data from the main processor is processed and
displayed. Here's a flow chart of what the display micro does.
Rather then go into every part of the code, I'll summarize a few key sections and let
the reader download the source file.
Display.asm
There are actually two types of data sent to the display micro,
ASCII and commands. Commands are routines that can clear the display or move
the cursor around, ASCII characters are the displayable images you're reading
right now. To distinguish between the two, I established a command table that
has the high bit set for all commands. Since ASCII characters only use the
lower 7 bits, it's an easy way to distinguish one from the other. Here's all the
commands and their values:
cmdClearDisplay 0x80
cmdGotoLine1 0x81
cmdGotoLine2 0x82
cmdGotoLine3 0x83
cmdGotoLine4 0x84
cmdCursorLeft 0x85
cmdCursorRight 0x86
cmdDisplayOff 0x87
cmdDisplayOn 0x88
cmdCursorOn 0x89
cmdCursorOff 0x8A
cmdBlinkOn 0x8B
cmdBlinkOff 0x8C
To be able to receive data at 115Kbaud and still run the display, an interrupt driven
service routine (ISR) is required. Everytime a data character is received by the UART, a
hardware interrupt is generated, which forces the program to call the ISR. The ISR then
reads the character from the UART and places it in a buffer in sram on the 2313 micro
and returns to where the main program was before the interrupt occurred. At some point
the main program checks the buffer for new data and then begins the process of testing
for a command and executing that command or displaying the data as ASCII.
The type of buffer used if referred to as a circular buffer, where data is
entered into progressive memory locations until you reach the end of the buffer,
then it wraps around to the beginning of the buffer, like a circle, and starts
writing at the beginning of the buffer again. Two pointers are used to operate
the buffer, the first is a head pointer which points to the next available
location in the buffer. The tail pointer points to the next location to pull
data off of the buffer. Each pointer has logic assiociated with it that wraps
it back to the beginning of the buffer. If the pointers have the same value,
then no data is in the buffer. If the pointers aren't equal, then there's data
in the buffer to process.
Conclusion
An LCD is a simple addition to your robot which can provide run-time information,
debug data, and looks cool.