GPS Logging with a Rabbit?
Summary: The Global Positioning System is used more and more and can be useful for many projects. Combine this with the new Rabbit Semiconductor microprocessor kit including a C compiler gives a powerful programmable GPS data logger with 128K bytes of battery backed RAM.
Introduction
I am working on a project, which uses a Global Positioning System (GPS) receiver to measure position. Part of the problem, or should I say challenge, is to save parts of the data so that finally it is used to plot the receiver position over time. The GPS modules produce RS232 data, which can be read on the screen through a terminal emulator like Hyperterminal [1] on Windows 95/98.
What I need is a device to store the RS232 text lines. One option is to carry around a portable PC along with the rest of the system. That makes quite a large and heavy unit, which I do not want, so I looked for a different way to make the logger.
There are many single chip microprocessors, such as the PIC range, which can easily do the processing, but they have only a few hundred bytes of RAM. This is not enough for my design, but looking at the electronic magazines I saw the adverts for a new microprocessor called the Rabbit. I guess what caught my eye was the complete system which consists of a development board with 128K bytes of RAM and 128K bytes of Flash memory, and a C compiler complete with development environment. [See Photo 1 - Rabbit Board.] The price of $99.00 was also affordable, being on a par with the new Flash PIC development kit, but with the added advantage of being C programmable. The price is somewhat higher today, though. Off I went to the web site and ordered the kit [3]. Within a few days the package arrived with all I needed except the power supply. The included one was a 110V US version. I just replaced it with a 220V UK power supply. The kit takes about 150mA with the LEDs turned on and it has its own regulator to provide 5V for the circuit, so a small power module is OK. I see the Rabbit kit can be bought in the UK, from Impulse Corporation Limited or the distributor 2001 [4].
Why use a Rabbit?
The Rabbit is a variation on the Z80 processor, but with many differences which are designed to assist programming with the C language. The most useful part of the system from my point of view is the 128K bytes of RAM. That is plenty of memory to store the data from the GPS logger. The RAM is battery backed, so it could be used to store data when the program isn't running. I haven't figured out how to do that yet, though!
If you get round to building your own hardware, the Rabbit microprocessor provides most of the 'glue' logic to connect four memory chips with no extra logic required. There are four serial ports available though one is used for programming and debugging, but it can be reused. The development kit has two of the serial ports connected to an RS232 interface chip and a third to an RS485 chip. Also the large Flash memory allows easy changes to the program. Overall it is certainly worth looking at for a variety of uses, and its always good to try a new 'toy'.
The Windows based development software provides a C compiler with built in assembler, an editor and a visual debugger. You get a lot of value out of this kit. There are several examples to try straight away. So within minutes you can have the serial cable plugged into the PC and the other end into the Rabbit, load an example, press the run button and within 30 seconds (at least on my computer) the LEDs can be flashing.
Embedded C from ZWorld
Having read the documents my first change was to make sure the program was running in RAM using the menu Options/Compiler. If you use the Flash all the time it will quickly wear out. The C system has its own bios, which is compiled and loaded before your own program. The source is included so that you can see how it works and maybe adapt it to your own hardware. All the code is downloaded through a facility of the microprocessor, which provides a hardware loader using either the serial port or the parallel slave port. The development system uses the serial port, so loading is quick and simple, and your own hardware could do the same. That is another convenience of this clever design. I'm getting to like it even more. When your program is complete, you change the compiler to load into Flash and then remove the serial debugging cable. The loaded program runs when you apply the power. The ease of development is all worked out. Now all I need to do is devise my code.
The ZWorld version of C is a little different from the ones you will see from others since it is designed to compile quickly and doesn't use header files in the same way. If you are used to C or Basic you should be able to make things work quite easily. Have a good look at the examples and you will see how things work.
There are several extensions to C which are there to help program in real time without having to use difficult program techniques. For instance you do not need a real-time operating system to carry out more than one function at a time. The various 'co' functions are used to group program lines into blocks, which in effect are parallel executing programs. It is probably easier to understand by seeing how my program uses them.
The Logging Program
My program does three things in parallel:
- Read the GPS serial data, analyse and store the data
- Print out the stored data
- Read the press button and operate the LEDs.
Each uses a 'costate' to group the instructions related to how it works. I've added line numbers to Listing 1 so that I can point out which part is which.
Much of the program is based on one of the samples provided to get you going with Rabbit system, but lets look at it in some detail.
Reading the GPS data
Function 1, reading the GPS serial data uses lines 30 to 57. Line 39 has the wfd, wait for done, keyword which tells the costate to wait for the rest of the line to finish. In this case that means, wait for the line of serial characters to arrive. The cof_serBgets function refers to serial port B and is a cofunction which allows the program to continue if the whole line has not arrived. With the debugger, you can single step to this instruction and see that the program jumps to after the end of the costate block if it is not complete. So you can see that waiting, maybe for a long time, for the line of text to arrive doesn't stop the rest of the program working. This is the great advantage of the idea of cofunctions. When the line of text does arrive the program runs on to the next lines of code. The rest of this costate looks for a text line starting with $GPGGA.
Its time to explain a little about the data which comes out of the GPS module. The module itself is a Garmin GPS25-LVS, which you can buy from Maplin, though, there are several other manufactures who provide similar devices. You could also use any GPS receiver, which has an RS232 output and sends standard NMEA (National Marine Electronics Association) sentences. [Photo 2 - Garmin Module and Antenna.] As well as the module you will also need an antenna. I chose the Sigem active antennae which needed the coaxial connector changing, but was much cheaper than any other in the catalogue. It also contains a magnet for temporary mounting say, on the roof of a car. The module also has an unusual ribbon cable connector, but it comes with a length of cable to make your own connections. I made connections for the 5V- power supply, at about 150mA, and three wires for the RS232 serial interface. Most RS232 GPS data is sent out at 4800 baud, which is fast enough to allow a burst of sentences every second. You can usually change the baud rate, though it is best not to go much slower.
GPS Sentences
The NMEA standardises the sentences used by GPS systems and other related electronic devices. A sentence is just a line of text containing identification and data. The first part of the sentence is something like $GPGGA and ends with a carriage return character. The $GP identifies the data as GPS information. The GGA string says this is the Global Positioning System Fix Data. The rest of the line is made up of fields separated by commas. I am only interested in the GGA sentence, because it contains the position and time information. The fields are made up of:
$GPGGA,daytime,latitude,north/south,longitude,east/west,GPS quality, number of satellites,horizontal precision,"M",geoid height,"M",differential, differential reference station,*checksum
daytime - UTC (GMT) time as hhmmss (hours minutes seconds) NOT local
time
latitude - ddmm.mmmm (degrees minutes and decimal minutes)
north/south - N or S (hemisphere of the latitude measurement)
longitude - dddmm.mmmm (degrees minutes and decimal minutes)
east/west - E or W (east or west of 0 degrees for the longitude measurement)
GPS quality - 0,1 or 2 (0 no fix, 1 just GPS, 2 differential measurement)
number of satellites - 00 to 12 (tracked satellites)
horizontal precision - 0.5 to 99.9 (measure of precision)
"M" - just the capital letter M
geoid height - -999.9 to 9999.9 (antenna height)
"M" - just the capital letter M
differential - seconds since last valid differential data
differential reference station - 0000 to 1023 (differential station ID)
*checksum - a * followed by a two character checksum
$GPGGA,181930,5314.6826,N,00208.1973,W,1,03,2.8,146.9,M,49.4,M,,*57 $GPGGA,181945,5314.6812,N,00208.2037,W,1,03,2.8,146.9,M,49.4,M,,*58 $GPGGA,182000,5314.6812,N,00208.2037,W,1,00,2.8,146.9,M,49.4,M,,*50 $GPGGA,182015,5314.6812,N,00208.2037,W,0,00,,,M,,M,,*42 $GPGGA,182030,5314.6812,N,00208.2037,W,0,00,,,M,,M,,*45
Figure 1 - GPS sentences
Figure 1 shows some of the data that I recorded. The first three lines show all the data I need. The bottom two lines show the data when there are not enough satellites in view. The good data uses only three satellites so it may not be very accurate. In particular the error in height may well be a long way out. Height errors are often twice the error in Latitude and Longitude.
The data is good enough to test the system, though. Going back to the program, lines 42 to 47 check that the GPS data contains the GGA string and selects readings at 15-second intervals. The GPS data is sent out every second, but to reduce the amount of data I need to store, only every 15th value is put into memory. I could use the same technique to halve the volume of data again if I selected 30-second steps. The if statement may look a bit verbose, but embedded code has to run quickly otherwise you can run out of time to do everything. The byte by byte comparison is quite fast. An alternative might be to use string comparisons, but that is almost certainly slower to execute. Remember embedded systems may be programmed in C but care must be taken not to waste time or memory.
Line 48 copies the text line into an array stored in RAM. The integer reci counts through the array. When it reaches the end of the array, lines 50 and 51 point it back to the start. Finally the flag vswitch1 is used to indicate the state of an LED. Each time a valid GPS line is received the LED changes from on to off or off to on depending on its last state. This is really a confidence indicator to tell me the program is working. At line 41 vswitch2 is used in a similar way, but flashes more often, several times a second, in response to any completely received GPS text line.
Printing out the recorded data
Well that gives me a way to filter out what I want and save it into RAM. Function 2, the next piece of code, lines 60 to 76, is to print the saved data. It uses serial port C to write to. For testing this was plugged into my PC running Hyperterminal. Once the code runs, it prints each logged GPS line. You could capture the text from Hyperterminal and put it into a spreadsheet to analyse it, or even plot a graph of position. The code is placed in a costate so that it runs without stopping the rest of the program. Again I use another integer, vswitch3, to flash another LED to show this part of the program is active.
Function 2, reading the press button and operating the LEDs.
The last costate in lines 79 to 97 is used to detect if the button is pressed, and has logic to debounce the inevitable multiple makes and breaks when a mechanical contact changes. The whole costate is taken from the example but is very instructive in showing how to insert real time delays without locking up the rest of the program. Stepping through it with the debugger is most revealing. The logic to operate the LEDs is at the top of the program in lines 31 to 36. Each vswitch is compared with the state of the pin attached to a LED, and the program sets or resets the corresponding values.
Well that's the logging part of my project. I am very pleased with how easy it is to use the Rabbit with its C compiler. The 128K bytes of RAM and the 128K of FLASH, gives me plenty of room to add other facilities, but that will have to be at another time, though. [See Photo 3 - All the parts.]