Thursday 17 December 2015

Arduino and the TinyGPS module

I've ordered this Tiny GPS module of eBay and as usual by the time it arrives in Namibia (~ 3 months later) I can't remember why I got it in the first place. So I decided to hooked it up to my Arduino Uno.

After Googling I found a DFRobot Wiki with some sample code, wiring,  and links to the required library.



I've modifying the code a bit and was able to retrieve information from the GPS, but the format was decimal degrees and I would like to get  the DMS format. This was the most tricky part, but I finally got it right, or at least I think so.

I've also added some additional readings just for fun...

The code

#include <TinyGPS.h>
#include <Wire.h>
#include <LiquidCrystal.h>

TinyGPS gps;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);              //LCD driver pins
int led = 13;

long lat, lon;
unsigned long fix_age, time, date, speed, course;
unsigned long chars;
unsigned short sentences, failed_checksum;
int year;
byte month, day, hour, minute, second, hundredths;
int Timezone = 2;                  //GMT +2:00
long alt;

int DEG;
int MIN;
float SEC;
long LATT, LONG;
char N_S, E_W;

int counter;

 
void LAT(){                        //Latitude state
  LATT=lat;
 
  if (LATT < 0)
  {
    N_S = 'S';
    LATT = -LATT;
  }
  else
  {
    N_S = 'N'; 
  }
 
  DEG = (int)(LATT/1000000);              //Get the Degrees
  LATT = LATT - (DEG*1000000);            //Remove the degrees from the calculation
  MIN = LATT*60/1000000;                  //Convert to minutes
  LATT = LATT*60 - (MIN*1000000);          //Remove the minutes from the calculation
  SEC = float(LATT)*60/1000000;

  lcd.setCursor(0,0);             // set the LCD cursor   position
  lcd.print(N_S);
  lcd.print(DEG);
  lcd.write(0xDF);
  lcd.print(MIN);
  lcd.print("'");
  lcd.print(SEC);
  lcd.write(0x22);
  lcd.print("           ");
}


void LON(){                        //Longitude state
  LONG=lon;
 
  if (LONG < 0)
  {
    E_W = 'W';
    LONG = -LONG;
  }
  else
  {
    E_W = 'E'; 
  }
 
  DEG = (int)(LONG/1000000);              //Get the Degrees
  LONG = LONG - (DEG*1000000);            //Remove the degrees from the calculation
  MIN = LONG*60/1000000;                 //Convert to minutes
  LONG = LONG*60 - (MIN*1000000);          //Remove the minutes from the calculation
  SEC = float(LONG)*60/1000000;

  lcd.setCursor(0,1);              // set the LCD cursor   position
  lcd.print(E_W);             
  lcd.print(DEG);
  lcd.write(0xDF);
  lcd.print(MIN);
  lcd.print("'");
  lcd.print(SEC);
  lcd.write(0x22);
  lcd.print("                ");
}



void setup()
{
  Serial.begin(9600);            //Set the GPS baud rate.

  pinMode(led, OUTPUT); 

  lcd.begin(16, 2);               // start the library
  lcd.setCursor(0,0);             // set the LCD cursor   position
  lcd.print("Nico's GPS");          // print a simple message on the LCD
  delay(2000);
  counter = 0;
}

void Date_Time() {

  lcd.setCursor(0,0);              // set the LCD cursor   position
  lcd.print(year); 
  lcd.print("-"); 
  lcd.print(month);
  lcd.print("-");
  lcd.print(day);
  lcd.print("          ");
 
  lcd.setCursor(0,1);              // set the LCD cursor   position
  lcd.print(hour + Timezone); 
  lcd.print(":"); 
  lcd.print(minute);
  lcd.print(":");
  lcd.print(second);
  lcd.print("          ");

 
}

void Altitude(){
  lcd.setCursor(0,0);              // set the LCD cursor   position
  lcd.print("Alt: ");
  lcd.print(gps.f_altitude());
  lcd.print(" m         ");
}

void Satellites(){
  lcd.setCursor(0,1);              // set the LCD cursor   position
  lcd.print("Satellites: ");
  lcd.print(gps.satellites());
  lcd.print("          ");
}

void Speed(){
  lcd.setCursor(0,0);              // set the LCD cursor   position
  lcd.print("KM/h: ");
  lcd.print(gps.f_speed_kmph());
  lcd.print("          ");
}

void Course(){
  lcd.setCursor(0,1);              // set the LCD cursor   position
  lcd.print("Course: ");
  lcd.print(gps.f_course());
  lcd.write(0xDF);
  lcd.print("          ");
}

void loop()
{
  while (Serial.available())
  {
    digitalWrite(led, HIGH);
    int c = Serial.read();                   // Read the GPS data
    if (gps.encode(c))                        // Check the GPS data
    {
      // process new gps info here
    }

  }
  digitalWrite(led, LOW);
  gps.get_position(&lat, &lon, &fix_age);     // retrieves +/- lat/long in 100000ths of a degree
  gps.get_datetime(&date, &time, &fix_age);   // time in hhmmsscc, date in ddmmyy

  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age); 

  counter++;

  if (counter >= 0 && counter <=1000) {
      LAT();
      LON();
  }
  if (counter >= 1001 && counter <=2000) {
      Date_Time();
  }
 
  if (counter >= 2001 && counter <=3000) {
      Altitude();
      Satellites();
  }
 
  if (counter >= 3001 && counter <=4000) {
      Speed();
      Course();
  }
 
  if (counter > 4000) {
      counter = 0;
  }

}


With the data I can now collect from the GPS module, I decided to search for a SD Card module to create a log file with entries every 5 seconds or so. I found and ordered the module again from eBay.

In the meanwhile I decided to replace the Arduino Uno with one of those cheap eBay Arduino Nanos.



After struggling for a while to get the cheap clone Arduino Nano to work I found this great posting on kiguino.moos.io explaining the issue and how to fix it.

I also had to add a symbolic link to get it working on my Mac:

sudo ln -s/dev/cu.usbmodem411 /dev/tty.wchusbserial1410


So what's next


Once the logger arrives I will add that to the Arduino Nano and if I'm brave enough I will attempt to get it all working on a PIC Micro Controller.

No comments:

Post a Comment