lunedì 31 agosto 2015

Arduino GPS Clock

Un bel po' di tempo fa esistevano degli orologi che si sincronizzano via segnale radio (che se non erro era emesso una volta l'ora da una trasmittente in Germania) ed aggiornavano l'eventuale errore dell'orologio interno

Oggi ho provato a crearmi il mio orologio di precisione sincronizzato con il sistema GPS.



Per fare cio' ho preso
1) Arduino Nano
2) Modulo GPS Breakout v3 (modulo costoso, circa 20 euro, ma si trova qualcosa di simile a meta' prezzo)
3) Modulo di 8 Digit a 7 barre comandato da MAX 7219




I collegamenti sono semplici
Il GPS puo' essere collegato sia al 5V che al 3V3. Per lasciare spazio al display e' stato connesso al 3V3. GND ovviamente a GND ed infine GPS/RX a D2 e GPS/TX a D3

Il display e' stato quindi collegato a 5V, GND, LOAD/CS a D5, CLK a D6 e DIN a D7

per il funzionamento dello sketch devono essere installate le librerie ADAFRUIT GPS Library e  LedControl




Sono necessari circa 15 secondi da un cold start per ottenere i dati relativi all'ora dal dato GPS.
Inserendo la batteria tampone sul modulo GPS questo tempo e' ridotto a poche frazioni di secondo

---------------------------------------------------------------------------------
#include "LedControl.h"

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

LedControl lc=LedControl(7,6,5,1);
unsigned long delaytime=250;


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



void setup() {
  lc.shutdown(0,false);
  lc.setIntensity(0,8);
  lc.clearDisplay(0);
  
  Serial.begin(115200);
  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);
  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();

int decina;
int unita;
int ora;
int minuti;
int secondi;

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 > 500) { 
    timer = millis(); // reset the timer
    
    ora = GPS.hour;
    minuti = GPS.minute;
    secondi = GPS.seconds;

// mostra ore 
    decina = (ora/10);
    unita = (ora%10);
    
    if (int(decina)==0) {
         lc.setChar(0,0,'0',false);
         }
         else {
         lc.setDigit(0,0,(byte)decina,false);
       }
    lc.setDigit(0,1,(byte)unita,false);



// mostra minuti 
    decina = (minuti/10);
    unita = (minuti%10);
    
    if (int(decina)==0) {
         lc.setChar(0,3,'0',false);
         }
         else {
         lc.setDigit(0,3,(byte)decina,false);
       }
    lc.setDigit(0,4,(byte)unita,false);

    
// mostra secondi
    decina = (secondi/10);
    unita = (secondi%10);
    
    if (int(decina)==0) {
         lc.setChar(0,6,'0',false);
         }
         else {
         lc.setDigit(0,6,(byte)decina,false);
       }
    lc.setDigit(0,7,(byte)unita,false);
  }
}