Sunday, 7 June 2020

GPS module - sentence and lat/lon date/time display

I have had a GPS module lying around for more than a year, but never wired it up to see if it works. When they are working they squirt out lines of text, called sentences, with starting prefixes $GPxxx which give a lot of data.

I have connected up my GPS module with another module which is a serial (RX/TX) data to/from USB converter.

 You can see the four connecting wires, Vcc-5V, Gnd-GND and Rx - TXD, Tx - RXD.

Next I connected the module to a USB port on my MacBook and ran a Serial Terminal app called "iSerialTerm" (excellent reliable app by the way). I set the terminal to the baud rate of the GPS module, 9600baud, chose the Serial terminal module USB address (which turned out to be "usbserial-00000000") and connected. Immediately I saw the GPS had acquired the satellites and was displaying received sentences.


Serial Terminal display

Coding of one sentence, RMC

A STEP FURTHER
And taking this a step further how about displaying the latitude, longitude, date and time. I wired up on my table top an Arduino Uno like this

The GPS is connected to Uno A0 and A1 as the RX & TX serial data lines. The OLED is connected to A4 and A5 as the I2C SDA and SCL lines. The other connections are power and ground (the GPS is connected to 3V3 as this is a spare pin, it works on either 3V3 or 5V). This is what it looks like



CODE
Now I have just to write some code... There is a useful library on the web called TinyGPS, it's documentation is here. I just needed two functions, one to pull down the latitude and longitude, the other to extract the date and time. These versions are,

      gps.f_get_position(&lat, &lon); // as floats
      gps.get_datetime(&date, &time, &fix_age); // as unsigned longs

Now to display them on the OLED. The lat and lon are floating point numbers and can be simply displayed using the functions

     dispNum(X, Y, lat, 2);
     dispNum(X, Y, lon, 2);

from my Oled.h header of functions using the u8g2 library behind it.

The date and time have to be sorted out. They are retrieved as "unsigned long" looking like this

Date  80620 = 8 Jun 2020
Time 9190200 = 9:19:02

If you are happy to read them like this then just display them, again using again the dispNum(...) function. 


8 Jun 2020 and 9:21:55

But if you want them as a "proper" Date (day, date, month, year "Mon 8 Jun 2020") then you have to do some extraction and use two of my Oled.h header functions

     dispDate(20, 40, dw, dy, mo, yr); // use dw = NULL
     dispTime(20, 55, hrs, mns, sec);

To avoid for now working out the day of the week (Mon, Tues...) I send a NULL which tells the function not to display any day, maybe I will add this later. Sorting out the "dy, mo, yr" and "hrs, mns, sec" is done in a couple of functions like this

// extract bytes dy, mo, yr from 80620 = 8 jun 2020
void calcDMY() {
  dy = (byte)(date / 10000);
  mo = (byte)(date / 100 - dy * 100);
  yr = (byte)(date - dy * 10000 - mo * 100 );
}

// extract bytes hrs, mns, sec from 9215500 = 9:21:55
void calcSMH() {
  unsigned long t;

  t = time / 100;
  hrs = (byte)(t / 10000);
  mns = (byte)(t / 100 - hrs * 100);
  sec = (byte)(t - hrs * 10000 - mns * 100);
}

You can then get this display

Remember: the time is in GMT

The sketch for this is GPS_DISPLAY here.

Coding & the working system











No comments: