wrighi
Published

GPS Distance altitude and Speed Logger

A simple project to make a GPS log station with data speed, max speed, distance trip and altitude. all data are write on SD card

IntermediateFull instructions provided10,066
GPS Distance altitude and Speed Logger

Things used in this project

Hardware components

GPS Module (Generic)
generic gps neo6m u-blox (much better with USB socket as to setup module in u-blox center program)
×1
Arduino Nano R3
Arduino Nano R3
×1
Graphic OLED, 128 x 64
Graphic OLED, 128 x 64
oled 0,96'' monocromatic 128x64 SDD 1306 (better white)
×1
Memory Socket, SD Card
Memory Socket, SD Card
SD card writer/reader for micro or normal SD cards
×1
Graphic OLED, 128 x 64
Graphic OLED, 128 x 64
oled white 1.3'' SH1106 is bigger and better compared with small 0,96'' SSD 1306
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

schematics

connect wires by colors

gps_mgebcsszu1_5rDBAfZKUE.fzz

schematics

basically the same circuit but maybe can help

Code

display 1306 0,96''

Arduino
use this with 0,96'' 4 pin oled 128x64 display
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>

#include <NeoSWSerial.h>
const int cs_sd=2;
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
File myFile;
float odo;
float Speed; 
float alt;

NeoGPS::Location_t    lastLoc;
bool                  lastLocOK = false;
static const int RXPin = 5, TXPin = 4; //-- gps pin
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);
const int SHOW_INTERVAL = 1;
const int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1; 
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;  //-- led on at speed limit
const float SPEED_LIMIT = 0.0; // --setup speed limit value es: 55.0; kmh default 0.0
int maxs = 0; 
void setup(){
  
  pinMode (LED_PIN, OUTPUT);
Serial.begin(9600);
gpsPort.begin(GPSBaud);
Wire.begin();
oled.begin(& Adafruit128x64, I2C_ADDRESS);
oled.setFont(TimesNewRoman16);
oled.clear();
oled.println(" ");
oled.println("  GPS LOGGER"); //you can custom this text
oled.println(" ");
oled.println("   WELCOME"); //you can custom this text
delay(3000);
oled.clear();
if(!SD.begin(cs_sd)){
oled.clear();
oled.println(" ");
oled.print("NO SD");
delay(3000);
return;}
oled.println(" ");
oled.print(" SD Card OK");
delay(2000);
oled.clear();
File data = SD.open("log.csv",FILE_WRITE);              
data.println(""); 
data.println("Dat  Hr+  Lat  Lon  Alt  Vel  Dis" ); 
data.close();}
void loop(){
if (gps.available( gpsPort )) {  
gps_fix fix = gps.read();  
show = (show + 1) % SHOW_INTERVAL;
if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
    digitalWrite( LED_PIN, HIGH );   
 } else {
 digitalWrite( LED_PIN, LOW ); } 
 if (fix.valid.location) { 
 if (lastLocOK) {
 odo += fix.location.DistanceKm( lastLoc );
 Speed = (fix.speed_kph());}
lastLoc   = fix.location;
lastLocOK = true;}
if ( Speed > maxs) 
maxs = Speed;
if (fix.valid.altitude)
 alt = ( fix.altitude () );
 
if (show == 0) {
#define MAX_CHARS 24
char displayBufffer[MAX_CHARS];
oled.setCursor(0,0);   
snprintf(displayBufffer, MAX_CHARS, " DIST :  %  3d.%02d", (int)odo, (int)(odo * 100)%100);//distance
oled.println(displayBufffer);   
snprintf(displayBufffer, MAX_CHARS, " KMH:  %  3d.%02d", (int)Speed, (int)(Speed * 100)%100);//speed
oled.println(displayBufffer);
snprintf(displayBufffer, MAX_CHARS, " MxSP: %  3d.%02d", (int)maxs, (int)(maxs * 100)%100);//max top speed
oled.println(displayBufffer);
snprintf(displayBufffer, MAX_CHARS, " ALT  :  %  3d.%02d", (int)alt, (int)(alt * 100)%100);//altitude
oled.println(displayBufffer);} 
if (fix.dateTime);   
String Temps=String(fix.dateTime.hours )+(":")+(fix.dateTime.minutes)+(":")+(fix.dateTime.seconds);
String Date=String(fix.dateTime.date )+("/")+(fix.dateTime.month)+("/")+(fix.dateTime.year);  
File data=SD.open("log.csv",FILE_WRITE);
data.println(Date +("  ")+ Temps +("  ")+ String(fix.latitude(), 6)+("  ")+String(fix.longitude(), 6)+("  ")+(alt)+("  ") +(Speed)+("  ")+(odo)); 
data.close();}}

