The simple way to process the NEMA sentence is to load the whole thing into a character buffer and parse it. The Netburner library has a nicely written serial driver that makes talking to the serial port pretty painless. Open the port and read characters from it. The serial driver is intrrupt driven, so if you get busy and don't read characters, nothing is lost. To fit this reading and parsing into the main control loop is as simple as adding code to check to see if GPS chars are available and then jumping to a routine to read and process the chars.
You duplicate this three times, GPS, IMU and Telemetry commands.
I thought I'd try to unclutter the main task loop and be a little more efficient. I'm the original author of the Netburner serial driver, so modifying things at the driver level was not too scary. I modified the serial driver to parse the GPGGA sentance one charactor at a time in a state machine and then post to a semaphore to tell the main task that new GPS data is ready. This is a nice routine because it spreads the GPS parsing out in time and has the minimum possible delay.When the sentence checksum is validated the data is ready, all of the floating point data fields have already been parsed out. So the main task only gets notified when data is actually ready. After the GPGGA I expanded the system to capture the proprietary garmin PGRMV sentence that gives me north, east and vertical velocity. Again its all clean and works well. The state machine now knows how to parse two sentences and ignore the others.
This data is processed by the main data processing task. In addition to using it internally it also sends telemetry frames off on the maxstream radio to be displayed and recorded on the ground.
The display program receives a data structure and logs, plots and displays things based on the received data frame type. (The processing for the IMU data is almost identical)
Now I want to upgrade the GPS to the Crescent Vector. The obvious software differences are:
- It provides Heading information
- It updates at 10Hz
- It does not support the garmin PGRMV sentance.
- None of its NMEA sentances have vertical velocity.
Humm I really want to know vertical velocity... digging in the crescent vector manual I discover that they have a binary message that has vertical velocity, in fact the single binary message has ALL the GPS data I have been capturing in a single message. The Crescent also has heading capability, alas it only outputs heading in a NMEA sentance, not a binary one. so my parsing state machine needs to process a mixed stream of Binary and NMEA messages.
The Binary message is nice in that it starts with $BIN so the beginning looks like a NMEA message, and the simple approach would be to just branch on this NMEA message ,
Its not that simple. My state machine resets its state to 0 whenever it sees a '$' beginning of message,but with the GPS sending binary data there is no guarentee that the binary data won't contain a '$' this breaks my state machine, so now the state machine knows if it is parsing a NMEA or binary data set and reacts accordingly. Also note that in a serial stream of chactors 1234.5678 there is no ambiguity on how to interpit the data. In a binary stream its a little bit more complicated. The GPS sends binary data as a IEEE754 double. standard format, but the GPS sends data in littel endian or intel format and the Coldfire processor I'm using uses big endian or Motorola format.(See Endian). SO I have to convert formats before I use the data. This is still a big win, because the endian conversion is much more efficient than parsing ASCII. Note that I'm already doing the endian conversion on the PC display software so this was not unexpected.
Once I'm parsing the GPS message the system stops responding reliably to telemetry commands....argghhhh! The problem is that If I keep the telemetry link busy sending data from the helicopter to the ground there is no time for the ground station to send data back. Up to this point the telemetry data stream was not too big for the down link pipe, switching from 5 to 10hz GPS pushes me over the edge. So now I write and debug a telemetry throttling routine that tries to keep the telemetry link idle for 50% of the time by throwing away data based on its age and priority.
All seems to be working except none of my telemetry frames have a spot for the GPS heading information, I'd like to keep both the GPS and IMU heading data, so I add a new GPS heading frame type to both the helicopter and the display software. Both areas are pretty modular so this is an easy fix. I label the new data with the same data type tag as the IMU heading data.... .
without remembering that the IMU heading is not floating point but a 0->65536 binary heading.(I worte the IMU parser and display code framework for my air lander over a year a go and have not really modifed it) Hence the GPS heading display is all messed up on the PC so I spend some time debugging the helicopter code to try and figure out why my parser is not properly parsing the GPS heading, only to eventually discover its a problem on the PC side.
This is now almost complete. At some future date I will add HOP and VDOP and signal to noise reporting. I'm now ready to take the whole helicopter outside and see how it works as an assembly. (I've been testing with two external GPS antennas on the roof. The GPS informs me that the antennas are 49.6 cm apart and that my roof has a heading of 172.3 degrees)
I really enjoy reading technical blog posts that give you a sense of the problems and struggles involved with building hardware. In an Ideal world I'd like to cover all of the project in this much detail. The reality of time and the need to sleep conspire against this. I've never been a skilled word smith so writing this saga took 25% as much time as struggling through the code. I don't have the patience to document everything to this level, but I'm going to try and do more posts at this level of detail.