giovedì 1 ottobre 2015

Ricevitore GPS per Arduino

Sto lavorando per interfacciare Arduino con un ricevitori GPS e ne ho presi un paio, di prezzo nettamente differente, per delle prove

GY-NEO6MV2per un costo di circa una decina di euro si puo' acquistare il ricevitore GY-NEO6MV2.

Si tratta di un semplice dispositivo con 4 connessioni (VCC 2.7-5V, GND, TX ed RX). Non e' di fatto programmabile ed il modulo trasmette dati sulla seriale (9600, 8N1) in formato NMEA ad 1Hz


Per l'uso con Arduino si puo' usare la libreria TinyGPS

Avendo un cavo FTDI si puo' collegare direttamente il dispositivo al PC leggendo i dati NMEA direttamente in un emulatore di terminale





Adafruit GPS Breakout

Ad un costo di circa 4 volte superiore (40 euro) si puo' trovare il modulo GPS Breakout di Adafruit che risulta essere di un'altra classe rispetto a GY-NEO6MV2.



E' disponibile un piedino per accendere o spengere il dispositivo, e' abilitata la ricezione dei segnali SBAS/EGNOS per il posizionamento DPGS, e' possibile variare il tipo di sentenze ricevute e la velocita' con cui vengono generate (da 100 milliHz a 10 Hz) e la velocita' della seriale.

Per l'uso con Arduino si puo' usare la libreria Adafruit-GPS-Library in cui sono contenuti vari esempi

C'e' da notare un bug nel firmware. Caricando lo sketch echo (che rimanda sulla seriale le stringhe NMEA del dispositivo) compaiono dei caratteri anomali
$PGTOP,11,2*6E
$PGTOP,11,2*6E
questi sono codici di programmazione del modulo MTK3339 e non dovrebbero essere presenti nel flusso NMEA (peraltro non c'e' modo di sopprimerli, si possono eliminare solo in postprocessing)

Il modulo viene riportato per avere una assorbimento di 20 mA in modalita' operativa e dalle mie prove tale valore risulta conforme al teorico

Di seguito il codice Arduino da poter usare con Gps Adafruit con impostata la richiesta della modalita' DPGS

----------------------------------------------------------------------
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>

unsigned long delaytime=250;


SoftwareSerial mySerial(3, 2);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  true
boolean usingInterrupt = false;
void useInterrupt(boolean);



void setup() {

  Serial.begin(9600);
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);
  //enable DPGS
  GPS.sendCommand(PMTK_ENABLE_SBAS);
  GPS.sendCommand(PMTK_ENABLE_WAAS);

  useInterrupt(true);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
#ifdef UDR0
  //if (GPSECHO)
    //if (c) UDR0 = c;
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();



void loop() {
  if (! usingInterrupt) {
    char c = GPS.read();
    //if (GPSECHO)
      //if (c) Serial.print(c);
  }
  if (GPS.newNMEAreceived()) {
    if (!GPS.parse(GPS.lastNMEA()))
      return;
  }

  if (timer > millis())  timer = millis();

  if (millis() - timer > 1000) {
    timer = millis(); // reset the timer
    //NOME DELLA STAZIONE
    Serial.print("ST01-");
      
    //GPS
    Serial.print(GPS.hour,DEC);
    Serial.print(":");
    Serial.print(GPS.minute,DEC);
    Serial.print(":");
    Serial.print(GPS.seconds,DEC);
    //Serial.print(".");
    //Serial.print(GPS.milliseconds,DEC);
    Serial.print(" ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.print(GPS.year, DEC);
if (GPS.fix)
    {
    Serial.print("-");
    Serial.print(GPS.latitude,4);
    Serial.print("-");
    Serial.print(GPS.lat);
    Serial.print("-");
    Serial.print(GPS.longitude,4);
    Serial.print("-");
    Serial.print(GPS.lon);
    Serial.print("-");
    Serial.print(GPS.HDOP,4);
    Serial.print("-");
    Serial.print((int)GPS.fixquality);

    Serial.print("-");
    Serial.print((int)GPS.satellites);
    }
    Serial.println();
  }
}

-------------------------------------------
Il modulo puo' essere messo in stato di ibernazione con i comandi
GPS.standby()
GPS.wakeup()

Una Arduino Uno con il modulo GPS attivo consuma circa 20 mA mentre la stessa configurazione con il GPS in ibernazione scende al di sotto dei 10 mA
Ovviamente dopo aver riacceso il modulo, il sistema deve effettuare da zero il Fix GPS (e' quindi consigliabile inserire la batteria tampone per le effemeridi)