display sh1106 1,3''

Arduino
code for large 1,3'' 4 pin 128x64 display
#include <SPI.h>
#include <SD.h>
#include <Wire.h>

#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>
//#include <SoftwareSerial.h> //check library or change neoSWSerial.h
#include <NeoSWSerial.h>
const int cs_sd=2;
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
File myFile;
float odo;
float Speed; 
float alt;

NeoGPS::Location_t    lastLoc;
bool                  lastLocOK = false;
static const int RXPin = 5, TXPin = 4; //-- gps pin
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);
const int SHOW_INTERVAL = 1;
const int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1; 
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;
const float SPEED_LIMIT = 0.0; // --setup speed limit value es: 55.0; kmh default 0.0
int maxs = 0; 
void setup(){
  
  pinMode (LED_PIN, OUTPUT);
Serial.begin(9600);
gpsPort.begin(GPSBaud);
Wire.begin();
oled.begin(&SH1106_128x64, I2C_ADDRESS);
oled.setFont(ZevvPeep8x16);
oled.clear();
oled.println(" ");
oled.println("  GPS LOGGER"); 
oled.println(" ");
oled.println("   WELCOME"); 
delay(3000);
oled.clear();
if(!SD.begin(cs_sd)){
oled.clear();
oled.println(" ");
oled.print("NO SD");
delay(3000);
return;}
oled.println(" ");
oled.print(" SD Card OK");
delay(2000);
oled.clear();
File data = SD.open("log.csv",FILE_WRITE);              
data.println(""); 
data.println("Dat  Hr+  Lat  Lon  Alt  Vel  Dis" ); 
data.close();}
void loop(){
if (gps.available( gpsPort )) {  
gps_fix fix = gps.read();  
show = (show + 1) % SHOW_INTERVAL;
if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
    digitalWrite( LED_PIN, HIGH );   
 } else {
 digitalWrite( LED_PIN, LOW ); } 
 if (fix.valid.location) { 
 if (lastLocOK) {
 odo += fix.location.DistanceKm( lastLoc );
 Speed = (fix.speed_kph());}
lastLoc   = fix.location;
lastLocOK = true;}
if ( Speed > maxs) 
maxs = Speed;
if (fix.valid.altitude)
 alt = ( fix.altitude () );
 
if (show == 0) {
#define MAX_CHARS 24
char displayBufffer[MAX_CHARS];
oled.setCursor(0,0);   
snprintf(displayBufffer, MAX_CHARS, " K m :% 3d.%02d", (int)odo, (int)(odo * 100)%100);
oled.println(displayBufffer);   
snprintf(displayBufffer, MAX_CHARS, " Kmh :% 3d.%02d", (int)Speed, (int)(Speed * 100)%100);
oled.println(displayBufffer);
snprintf(displayBufffer, MAX_CHARS, " Mspd:% 3d.%02d", (int)maxs, (int)(maxs * 100)%100);
oled.println(displayBufffer);
snprintf(displayBufffer, MAX_CHARS, " Alt :% 3d.%02d", (int)alt, (int)(alt * 100)%100);
oled.println(displayBufffer);} 
if (fix.dateTime);   
String Temps=String(fix.dateTime.hours )+(":")+(fix.dateTime.minutes)+(":")+(fix.dateTime.seconds);
String Date=String(fix.dateTime.date )+("/")+(fix.dateTime.month)+("/")+(fix.dateTime.year);  
File data=SD.open("log.csv",FILE_WRITE);
data.println(Date +("  ")+ Temps +("  ")+ String(fix.latitude(), 6)+("  ")+String(fix.longitude(), 6)+("  ")+(alt)+("  ") +(Speed)+("  ")+(odo)); 
data.close();}}

