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 a dedicated SPI bus, TTL-level serial bus, I2C bus, and several 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.

My first display was 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 (the 0x prefix stuff is IBM's way of writing hexadecimal characters; you don't actually send those characters):

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(slave address, register to write, data string, number of bytes)

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. I was disappointed at the brightness of this large display so I ordered a .56" display and backpack to try. The Adafruit folks have their stuff together -- it was a simple unplug/replug to install the new display. No code changes, the wires are in the same order. Easy. Oh, and it is brighter, which will be important in the sunlight on the salt.

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 GPS module is a pretty simple plug-and-play device. It requires 5V power and communicates via a TTL-level serial bus. Four wires and some code. Pretty easy. I got the code mostly working with the modules on a powered breadboard but it was quite a pain to lug everything outside and setup a table to see the GPS get a fix (my shop is in a metal hangar). Besides, I wanted to see it work when I was driving. So I constructed a simple breadboard circuit with everything plugged in, using a 7805CT fixed 5V regulator to power everything. I had a 12V small battery around for a power source (you could use the power port on most modern cars, too).

DSCF1428 DSCF1430


The EZsbc card can be powered through the USB port, which is ideal for developing code. My laptop provides enough current to run the whole thing (about 90 mA with the smaller display shown). On battery power, I provide 5V to the EZsbc card from the regulator but I don't hook up the USB and battery power at the same time. Check out the schematic for the EZsbc1 to see why -- there is a small 2.2 ohm resistor between the 5V input on the USB connector and the 5V pin on the card itself. If the voltages differed by much, you could blow this resistor or possibly hurt the USB port driver in your computer.

The Speedometer schematic is available on the download page. Basically, there are four wires and power. Simple.

Does it work? Yep! Works fine. I send some commands to the GPS module to increase the update rate of the VTG message (the one that contains speed over the ground) and slow the rate of the RMG message (which I only use to determine that the chip has found some satellites and has a position fix). I hope this will let the speed display keep up with the accelerating car (as of this moment, however, the update rate has not taken effect; hmmm). As we enter the last mile on the five mile course, however, the rate of change of speed is not so fast and I suspect even the base setting (once per second) would keep up with speed changes. I have written a version of this code that keeps track of the maximum speed. This might be what I really want to display, although I would love to know just how fast I'm going when I turn off the course too. So I may add a toggle switch or a button to display the max speed after I come to a stop. Easy -- it's just code now.

Total parts cost -- under $100. Just for fun, I laid out a printed circuit to fit a box I found at InterTex Electronics. Here is the result:

Speedo front Speedo

I've tried it out at the Texas Mile and at El Mirage. Had an issue with saving the max speed at El Mirage that I haven't sorted out yet, however.