Saturday, October 4, 2008

Debugging a serial (RS232) datastream with a digital storage oscilloscope

I'm finally in Paris, and loving it so far. It's a great city to walk around, there's so much to see. I spent most of my first day here out with my camera, with my home-made GPS switched on all day.. I got approximately 11 hours out of it before the battery died, and it wasn't even totally full to start with. Also the GPS seems to be very reliable now that I moved the wires from in front of its antenna.. it usually acquires its position a few 10s of seconds after it is switched on. After that it consistently re-acquires quickly as I come out of buildings and off of the Metro. I'm very happy with it now! The picture from Pont St Michel (above) was geotagged by my D300 with the following information:
  • Latitude: 40° 51.230' N
  • Longitude: 2° 20.683' E
  • Altitude: 40m
  • Time: 2008-10-04 13:25:50 UTC
If you build one of the interface circuits (either my design from the last post or one of the others from the web which use BJTs) you will probably want to test it before you connect it to your camera. An oscilloscope is the perfect tool for this. I tested my circuit initially using a 1970s vintage Tektronix 465 scope that I got on eBay for about $250 few years ago. An old analog scope like this does all you need to convince yourself that the voltage levels are right, i.e. between 0V and +5V and pegged at +5V when not transmitting. With an analog scope you can also check that the baud rate is right for the camera. At a baud rate of 4800 the duration of the smallest pulse should be 1/4800 = 0.208ms. You can also probably sell an old scope like the Tek'465 after you are finished with it for almost what you paid for it.

If you have access to a digital storage oscilloscope (DSO) or a USB oscilloscope, such as those made by Picoscope, you can also go one step further by decoding the serial datastream and making sure the information from the GPS is correct. If needs be you decode the RS232 stream directly from the GPS and the CMOS-level stream coming from the interface circuit. All the Picoscopes allow you to record the waveform and save it to your computer where the serial datastream can be decoded and examined. I used the Picoscope 3205 that my dad got me as a moving gift to save ~200,000 samples from the waveform generated by the interface circuit and wrote a small PERL program to convert it to ASCII. The figure below illustrates how first two characters in the serial data are encoded. The x-axis shows number of milliseconds since the time that the oscilloscope triggered at - it was set to trigger on the first transition from +5V to 0V. The y-axis shows the voltage at the output from the interface circuit.
The data is transmitted with an asynchronous serial start-stop format, in which the start of a character is indicated by the transmitter using a start bit, and the end of the character using one or more stop bits. In the figure above, the transmission is initially in the idle state, which has logic 1. The transmitter signals the start of a character with a logic 0 start bit, indicated by the first "s" in the figure. It then transmits the eight data bits, from least significant to most significant, indicated by 0-7. Finally it transmits two stop bits with logic 1, indicated by "S". The second character starts immediately, with the same sequence. The first two characters are:
  1. LSB-MSB: 00100100 = Decimal: 36 = ASCII: $
  2. LSB-MSB: 11100010 = Decimal: 71 = ASCII: G
which are the first two characters in the NMEA data messages. I wrote a small program in PERL which converts a set of voltage measurements into ASCII data. The data should be in a file with two columns, the first being a time measurement in milliseconds, the second a voltage. The script and two example files captured using my Picoscope are available on my website. For example, using the script on one of the example files (nmea2.txt) gives:

$GPGGA,152917.000,5317.5456,N,00614.3536,W,1,04,4.8,62.3,M,54.8,M,,0000*73
$GPGSA,A,3,16,06,23,31,,,,,,,,,6.3,4.8,4.1*3C
$GPGSV,3,1,11,16,56,290,36,24,46,077,20,21,45,147,13,31,45,203,33*77
$GPGSV,3,2,11,29,41,067,15,06,23,245,32,30,16,116,17,23,15,299,37*71
$GPGSV,3,3,11,13,13,328,20,10,12,043,11,03,09,249,22*42
$GPRMC,152917.000,A,5317.5456,N,00614.3536,W,0.37,77.42,220908,,*29

The specification for the NMEA messages are available on the Internet in many places, although they are apparently copyrighted by NMEA, so I won't post them here. For example, you can find the messages relevant to GPS at the end of many of USGlobalsat's manuals.

The PERL script can be used to decode either real RS232 or logic-level serial, at any baud rate. Just change the vales of the configuration variables in the script to reflect what you need.

That's all for now. I'm not sure what I'll have to write about next time as I don't have any of my electronics gear with me, it's stuck on a boat somewhere between L.A. and here.

No comments: