Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Elizabeth VicarteStephanie VicarteIrak Mayer
Published © GPL3+

GPS Drivers Log

An easier alternative to using a boring, inconvenient, pen-and-paper Drivers Log!

IntermediateFull instructions provided6 hours1,499
GPS Drivers Log

Things used in this project

Hardware components

WIZ750SR
WIZnet WIZ750SR
×1
Adafruit Ultimate GPS FeatherWing
×1
Adafruit FeatherWing OLED
×1
Adafruit Feather M0 Adalogger
×1
3.7 V LiPo Battery
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Code

GPS data logger and Server using WIZ750SR and Feather family boards

Arduino
Main program to collect GPS data and serve clients to transfer the data thru the WIZ750SR
//GPS logger program using a Feather Adalogger, GPS feather wing and an OLED feather wing boards.
//7-18-2018
//IVM
//
     
#include <Adafruit_GPS.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Arduino.h>   // required before wiring_private.h
#include "wiring_private.h" // require to activate second UART

const int chipSelect = 4;

//OLED variable instance
Adafruit_SSD1306 display = Adafruit_SSD1306();

//Pins for OLED buttons.
  #define BUTTON_A 9
  #define BUTTON_B 6
  #define BUTTON_C 5
  #define LED      13

// Serial port for the GPS module
#define GPSSerial Serial1

// Connect to the GPS on the hardware port
Adafruit_GPS GPS(&GPSSerial);
     
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false

//Set the log filename
#define LOGFILENAME "GPSdlog.txt"

//Interval timer.
uint32_t timer = millis();

//Menu related variables.
int MenuSel = 0;
int CurrMenuSel = 0;
double varMPH = 0.0;
int varQuality = 0;
String varTime="";

bool varConnected = false;

#define ADDNEWSERIAL 1

//Simple activation keyword between server and client.
#define PASSCODE "gpsData"

//#ifdef ADDNEWSERIAL
//Initialize 2nd UART port.
Uart Serial2 (&sercom1, 11, 10, SERCOM_RX_PAD_0, UART_TX_PAD_2);
void SERCOM1_Handler()
{
  Serial2.IrqHandler();
}
//#endif

//Displays the main menu on the OLED display
void DisplayMainMenu()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Welcome. The digital drivers log book");
  display.println("A start GPS log");
  display.println("C transfer log.");
  display.setCursor(0,0);
  display.display(); 
  
}

//Displays the start gps log menu on the OLED display
void DisplayConfirm()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Press Button B");
  display.println("to start GPS Log");
  display.setCursor(0,0);
  display.display(); 
}

//Displays the gps log menu on the OLED display
void DisplayGPSLog()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("GPS Log Data.");
  display.display(); 
}

//Displays the server connection menu on the OLED display
void DisplayWizNet()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Opening Server");
  display.println("Waiting...");
  display.display(); 
}

//Displays the start connection menu on the OLED display
void DisplayConnect()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Connected.");
  display.println("Press B to start");
  display.println("Download");
  display.display(); 
}

//Displays the Downloading menu on the OLED display
void DisplayDownloading()
{
  display.clearDisplay();
  display.display();
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Start Transfer Data");
  display.println("Download...");
  display.display(); 
  
}

//Displays status information on the OLED display
void DisplayUpdateSpeed()
{
  display.clearDisplay();
  display.display();
  display.setCursor(0,0);
  display.println("GPS Log Data.");
  display.print("Speed(mph): ");
  display.println(String(varMPH));
  display.print("Quality: ");
  display.println(String(varQuality));
  display.print("Time: ");
  display.println(varTime);
  display.display();
}

//Initialize SD card
bool InitSD()
{
    if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    return false;
  }

  return true;
}

void setup()
{
  //while (!Serial);  // uncomment to have the sketch wait until Serial is ready
  
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");
  
  //Init display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
  //Status information displayed.
  display.clearDisplay();
  display.display();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Init SD card.");
  display.display(); 
     
  Serial.print("Initializing SD card...");

  //Start SD card
  if (!InitSD())
    return;
  
  display.println("Init SD card OK.");
  display.println("Init GPS.");
  display.display(); 
  
  Serial.println("card initialized.");
  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's
  GPS.begin(9600);
  // Turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);

  \\Give it time to initialize
  delay(1000);
  
  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);

  display.println("Init GPS OK.");
  display.display(); 
 

  Serial.println("OLED FeatherWing test");
  

  display.display();
  delay(1000);

//#ifdef ADDNEWSERIAL
  //Initialize second UART matching the settings for the WIZ750SR
   Serial2.begin(115200);
  // Assign pins 10 & 11 SERCOM functionality
  pinPeripheral(10, PIO_SERCOM);
  pinPeripheral(11, PIO_SERCOM);
//#endif

  Serial.println("IO test");

  //Initialize OLED buttons on the feather win.
  pinMode(BUTTON_A, INPUT_PULLUP);
  pinMode(BUTTON_B, INPUT_PULLUP);
  pinMode(BUTTON_C, INPUT_PULLUP);

  //Initialize Menu text.
  DisplayMainMenu(); 
}

//Function that takes care of GPS collection data and save to the SD card.
void ProcessGPS()
{
  // read data from the GPS 
  char c = GPS.read();
  // Send to serial if you really need to.
  if (GPSECHO)
    if (c) Serial.print(c);
  // Sentence is received?
  if (GPS.newNMEAreceived()) 
  {
#ifdef DEBUG_DATA
    Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
#endif
    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return; // if sentence is not complete.
  }
  // check the timer, if over the threshold --> reset.
  if (timer > millis()) timer = millis();
     
  // every 2 seconds or so, print out the current stats
  if (millis() - timer > 2000) 
  {
    timer = millis(); // reset the timer

//Display the GPS data if needed
#ifdef DEBUG_DATA
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');  //time
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: "); //date
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix); //Satellite link stablish status
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); //Quality of link
#endif

    //If a link to a satellite is stablished.
    if (GPS.fix) 
    {
      //Initialize data container.
      String dataString = "";

//Display the GPS data if needed
#ifdef DEBUG_DATA
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
#endif


      // open the file. 
      File dataFile = SD.open(LOGFILENAME, FILE_WRITE);
    
      // if the file is available, write to it:
      if (dataFile) 
      {
        //Add the data to the string buffer
        dataString += "Time: ";
        dataString += String(GPS.hour);
        dataString += ":";
        dataString += String(GPS.minute);
        dataString += ":";
        dataString += String(GPS.seconds);
        dataString += ".";
        dataString += String(GPS.milliseconds);
        varTime = String(GPS.hour);
        varTime += ":";
        varTime += String(GPS.minute);
        varTime += ":";
        varTime += String(GPS.seconds);
        varTime += ".";
        varTime += String(GPS.milliseconds);
        dataString += " Date: ";
        dataString += String(GPS.day);
        dataString += "-";
        dataString += String(GPS.month);
        dataString += "-20";
        dataString += String(GPS.year);
        dataString += " Fix: "; 
        dataString += String((int)GPS.fix);
        dataString += " quality: "; 
        dataString += String((int)GPS.fixquality);
        dataString += "Location: ";
        dataString += String(GPS.latitude);
        dataString += String(GPS.lat);
        dataString += String(", ");
        dataString += String(GPS.longitude);
        dataString += String(GPS.lon);
        dataString += String(", ");
        dataString += " Speed (knots): ";
        dataString += String(GPS.speed);
        dataString += String(", ");
        dataString += " Angle: ";
        dataString += String(GPS.angle);
        dataString += String(", ");
        dataString += " Altitude: ";
        dataString += String(GPS.altitude);
        dataString += String(", ");
        dataString += " Satellites: ";
        dataString += String((int)GPS.satellites);

        //Convert gps speed from knots to mph.
        varMPH = GPS.speed * 1.15078;
        varQuality = (int)GPS.fixquality;
        //Update speed to OLED display
        DisplayUpdateSpeed();
        
        dataFile.println(dataString);
        dataFile.close();
        // print to the serial port too:
#ifdef DEBUG_DATA
        Serial.print(dataString);
#endif

      }
      // if the file isn't open, pop up an error:
      else {
        Serial.println("error opening datalog.txt");
      }

    }
  }
}

//Function to read the gps log file and transfer it to the client.
bool SendFile()
{
  File dataFile = SD.open(LOGFILENAME);

  if (dataFile) {
    while (dataFile.available()) {
      //Send data thru UART 2 port
      Serial2.write(dataFile.read());
    }
    dataFile.close();
    Serial2.write("Bye");
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    return false;
  }
  
  return true;
}

//Function that waits for a client to connect. The function checks for the passcode to match in order to start a communication link.
bool Connect2Client()
{
  //return true;
  
  if (Serial2.available()) 
  {
    String dataRead="";
    
    while (Serial2.available())
    {
      char inByte = Serial2.read();
      if (inByte != '\n' && inByte != '\r')
        dataRead += inByte;
      Serial.write(inByte);
      delay(50);
    }

    Serial.print(String(dataRead.length()));
    Serial.print(String(PASSCODE).length());
    Serial.println(dataRead);
    //Check for passcode. If correct return communicaton stablished.
    if (dataRead.compareTo(String(PASSCODE)) == 0)
      return true;
    
  }
  
  return false;
}

//Main menu loop.
void loop() // run over and over again
{

//Menu Selection.
  if (CurrMenuSel == 0)
  {
    
    if (! digitalRead(BUTTON_A))
    {
      MenuSel =  1;
    }
    
    if (! digitalRead(BUTTON_C)) 
    {
      varConnected = false;
      MenuSel = 3;
    }
  }
  else if (CurrMenuSel == 1)
  {
      if (! digitalRead(BUTTON_B)) 
      {
        MenuSel = 2;
      }

      if (! digitalRead(BUTTON_C)) 
      {
        MenuSel = 0;
      }
  }
  else if (CurrMenuSel == 2)
  {
      ProcessGPS();
     
      if (! digitalRead(BUTTON_A))
      {
        MenuSel =  0;
      }
      
      if (! digitalRead(BUTTON_C)) 
      {
        MenuSel = 0;
      }
  }
  else if (CurrMenuSel == 3)
  {
      if (!varConnected)
      {
        if (Connect2Client())
        {
          varConnected = true;
          DisplayConnect();
        }
      }
      
      if (!digitalRead(BUTTON_B)) 
      {
        if (varConnected == true)
        {
          MenuSel =4;
        }
        else
        {
          MenuSel = 0;
        }
      }

      if (! digitalRead(BUTTON_A))
      {
        MenuSel =  0;
      }
  }
  else if (CurrMenuSel == 4)
  {
     
    {
      SendFile();
    }

    MenuSel = 0;
  }

//Main task execute 
   if (CurrMenuSel != MenuSel)
   {
     if (MenuSel == 0)
     {
        DisplayMainMenu();
     }
     else if (MenuSel == 1)
     {
        DisplayConfirm();
     }
     else if (MenuSel  == 2)
     {
        DisplayGPSLog();
     }
     else if (MenuSel == 3)
     {
        DisplayWizNet();
     }
     else if (MenuSel == 4)
     {
        DisplayDownloading();
     }

//Try to clear the buffer from the buttons
     CurrMenuSel = MenuSel;
     digitalRead(BUTTON_A);
     digitalRead(BUTTON_B);
     digitalRead(BUTTON_C);
   }
      
}

Python client to get GPS data from logger

Python
Request a connection to the server (data logger), sends passcode, receives data and saves on a local file.
import socket
import sys

def client_prog():
    host = "192.168.1.75"
    port = 5000
    initFile = False
    outFile = None
    outfilename ="gpsDatalog.txt"

    #initialize a socket
    client_socket = socket.socket()
    #Request a communication link with the server
    client_socket.connect((host, port))

    #Passcode
    message = "gpsData"

    #Meanwhile server does not send the close link passcode
    while message.lower().strip() != 'bye':
        #Send passcode
        client_socket.send(message.encode())
        #Read data from server
        data = client_socket.recv(1024).decode()

        #Print debug information or data received.
        print('Received from server: '+data)

        #if file has not being initialize then open file.
        if (initFile == False):
            outFile = open(outfilename,'w')
            initFile = True

        #Write to file data raceived.
        outFile.write(data)
        message = data[-4:]

    #close the communication channel
    client_socket.close()
    #close file
    outFile.close()

if __name__ == '__main__':
    client_prog()

Credits

Elizabeth Vicarte

Elizabeth Vicarte

13 projects • 7 followers
Stephanie Vicarte

Stephanie Vicarte

14 projects • 12 followers
Irak Mayer

Irak Mayer

18 projects • 10 followers

Comments