GPS SPEEDOMETER
I am building a speedometer for
my lakester that I hope will give me reasonably accurate
speed data during a run at Bonneville. In the past, I have
tried to read the tachometer as I pass through the last
mile marker to get some idea of my speed. Between the car
vibrating, the wind buffeting my helmet, and the general
anxiety of keeping the car straight at speed, I have been
pretty unsuccessful. Oh, I could say it was doing maybe
7700 rpm, but it could have been almost anywhere betwen
7500 and 8000. It was just a guess.
By a process of absolute serendipity, I ended up with a
small computer card with embedded BASIC and lots of I/O
options that just begged to be put to some practical use.
Web searches uncovered a GPS module that offers a speed
output and a display card with large, bright LED's. Put
them together and I just might have something that I can
actually see at speed.
The computer card -- really, it's more like a 40-pin DIP
chip -- is from EZsbc. The one I got is the EZsbc1.
Uses an LPC2138 ARM-7 processor from NXP. It has a
version of BASIC installed as the O/S. Programming it
requires a PC running a terminal program (I used
HyperTerm) and a USB port with a driver program. There
is a download page on their website that explains how to
do this and it is simpler than it appears (especially if
you use HyperTerm and ignore all the setup info on
TerraTerm). It should be possible to program this card
from a Mac, as well. I hope to try this one of these
days.
This card/chip has a lot of I/O pins, including dedicated
SPI bus, TTL-level serial bus, I2C bus, and ADC inputs. A
number of the pins can be used as PWM outputs, which seems
to be quite the thing among the robot crowd for driving
small motors.
I ended up ordering The Ultimate GPS breakout from Adafruit.
This module has a GPS on a chip, with provision for
using either the antenna on the chip or an external
antenna, and a simple ASCII interface using TTL-level
serial I/O.
The display is a 4-digit 1.2" LED module mounted on a
backpack card with the driver chip and an I2C I/O. This
card is produced by Adafruit as well but I bought mine
from InterTex Electronics in San Antonio. This rascal
proved to be rather difficult to interface to the EZsbc.
Hard to decide who to blame...so I won't bother. But
here's what happened.
Adafruit supplies C libraries for any of their products
that are intended to be interfaced to a computer. The
libraries are specific to the Arduino and the Raspberry Pi
computer cards. They offer comprehensive instructions for
assembling any cards that are kits and for hooking them up
and running sample code. If, however, you are going to use
something other than one of these computer cards to drive
their cards, you are pretty much left to figure things out
on your own.
In the case of the LED display, I managed eventually to
find enough examples of driver code and explanations of how
various folks got this card to work, that I came up with a
general idea of how to manage this chip. The chip powers up
in Standby mode, which means the LED's are all off. To
start the chip driving the LED segments, you have to send
it three commands via the I2C bus. Each command must be
preceded by the card address -- which is 0xe0, no matter
what Adafruit says in their instructions. (Yes, the chip
'address' is 0x70 but this is a 7-bit address and to get
the chip to actually write the address internally so that
the following command is processed, you have to left-shift
the address and add a zero to form an 8-bit value, which
happens to be 0xe0.) Thus, a triplet of 2-byte commands
must be sent to the card. I sent them in this order:
0xe0 0x21 (enables the on-board oscillator)
0xe0 0xef (sets the brightness to max
0xe0 0x81 (sets the display to ON
It took me several days to get this right. Not that the
commands were hard to figure out (everyone mentioned these)
but because I hard-headedly refused to believe the scope
display of the data on the I2C line. I was using the EZsbc
BASIC command
I2CWR(,,,)
to send the commands. In particular, I would program
c$=chr$(0x21)
i2cwr(0xe0,0,c$,1)
which, it turns out, sends the bytes 0xe0, 0x00, and 0x21
to the card. When I finally realized that I was sending
THREE bytes to the display chip, I changed the code to try
c$="x"
i2cwr(0xe0,0x21,c$,0)
and everything began working. The rest was pretty simple. I
wrote some test code (see the downloads page) that lets me
enter a number, parses out the digits, and displays them on
the LEDs. The only 'trick' to this code is realizing that
1) you have to send the segment codes rather than the
numbers to the chip and 2) the digits are located at
addresses 0, 2, 6, and 8. The colons and decimal points are
at address 4. The code listing should be self-explanatory.
If you can't read BASIC then you're probably a C-programmer
and Adafruit has you covered already