more data on display sh1106 1.3 version 2021''

Arduino
add "Di" aerial distance (km) from fix point base. add "S"satellites count. add "Am"max altitude. add "He"heading degrees (360° N 180° S) previous data: "Km" odometer travel distance, "Sp" live speed, "Sm" max speed, "Al" altitude slm.
display now is full with 8 informations data most of it collect to SD card (just heading and satellite count are not)
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>
#include <NeoSWSerial.h>
#define I2C_ADDRESS 0x3C
#define RST_PIN -1
#define MAX_CHARS 24
#define RX_pin 5
#define TX_pin 4
#define SHOW_INTERVAL 1
#define GPS_baud 9600
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
float odo, Speed, alt, Dist, head, maxs = 0, Am = 0;
unsigned int Sat = 0;
NeoGPS::Location_t    lastLoc, base;
bool stScan = true, lastLocOK = false;
static NeoSWSerial gpsPort(RX_pin, TX_pin);
static constexpr int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1;
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;
const float SPEED_LIMIT = 0.1; // speed limit value
void disp(int c, int r)
{
  oled.clear();
  oled.setCursor(c, r);
}
void setup() {

  pinMode (LED_PIN, OUTPUT);
  Serial.begin(9600);
  gpsPort.begin(GPS_baud);
  Wire.begin();
  oled.begin(&SH1106_128x64, I2C_ADDRESS);
  oled.setFont(ZevvPeep8x16);
  oled.clear();
  disp(30, 2);// as to center your name change 30
  oled.println("YourName");//10 characters available here
  delay(2000);
  disp(55, 2);
  oled.print("GPS");//5 characters available here
  delay(2000);
  oled.clear();
  const int cs_sd = 2;
  if (!SD.begin (cs_sd)) {
    oled.clear();
    disp(60, 2);
    oled.print("SD");//if you read this on display mean SD is not present
    delay(10000);
    oled.clear();
    return;
  }
  disp(60, 2);
  oled.print("OK");
  delay(2000);
  oled.clear();
  File data = SD.open("L.csv", FILE_WRITE);
  data.println("");
  data.println("Da  Hr  La  Lo  At  Am  Km  Di  Sp  He  Sa" );
  data.close();
}
void loop() {
  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();
    show = (show + 1) % SHOW_INTERVAL;
    if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
      digitalWrite( LED_PIN, HIGH );
    } else {
      digitalWrite( LED_PIN, LOW );
    }
    if (fix.valid.location) {
      if (lastLocOK) {
        odo += fix.location.DistanceKm( lastLoc );
        Speed = fix.speed_kph();
      }
      lastLoc   = fix.location;
      lastLocOK = true;
      if (stScan) {
        stScan = false;
        base   = fix.location;
      } else {
        Dist = ( fix.location.DistanceKm( base ) );
      }
    }
    if ( Speed > maxs)          maxs = Speed;
    if (fix.valid.heading )     head = fix.heading() ;
    if (fix.valid.satellites )  Sat = fix.satellites ;
    if (fix.valid.altitude)     alt = fix.altitude();
    if ( alt > Am)              Am = alt;
         if (show == 0) {
        char displayBufffer[MAX_CHARS];
        oled.setCursor(0, 0);
        snprintf(displayBufffer, MAX_CHARS, "Km:%2d.%1d",  (int)odo, (int)(odo * 100) % 100);
        oled.println(displayBufffer);
        oled.setCursor(65, 0);
        snprintf(displayBufffer, MAX_CHARS, "Di:%2d.%1d",  (int)Dist, (int)(Dist * 100) % 100);
        oled.println(displayBufffer);
        snprintf(displayBufffer, MAX_CHARS, "Sp:%2d.%1d", (int)Speed, (int)(Speed * 10) % 10);
        oled.println(displayBufffer);
        oled.setCursor(65, 2);
        snprintf(displayBufffer, MAX_CHARS, "Sm:%2d.%1d", (int)maxs, (int)(maxs * 10) % 10);
        oled.println(displayBufffer);
        snprintf(displayBufffer, MAX_CHARS, "Al:%2d.%1d", (int)alt, (int)(alt * 100) % 100);
        oled.println(displayBufffer);
        oled.setCursor(65, 4);
        snprintf(displayBufffer, MAX_CHARS, "Am:%2d.%1d", (int)Am, (int)(Am * 100) % 100);
        oled.println(displayBufffer);
        snprintf(displayBufffer, MAX_CHARS, "Sa: %d", (int)Sat);
        oled.println(displayBufffer);
        oled.setCursor(65, 6);
        snprintf(displayBufffer, MAX_CHARS, "He:%2d.%1d", (int)head, (int)(head * 100) % 100);
        oled.println(displayBufffer);
      }
    File data = SD.open("L.csv", FILE_WRITE);
    data.print(fix.dateTime.hours + 2);
    data.print(":");
    data.print(fix.dateTime.minutes);
    data.print("  ");
    data.print(fix.dateTime.date);
    data.print("/");
    data.print(fix.dateTime.month);
    data.print("  ");
    data.print(fix.latitude(), 6);
    data.print("  ");
    data.print(fix.longitude(), 6);
    data.print("  ");
    data.print(alt);
    data.print("  ");
    data.print(Am);
    data.print("  ");
    data.print(odo);
    data.print("  ");
    data.print(Dist);
    data.print("  ");
    data.print(Speed);
    data.print("  ");
    data.print(head);
    data.print("  ");
    data.print(Sat);
    data.println();
    data.close();
  }
}

