Arduino GPS 6MV2

GPS, een afkorting van Global Positioning System. In eerste instantie in 1967 ontwikkeld voor militaire toepassing (denk aan kruisraketten, lange afstands-raketten), maar dit wordt nu ( vanaf 1983) ook erg veel gebruikt in civiele toepassingen. Positie bepaling, tijdsynchronisatie zijn een paar veel voorkomende toepassingen.

Het GPS systeem een nauwkeurigheid van zo'n 10 meter. Dit is verder op te voeren met DGPS (Differentieal GPS). Een aardse GPS zender waarvan de positie bekend is zend uit op een frequentie van 283,5 tot 325 KHz. Nauwkeurigheid ongeveer 2 meter. Dit is nog verder te verbeteren met RTK, nauwkeurigheid tot 2 millimeter. (afhankelijk van de gebruikte golflengte).

Naast het Amerikaanse GPS systeem bestaat er ook nog het GLONASS (Russisch) en het Galileo (Europese) systeem.

De toepassing die waarvoor ik een GPS ontvanger nodig had is het bepalen van een een redelijk nauwkeurige tijdbron om een WSPR baken zender te bouwen. Een klok-chip zou deze functie ook kunnen vervullen, maar na enige tijd is het synchroniseren van de zo'n tijdbron noodzakelijk omdat deze niet stabiel genoeg zijn. De tijd van een referentieklok op het internet betrekken is ook een optie, maar als er op de betreffende locatie geen connectie met het internet mogelijk is dan valt deze optie ook af.

De GPS module GPS6MV2 bevat een complete U-Blox NEO 6 ontvanger module. De module heeft een voedingspanning van 2,7 - 3,6 Volt nodig. Mogelijke interfaces zijn UART, SPI, USB, DCC (I2C compliant). Uit de UART komt 9600 Bps ASCII data. Dit is zeer goed te verwerken met een Arduino controller.

De ASCII data die door de ontvanger aangeboden wordt NMEA datagrammen (National Marine Electronics Association).  Als je met de datastroom uit de ontvanger mee leest dan zie je berichten die met een $ beginnen.

  • $GPGGA: Global Positioning System Fix Data
  • $GPGSV: GPS satellites in view
  • $GPGSA: GPS DOP and active satellites
  • $GPRMC: Recommended minimum specific GPS/Transit data
  • enzovoort.

Meer informatie over het NMEA protocol kan gevonden worden op deze site.

De Arduino kan de GPS module uitlezen met de library SoftSerial.h, en de library TinyGPS++, deze bevat alles voor het decoderen van de NMEA datagrammen. Ook bevat de library TinyGPS++ een aantal demo voorbeelden. Helaas had ik daarbij steeds last van verminkte data. Bijvoorbeeld het aantal zichtbare GPS satellieten gaf vreemde waarden weer. Als je controleert of er een buffer overflow is geweest dan wordt dit inderdaad bevestigd.

[crayon]
if (ss.overflow()) {
Serial.println("SoftwareSerial overflow!");
}
[/crayon]
 

De code om de GFS module uit te lezen:
[crayon]
/*
 Berto van Oorspronk
 PA3HFN
 Test GPG module GPS6MV2 module
 with the AltSoftSerial and the TinyGPS++ module
 */
 
// Loading library's
#include <AltSoftSerial.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 8, TXPin = 9;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device, PIN 8 and 9
AltSoftSerial ss(RXPin, TXPin);

void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (ss.available() > 0)
    if (gps.encode(ss.read()))
      displayInfo();

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  }
}

void displayInfo()
{
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    Serial.print(gps.location.lat(), 6);
    Serial.print(F(","));
    Serial.print(gps.location.lng(), 6);
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Datum/Tijd: "));
  if (gps.date.isValid())
  {
    Serial.print(gps.date.day());
    Serial.print(F("-"));
    Serial.print(gps.date.month());
    Serial.print(F("-"));
    Serial.print(gps.date.year());
  }
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F(" "));
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
    // Sats visible
    Serial.print(F(" Sats="));
    Serial.println(gps.satellites.value());
  }
  else
  {
    Serial.print(F("INVALID"));
  }
  delay(1000);
  //Serial.println();
}
[/crayon]
Door de ontvangen long/lat coördinaten (10.000 records) op een kaart te zetten zie je de afwijking van de GPS ontvanger. De opgegeven nauwkeurigheid van het GPS systeem is ongeveer 10 meter doordat er fasedraaiing in de atmosfeer kan ontstaan of reflecties van het signaal door bebouwing.

10.000 GPS metingenDe ontvangen data geeft dit dan ook weer, De ontvanger ontving minimaal 9 en maximaal 12 satellieten tijdens het opslaan van de records.

 

 

 

Gebruikte code hiervoor:
[crayon]
/*
Berto van Oorspronk
PA3HFN
Test GPG module GPS6MV2 module
with the AltSoftSerial and the TinyGPS++ module
*/

// Loading library's
#include
#include <TinyGPS++.h>
#include

static const int RXPin = 8, TXPin = 9;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device, PIN 8 and 9
AltSoftSerial ss(RXPin, TXPin);

void setup()
{
Serial.begin(115200);
ss.begin(GPSBaud);

Serial.println("Lat;Long-s /dev/ttyACM0;Date;Time;Sats");
}

void loop()
{
// This sketch displays information every time a new sentence is correctly encoded.
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();

if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("No GPS detected: check wiring."));
while(true);
}
}

void displayInfo()
{
//Serial.print(F("Location: "));
if (gps.location.isValid())
{
Serial.print(gps.location.lat(), 6);
Serial.print(F(";"));
Serial.print(gps.location.lng(), 6);
Serial.print(F(";"));
}
else
{
Serial.print(F("INVALID"));
}

//Serial.print(F(" Datum/Tijd: "));
if (gps.date.isValid())
{
Serial.print(gps.date.day());
Serial.print(F("-"));
Serial.print(gps.date.month());
Serial.print(F("-"));
Serial.print(gps.date.year());
}
else
{
Serial.print(F("INVALID"));
}

Serial.print(F(";"));
if (gps.time.isValid())
{
if (gps.time.hour() < 10) Serial.print(F("0"));
Serial.print(gps.time.hour());
Serial.print(F(":"));
if (gps.time.minute() < 10) Serial.print(F("0"));
Serial.print(gps.time.minute());
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.print(gps.time.second());
Serial.print(F("."));
if (gps.time.centisecond() < 10) Serial.print(F("0"));
Serial.print(gps.time.centisecond());
// Sats visible
Serial.print(F(";"));
Serial.println(gps.satellites.value());
}
else
{
Serial.print(F("INVALID"));
}
delay(1000);
//Serial.println();
}
[/crayon]