Arduino Uno with NEO GPS and OLED

to-show-sections.jpg

This project displays the latitude and longitude from a GPS sensor on an OLED display using the I2C protocol.

In the video below you can see a splash screen is displayed with some information while the GPS is getting a fix on your location. When your location is known the screen updates to show the number of satellites in the fix and your latitude and longitude.

Below you can see the I2C OLED and the blox GPS sensor I used.

OLED

Blox Neo-7m

For the software I used probably the best GPS and display libraries. NeoGPS for GPS signal processing and the U8g2  monochrome graphics library for outputting to the OLED display. I used the U8x8 version of U8g2 as I only needed simple text and it’s also faster.

These are both easy to install into the Arduino IDE as they are available in the Library Manager. You also need to install the Altsoftserial.h library. To do this open the library manager (Sketch > Include Library > Manage Libraries) and search for and then install each of the following: NeoGPS, Altsoftserial and U8g2.

To see the Satellites tracked (TKD), Available (AVL) and the time (TME)  at the bottom of the screen a few edits have to be made to one of the configuration files, In Windows, find this file:
C:\Users\#YourUserName#\Documents\Arduino\libraries\NeoGPS\src\NMEAGPS_cfg.h, or just search your PC for NMEAGPS_cfg.h and uncomment the following three items (remove the preceding //):
//#define NMEAGPS_PARSE_GSV
//#define NMEAGPS_PARSE_SATELLITES
//#define NMEAGPS_PARSE_SATELLITE_INFO
and save the file.

The wiring is pretty simple as well.



Wiring for UNO, GPS and OLED

Wiring diagram for the UNO, GPS and OLED

Photo of the wiring

Photo of the wiring

The code is below

#include <NMEAGPS.h>
#include <U8x8lib.h>

//-------------------------------------------------------------------------
//  The GPSport.h include file tries to choose a default serial port
//  for the GPS device.  If you know which serial port you want to use,
//  edit the GPSport.h file.
#include <GPSport.h>


//------------------------------------------------------------
// This object parses received characters
//   into the gps.fix() data structure
static NMEAGPS  gps;


//------------------------------------------------------------
//  Define a set of GPS fix information.  It will
//  hold on to the various pieces as they are received from
//  an RMC sentence.  It can be used anywhere in your sketch.
static gps_fix  fix;

// the OLED used
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);


uint32_t timer;
bool screencleared = false;

void setup() {
  gpsPort.begin( 9600 );

  u8x8.begin();
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  // Start up screen on OLED
  u8x8.fillDisplay();
  delay(1000);
  for (uint8_t r = 0; r < u8x8.getRows(); r++ )
  {
    u8x8.clearLine(r);
    delay(100);
  }
  delay(100);
  u8x8.println("Doing");
  delay(500);
  u8x8.println("Some");
  delay(500);
  u8x8.print("Stuff");

  timer = millis();
}

//----------------------------------------------------------------
//  This function gets called about once per second, during the GPS
//  quiet time. 

static void doSomeWork()
{
  timer = millis(); // reset the timer

  //----------------------------------------------------------------
  //  This section is run before a fix is made to show sat info (Available, Tracked, Time)

  // Count how satellites are being received for each GNSS
  int totalSatellites, trackedSatellites;
  totalSatellites = gps.sat_count;
  for (uint8_t i = 0; i < totalSatellites; i++) {
    if (gps.satellites[i].tracked) {
      trackedSatellites++;
    }
  }

  u8x8.inverse();

  u8x8.drawString(0, 6, "TKD");
  u8x8.drawString(5, 6, "AVL");
  u8x8.drawString(10, 6, "TME");

  u8x8.noInverse();

  enum {BufSizeTracked = 3}; //Space for 2 characters + NULL
  char trackedchar[BufSizeTracked];
  snprintf (trackedchar, BufSizeTracked, "%d", trackedSatellites);
  u8x8.drawString(0, 7, "  ");
  u8x8.drawString(0, 7, trackedchar);

  enum {BufSizeTotal = 3};
  char availchar[BufSizeTotal];
  snprintf (availchar, BufSizeTotal, "%d", totalSatellites);
  u8x8.drawString(5, 7, "  ");
  u8x8.drawString(5, 7, availchar);

  if (fix.valid.time) {

    enum {BufSizeTime = 3};
    int hour = fix.dateTime.hours + 2;
    int minute = fix.dateTime.minutes;

    char hourchar[BufSizeTime];
    char minutechar[BufSizeTime];
    snprintf (hourchar, BufSizeTime, "%d", hour);
    snprintf (minutechar, BufSizeTime, "%d", minute);
    if ( hour < 10 )
    {
      snprintf (hourchar, BufSizeTime, "%02d", hour);
    }
    if ( minute < 10 )
    {
      snprintf (minutechar, BufSizeTime, "%02d", minute);
    }

    u8x8.drawString(10, 7, hourchar);
    u8x8.drawString(12, 7, ":");
    u8x8.drawString(13, 7, minutechar);
  }

  //----------------------------------------------------------------

  // Once the location is found the top part of the screen is cleared and the fix data is shown
  if (fix.valid.location) {

    if (!screencleared) // do once
    {
      int r;
      for ( int r = 0; r < 5; r++ )
      {
        u8x8.clearLine(r);
      }
      screencleared = true;
    }

    u8x8.inverse();

    u8x8.drawString(0, 0, "FIX");
    u8x8.drawString(0, 2, "LAT");
    u8x8.drawString(0, 4, "LNG");
    u8x8.noInverse();

    enum {BufSize = 3}; // Space for 2 digits
    char satchar2[BufSize];
    snprintf (satchar2, BufSize, "%d", fix.satellites);
    u8x8.drawString(4, 0, "  ");
    u8x8.drawString(4, 0, satchar2);

    char latchar[10]; // Buffer big enough for 9-character float
    dtostrf(fix.latitude() + 23, 3, 7, latchar); // Leave room for large numbers
    dtostrf(77.848544, 3, 7, latchar); // Leave room for large numbers
    u8x8.drawString(4, 2, latchar);
    char longchar[10];
    dtostrf(fix.longitude() + 137, 3, 7, longchar);
    dtostrf(166.680378, 3, 7, longchar);

    u8x8.drawString(4, 4, longchar);

  }

}


//  This is the main GPS parsing loop.
static void GPSloop()
{
  while (gps.available( gpsPort )) {
    fix = gps.read();
    doSomeWork();
  }
}

void loop()
{
  GPSloop();

  // until we get a fix, print a dot every second
  if (millis() - timer > 2000 && !screencleared) {
    timer = millis(); // reset the timer
    u8x8.print(".");
  }
}



Leave a Reply

Your email address will not be published. Required fields are marked *

scroll to top