10/2021 update compass 16 sectors

Arduino
a new code version for oled 1.3'' sh1106 with travel time and compass 16 sectors
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#include <NMEAGPS.h>
#include <NeoSWSerial.h>

#define I2C_ADDRESS 0x3C
#define RST_PIN -1
#define MAX_CHARS 24
#define RX_pin 5
#define TX_pin 4
#define SHOW_INTERVAL 1
#define GPS_baud 9600
SSD1306AsciiWire oled;
NMEAGPS gps;
gps_fix fix;
float odo, Dist;
unsigned int head, Speed, alt, Sat = 0, maxs = 0;

NeoGPS::Location_t    lastLoc, base;
bool stScan = true, lastLocOK = false;
bool altOK = false;
bool Satok = false;
static NeoSWSerial gpsPort(RX_pin, TX_pin);
static constexpr int INITIAL_SHOW  = (2 * SHOW_INTERVAL) - 1;
int show          = INITIAL_SHOW;
const int   LED_PIN  = 3;
const float SPEED_LIMIT = 0.1; // speed limit value

void disp(int c, int r) {
  oled.clear();
  oled.setCursor(c, r);
}

const char* strBussola[16] = {"N  ", "NNe", "NE ", "EnE", "E  ", "EsE",
                              "SE ", "SSe", "S  ", "SSw", "SW ", "WsW", "W  ", "WnW", "NW ", "NNw"
                             };
int index;

int trovaIndice(float angolo) {
  int _index;
  for (_index = 0; _index < 16; _index++) {
    float angoloDirezione = _index * 22.25 + 11.25;
    float angoloMin = angoloDirezione - 11.25;
    float angoloMax = angoloDirezione + 11.25;
    if (angolo >= angoloMin && angolo <= angoloMax)
      return _index;
  }
  return _index;
}

void setup() {
  pinMode (LED_PIN, OUTPUT);
  Serial.begin(9600);
  gpsPort.begin(GPS_baud);
  Wire.begin();
  oled.begin(&SH1106_128x64, I2C_ADDRESS);
  oled.setFont(ZevvPeep8x16);
  //oled.displayRemap(true); // inversione dello schermo display
  disp(0, 2);
  oled.println(F(" YOUR  NAME "));// put your name here
  delay(1500);
  oled.setCursor(24, 5);
  oled.println(F("GPS LOGGER"));
  delay(2500);
  oled.clear();
  const int cs_sd = 2;
  if (!SD.begin (cs_sd)) {
    oled.clear();
    disp(50, 2);
    oled.print(F("SD"));
    delay(10000);
    oled.clear();
  }
  File data = SD.open("L.csv", FILE_WRITE);
  data.println("");
  data.println(F("D H T La Lo At Km Di Ve He Co Sa" ));
  data.close();
}

