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.
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.
UNO -> OLED
5v -> VCC
GND -> GND
A4 -> SDA
A5 -> SCL
UNO -> GPS
3.3v -> VCC
GND -> GND
8 -> TX
9 -> RX
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(), 3, 7, latchar); // Leave room for large numbers u8x8.drawString(4, 2, latchar); char longchar[10]; dtostrf(fix.longitude(), 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 5 seconds if (millis() - timer > 5000 && !screencleared) { timer = millis(); // reset the timer u8x8.print("."); } }
Buy Me A Coffee
If you found something useful above please say thanks by buying me a coffee here...
hi, mine is getting stuck on the “Doing Some stuff” part. i am not sure whats going on here.
Hi, Is the same hardware? You can use this software to test you are receiving data – u-blox.com/en/product/u-center-windows
yeah i have the same hardware but its stil not working. do i need the software in order for this to work? im a little confused on what the software doe. thanks
The software takes a reading from the GPS and shows you all sorts of information. It’s the best way to check the GPS is working.
ok thanks
hey i got U-Center, but its not displaying anything. do you think my gps is not working?
Does it show anything when you have the GPS connected? How are you connecting it?
no nothing is shown. i dont think its connecting
how should i connect it?
You need a USB to Serial converter. I used one of these: https://www.ebay.co.uk/itm/For-Arduino-Serial-FT232RL-USB-HOT-Converter-3-3V-to-Module-Adapter-TTL-FTDI-5V-/222898816179. I chose ‘Receiver > Port’ in U-Center and it started working. There are other USB to Serial converters around but they sometimes have driver problems. You’ll see this in device manager in Windows.
Hi
I followed through every single steps as you described using same hardware but I got an error.
exit status 1
‘class NMEAGPS’ has no member named ‘sat_count’
can you help me solving this plzz
You probably just need to do this…
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.
Your suggestion solved my compile issue with gps.sat_count.
Thanks
C:\Users\#YourUserName#\Documents\Arduino\libraries\NeoGPS\src
After this src folder shows empty
no idea what to do
What happens if you search your PC for NMEAGPS_cfg.h ? Is it Windows 10 you are using? Maybe the files are being hidden.
You could try reinstalling the NeoGPS library.
Plzz reply something
It is important project for me
Thanks
I can only suggest that you remove the NeoGPS folder from here: C:\Users\YOURUSERNAME\Documents\Arduino\libraries, Then install it again. I’ve posted the NMEAGPS_cfg.h file that works for me here: https://robotzero.one/wp-content/uploads/2018/04/NMEAGPS_cfg.h
Lat and Long will not work (stuck at the programs pre-set), and should be removed from the program. Your Time zone is easily corrected by adding or subtracting the ‘+’ number.
If anyone responds I’ll gladly give more detail.
To fix Lat Long…
char latchar[10]; // Buffer big enough for 9-character float
dtostrf(fix.latitude() + 0, 0, 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() + 0, 0, 7, longchar);
//dtostrf(166.680378, 3, 7, longchar);
______________________________________________
To fix Timezone…
enum {BufSizeTime = 3};
int hour = fix.dateTime.hours + 11;// was +2 TIME ZONE CORRECTION SETTING!
int minute = fix.dateTime.minutes;
Hi,
I’ve removed the code dtostrf(77.848544, 3, 7, latchar); because it was setting the variable latchar to a hardcoded value rather than the value from the method fix.latitude to get your actual latitude. The code still worked.. you just have to be in range of enough satelites for fix.valid.location to be satisfied.
Good point about the int hour = fix.dateTime.hours + 2;. You have to change this number to get the correct hour for your timezone to appear on the screen.
Hi WordBot, cheers for the reply. Only issue I am having now is the fact that when 2400 hours is reached (midnight), the time continues counting past that. ie at actual 0700 hours this morning I got a displayed time of 3000 plus hours. I had to reset my ‘TIME ZONE CORRECTION SETTING!’ (as above) to bring the time back to normal, (seconds were fine). I’m still trying to figure that one out. Any suggestions welcome from you. Other than that, wonderful piece of kit! Thankyou!
I’m not sure exactly how to do it but with some maths like hours%24 modulus you can probably fix it. To do it properly you have to allow for daylight savings and all that stuff. Maybe this library will help – https://github.com/JChristensen/Timezone Bit too much extra info for this tutorial.
It really is a lovely little project, I’ll have to work something out to fix it, then it’ll be perfect. Perfect for my tracking telescope that demands position and time to track stars. Thankyou so much. I’m sure it’s a simple task, just gotta find the time! Cheers!
Got this setup running with little trouble, however there seems to be severe error in LAT and LNG. I am located at near N33.3, W86.7 but display shows LAT 56.3 and LNG 50.2. TRK = 12 AVL = 12 FIX = 9. Time is correct.
Richard
Ah.. I had put in some extra numbers so the screen and video examples didn’t show my exact lat and long. I left them in the code though so not very secret! I think this must have been added in a recent update when I pasted in some old code to fix another problem.
This section needs to be replaced:
char latchar[10]; // Buffer big enough for 9-character float
dtostrf(fix.latitude(), 3, 7, latchar); // Leave room for large numbers
u8x8.drawString(4, 2, latchar);
char longchar[10];
dtostrf(fix.longitude(), 3, 7, longchar);
Working great now!!
Thanks
Hi, I’m using an Arudino Mega, I’m recieving gps-data on serial monitor,but not on my display… how can I change the gpsPort, so that it runs GPSloop() and doSomeWork()???
Thank you for fast reply.
I’ve not tried it but apparently…
// 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.
Options for serial pins: https://www.arduino.cc/reference/en/language/functions/communication/serial/
I keep getting this when trying to compile… any ideas?
‘class U8X8_SSD1306_128X64_NONAME_HW_I2C’ has no member named ‘println’
Hi. I’m not sure. Maybe it needs
#include {Arduino.h}
(replacing the {} with <>) at the top of the sketch?
I’ll give it a try. Thank you!
I added the statement at the top that you suggested but the issue persisted.
I am wondering if the issue is that Im trying to compile this for an Arduino Nano Every instead of an Uno? I figured they would be the same but maybe not?
When I review the output further, there are actually a LOT of failures:
sketch_feb02a:46:8: error: ‘class U8X8_SSD1306_128X64_NONAME_HW_I2C’ has no member named ‘println’
u8x8.println(“Doing”);
^~~~~~~
sketch_feb02a:48:8: error: ‘class U8X8_SSD1306_128X64_NONAME_HW_I2C’ has no member named ‘println’
u8x8.println(“Some”);
^~~~~~~
sketch_feb02a:50:8: error: ‘class U8X8_SSD1306_128X64_NONAME_HW_I2C’ has no member named ‘print’
u8x8.print(“Stuff”);
^~~~~
sketch_feb02a:68:25: error: ‘class NMEAGPS’ has no member named ‘sat_count’
totalSatellites = gps.sat_count;
^~~~~~~~~
sketch_feb02a:70:13: error: ‘class NMEAGPS’ has no member named ‘satellites’; did you mean ‘parseSatellites’?
if (gps.satellites[i].tracked) {
^~~~~~~~~~
parseSatellites
From what I read the code should be the same. Maybe it’s not finding the libraries. Try removing the include for the screen and see if the error message changes.