Linux support for GPS Receiver over serial port

I have always have had a sweet spot for GPS technology. Back in 2005 already, I did some projects with tracking vehicles using a ‘GPS mouse’ and smart phones with GPRS. A GPS was not built in by default in those devices. We used Bluetooth to connect. I still have warm feeling about what I managed to do back then…

Nowadays, GPS is available everywhere. Just count the number of GPS receives you have in your mobile devices, car or even your pets collar. Within my family we easily reach up to 12 systems with free and accurate global positioning.

I wanted to experiment with GPS over USB cable. So I was checking out this GPS receiver on Ali express with this promising title: “BEITIAN Auto-adapted baud rate USB GNSS GPS Receiver 1Hz 4M FLASH 5.0V Double-sided tape NMEA-0183 BN-85U better than BU-353S4”

I used a Sirfstar III chipset for GPS, fourteen years ago. I have no clue about the ‘BU-353S4’ or even the better ‘BN-85U’ 🙂

Let’s check out if this one just works OK as a reliable GPS receiver.

It has a USB cable which is more convenient than a Bluetooth connection when you want to read data for days instead of hours. And it only costs around 8 dollar.

I was interested if this one could work on Linux too so I contacted the shop. I got a positive message back (thanks, shop5059202) and I was sent some zip file which should contain the driver. I will come back to that in a moment…

Running it on Windows

I first tried it out on Windows, I just plugged the USB of the GPS in and it was seen as a serial port without hesitation:

This behavior was as expected. GPS data is traditionally received over RS-232, serial ports. Even that Bluetooth GPS mouse I used in 2005, implemented a serial connection protocol.

So I downloaded some Windows app which could show data received over the serial port. I went for the Serial Debug Assistant app:

And because I knew I had to listen to comport 7, I immediately got the data:

The data received is sent in the NMEA format. this is a very traditional way to show GPS information. Each sentence is just one line with:

  1. Message identification at the start
  2. Predefined fields (relative to the message) in the middle
  3. Checksum at the end
  4. Carriage-return and linefeed to separate messages

There are multiple GPS systems: GPS, Glonass, Beidou, Galileo, etc. So you can expect receiving the same kind of message from different systems if your GPS supports multiple systems. Eg. GLGSA serves DOP (dilution of position) and active satellite information from Glonass, GPGSA serves information from GPS.

Other messages are sent in parts like the GSV message, satellites in view:

$GPGSV,2,1,6,01,50,304,26,03,24,245,16,08,56,204,28,10,21,059,2077 $GPGSV,2,2,6,28,16,307,20,32,49,078,30*73 

These two lines contain information about six satellites in view. These must be seen as one message.

So this raw GPS information needs some parsing before you can really use it.

Nuget package

I have written a simple .Net Core parser. It’s available on GitHub. It’s a light-weight parser for NMEA messages. It currently parses GSV, GGA, GSA, GLL, GMC, VTG and TXT messages:

  1. GGA Global Positioning System Fix Data
  2. GLL Geographic position, Latitude and Longitude
  3. GSA GPS DOP and active satellites
  4. GSV Satellites in view
  5. RMC Recommended minimum specific GPS/Transit data / Most commonly
  6. VTG Track made good and ground speed
  7. TXT U-Blox specific information text

Using it is simple, just create an instance, and support the event in a callback function:

    _parser = new NmeaParser();
    _parser.NmeaMessageParsed += NmeaMessageParsed;

    private static void NmeaMessageParsed(NmeaMessage e)
        if (e is GnrmcMessage)
           // Use message

The parser is event-driven. Just pass it NMEA messages and an event is raised when a message is parsed.

But it’s even a bit smarter, it collects multiple GSV (satellites in view) messages and raises one event. Also GSA (DOP and active satellites) information is combined for multiple GPS systems and raises just one event.

The latitude and longitude are converted to decimal degrees, the format used by IoT Central.

In the test application, I read serial port information using the .Net Core System.IO logic. Check out that bonus SerialNmeaReader. At this moment, this only works on Windows. Serial ports on Linux are not supported (yet) by .Net Core.

To make this project even more accessible, I created a NuGet package for this library. You can use this package manager command to load it:

Install-Package svelde-nmea-parser -Version 1.0.0

Note: I tested my library against a few GPS devices. If you are a manufacturer of GPS devices and you want to have your device officially supported, please contact me.

Can I use it on Linux?

As I already mentioned, a (link to a) zip file was sent by the seller of my GPS module.

But I waited to long to access the file. When I finally tried to access it, it was not available anymore. Luckily I was more curious about the native Linux support so I just plugged it into my Advantech Uno IoT Edge device running XUbuntu 18.04.

There I tried this command:

dmesg | grep -i usb

This gave me this output with some interesting lines about the USB devices on my machine:

It was showing some information about u-blox , the GPS chipset in the GPS. And looking a bit closer to it, it was also showing something called ‘ttyACM0’. TTY is traditionally reserved for serial communication. So Linux knows about the serial port support?

Note: This is a nice trick for every type of USB device. Just test it.

Then I checked for the existence of this port:

Yes, this serial port really exists.

Finally I checked this output of that serial port:

sudo cat /dev/ttyACM0

This give me this output:

Yes, this GPS device is supported by Linux out-of-the-box. I retrieve the text information from the U-Blox chipset. And I see some incomplete messages (due to poor in-house reception).


This is a surprise for me! This device is a fun and cheap way getting started with GPS. I did not expect to see Linux supporting an eight dollar GPS device.

I still have to parse the raw data within Linux but that is something for a new blog…