void loop() {
  unsigned long tmp = millis() / 1000;
  byte secondi = tmp % 60;
  byte minuti = (tmp / 60) % 60;
  byte ore = (tmp / 3600) % 24;

  if (gps.available( gpsPort )) {
    gps_fix fix = gps.read();
    show = (show + 1) % SHOW_INTERVAL;
    if (fix.valid.speed && (fix.speed_kph() > SPEED_LIMIT)) {
      digitalWrite( LED_PIN, HIGH );
    } else {
      digitalWrite( LED_PIN, LOW );
    }
    if (fix.valid.location) {
      if (lastLocOK) {
        odo += fix.location.DistanceKm( lastLoc );
        Speed = fix.speed_kph();
      }
      lastLoc   = fix.location;
      lastLocOK = true;
      if (stScan) {
        stScan = false;
        base   = fix.location;
      } else {
        Dist = ( fix.location.DistanceKm( base ) );
      }
    }
    if ( Speed > maxs)          maxs = Speed;
    if (fix.valid.satellites ) {
      Sat = fix.satellites ;
      Satok = true;
    }


    if (fix.valid.heading ) {
      head = fix.heading() ;
      index = trovaIndice(head);
    }

    if (fix.valid.altitude){ 
      alt = fix.altitude();
     altOK = true;
    }

    if (show == 0) {
      char displayBufffer[MAX_CHARS];
      oled.setCursor(0, 0);
      snprintf(displayBufffer, MAX_CHARS, "Km: %d.%d",  (int)odo, (int)(odo * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 0);
      snprintf(displayBufffer, MAX_CHARS, "Ve: %d", (int)Speed, (int)(Speed * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "Di: %d.%d",  (int)Dist, (int)(Dist * 100) % 100);
      
      oled.println(displayBufffer);
     oled.setCursor(65, 2);
     snprintf(displayBufffer, MAX_CHARS, "Vm: %d", (int)maxs, (int)(maxs * 100) % 100);
      
      oled.println(displayBufffer);

      snprintf(displayBufffer, MAX_CHARS, "Al: %d", (int)alt, (int)(alt * 100) % 100);
      oled.println(displayBufffer);
      oled.setCursor(65, 4);
      snprintf(displayBufffer, MAX_CHARS, "He: %d", (int)head, (int)(head * 100) % 100);
      oled.println(displayBufffer);
      snprintf(displayBufffer, MAX_CHARS, "%d:%d:%d ", (int)ore, (int)minuti, (int)secondi);
      oled.println(displayBufffer);
      oled.setCursor(65, 6);
      snprintf(displayBufffer, MAX_CHARS, "Co: %s\n", (strBussola[index]));
      
      oled.println(displayBufffer);
    }
    File data = SD.open("L.csv", FILE_WRITE);
    data.print(fix.dateTime.hours + 2);
    data.print(":");
    data.print(fix.dateTime.minutes);
    data.print(" ");
    data.print(fix.dateTime.date);
    data.print("/");
    data.print(fix.dateTime.month);
    data.print(" ");
    data.print(ore);
    data.print(":");
    data.print(minuti);
    data.print(":");
    data.print(secondi);
    data.print(" ");
    data.print(fix.latitude(), 6);
    data.print(" ");
    data.print(fix.longitude(), 6);
    data.print(" ");
    data.print(alt);
    data.print(" ");

    data.print(odo);
    data.print(" ");
    data.print(Dist);
    data.print(" ");
    data.print(Speed);
    data.print(" ");
    data.print(head);
    data.print(" ");
    data.print(strBussola[index]);
    data.print(" ");
    data.print(Sat);
    data.println();
    data.close();
  }
}

Credits

wrighi

wrighi

3 projects • 1 follower

Comments