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.