Objetivos
Arduino UNO | |
GPS Shield |
Usando el data logger y la tarjeta SD
Ahora que sabemos usar el shield para obtener los datos del GPS, vamos a centrarnos en otras características que nos ofrece. Concretamente en la capacidad para grabar los datos en una tarjeta SD. Y como extra vamos a calcular la distancia desde nos encontramos al lugar que le indiquemos.
Lo primero que tenemos que hacer es incluir las librerías y declarar las variables e instancias que vamos a usar después. La mayoría se repiten del ejemplo anterior, y las que no lo hacen, son las que necesitamos para usar el data logger y la tarjeta SD.
Para poder usar el data logger tenemos que declarar una variable para indicar el chip que estamos usando. No os voy a engañar, cuando lo intentamos no conseguimos encontrar información concreta de cuál es, pero un poco de prueba y error nos dio la solución, es el chip 8. A parte de eso, tenemos que dar nombre al archivo que usaremos para guardar los datos en la tarjeta, con la extensión .CSV.
#include <TinyGPS++.h> #include <SoftwareSerial.h> #include <SD.h> const int chipSelect = 8; static const int RXPin = 2, TXPin = 3; static const uint32_t GPSBaud = 9600; File dataFile; char filename[] = "LOGGER00.CSV"; // The TinyGPS++ object TinyGPSPlus gps; // The serial connection to the GPS device SoftwareSerial ss(RXPin, TXPin); // For stats that happen every 5 seconds unsigned long last = 0UL;
En el setup tenemos que inicializar el GPS y la SD. Al hacerlo creamos un nuevo archivo en la SD y le damos un nombre con números correlativos, para no borrar siempre el archivo anterior cuando vayamos a grabar uno nuevo.
Si hemos conseguido abrir la SD y grabar el archivo correctamente, escribimos las cabeceras de los campos que queremos mostrar y las mostramos también en el monitor serie: latitud, longitud, altitud, velocidad, fecha, hora y distancia al objetivo que le marquemos.
void setup() { Serial.begin(9600); ss.begin(GPSBaud); Serial.print(F("Initializing SD card. ")); // make sure that the default chip select pin is set to // output, even if you don't use it: pinMode(chipSelect, OUTPUT); // see if the card is present and can be initialized: if (!SD.begin(chipSelect)) { Serial.println(F("Card failed.")); // don't do anything more: return; } Serial.println(F("Card initialized.")); // create a new file with a new filenumber for (uint8_t i = 0; i < 100; i++) { filename[6] = i/10 + '0'; filename[7] = i%10 + '0'; if (! SD.exists(filename)) { // only open a new file if it doesn't exist dataFile = SD.open(filename, FILE_WRITE); break; // leave the loop } dataFile.close(); } if (! dataFile) { Serial.println("couldnt create file"); } Serial.print("Logging to: "); Serial.println(filename); Serial.println(""); //_________________________Write Log File Header__________________________________________________ File dataFile = SD.open(filename, FILE_WRITE); if (dataFile) { dataFile.print(F("Latitud")); dataFile.print(","); dataFile.print(F("Altitud")); dataFile.print(","); dataFile.print(F("Velocidad")); dataFile.print(","); dataFile.print(F("Fecha")); dataFile.print(","); dataFile.print(F("Hora")); dataFile.print(","); dataFile.println(F("Distancia al objetivo")); dataFile.close(); } Serial.print(F("Latitud")); Serial.print(","); Serial.print(F("Longitud")); Serial.print(","); Serial.print(F("Velocidad")); Serial.print(","); Serial.print(F("Fecha")); Serial.print(","); Serial.print(F("Hora")); Serial.print(","); Serial.println(F("Distancia al objetivo")); }
Y ya en el loop obtenemos los datos del GPS y los vamos escribiendo en la SD. Una vez tengamos nuestra posición, le indicamos la posición objetivo y calculamos la distancia a la misma. Hemos puesto como objetivo las coordenadas de Madrid.
{ // Dispatch incoming characters while (ss.available() > 0) gps.encode(ss.read()); if (gps.location.isUpdated()) { Serial.print(gps.location.lat(), 6); Serial.print(F(",")); Serial.print(gps.location.lng(), 6); Serial.print(F(",")); File dataFile = SD.open(filename, FILE_WRITE); dataFile.print(gps.location.lat(), 6); dataFile.print(F(",")); dataFile.print(gps.location.lng(), 6); dataFile.print(F(",")); dataFile.close(); } else if (gps.speed.isUpdated()) { Serial.print(gps.speed.kmph()); Serial.print(F(",")); File dataFile = SD.open(filename, FILE_WRITE); dataFile.print(gps.speed.kmph()); dataFile.print(F(",")); dataFile.close(); } else if (gps.date.isUpdated()) { Serial.print(gps.date.day()); Serial.print(F("/")); Serial.print(gps.date.month()); Serial.print(F("/")); Serial.print(gps.date.year()); Serial.print(F(",")); File dataFile = SD.open(filename, FILE_WRITE); if (gps.date.day()<10){ // Add a zero, if necessary, as above dataFile.print(0); } dataFile.print(gps.date.day()); dataFile.print(F(".")); if (gps.date.month()<10){ // Add a zero, if necessary, as above dataFile.print(0); } dataFile.print(gps.date.month()); dataFile.print(F(".")); dataFile.print(gps.date.year()); dataFile.print(F(",")); dataFile.close(); } else if (gps.time.isUpdated()) { Serial.print(gps.time.hour()); Serial.print(F(":")); Serial.print(gps.time.minute()); Serial.print(F(":")); Serial.print(gps.time.second()); Serial.print(F(",")); File dataFile = SD.open(filename, FILE_WRITE); if (gps.time.hour()<10){ // Add a zero, if necessary, as above dataFile.print(0); } dataFile.print(gps.time.hour()); dataFile.print(F(":")); if (gps.time.minute()<10){ // Add a zero, if necessary, as above dataFile.print(0); } dataFile.print(gps.time.minute()); dataFile.print(F(":")); if (gps.time.second()<10){ // Add a zero, if necessary, as above dataFile.print(0); } dataFile.print(gps.time.second()); dataFile.print(F(",")); dataFile.close(); } else if (millis() - last > 1000) { // Serial.println(); if (gps.location.isValid()) { static const double MADRID_LAT = 40.4893538, MADRID_LON = -3.6827461; //custom location double distanceToMadrid = TinyGPSPlus::distanceBetween( gps.location.lat(), gps.location.lng(), MADRID_LAT, MADRID_LON); double courseToLondon = TinyGPSPlus::courseTo( gps.location.lat(), gps.location.lng(), MADRID_LAT, MADRID_LON); File dataFile = SD.open(filename, FILE_WRITE); dataFile.println(distanceToMadrid/1000, 6); dataFile.close(); Serial.println(distanceToMadrid/1000, 6); } last = millis(); } }
Aquí os dejamos el programa completo:
Si abrimos el monitor serie podemos ver como funciona el GPS. Primero veremos si es capaz de acceder a la tarjeta y el nombre del archivo que va a crear. A partir de ahí nos irá dando los datos que hemos obtenido del GPS.
Podéis meter los datos que hemos obtenido en el localizador de coordenadas de Google para ver si funciona correctamente. En nuestro caso la precisión ha sido altísima:
Utilizando los datos de la tarjeta SD
Para probar el GPS en condiciones vamos a soltarlo del ordenador, colocarle una power bank (las baterías que se suelen usar para cargar los móviles) y vamos a salir a dar una vuelta, a ver si todo funciona en condiciones.
Bueno, ya estamos de vuelta… Así que ahora vamos a sacar la tarjeta SD del shield a conectarla a nuestro PC. Si la abrís podréis ver los diferentes archivos que hemos ido guardando.
Ahora abrimos una hoja nueva de Excel donde vamos a importar los datos que hemos guardado. Para ello vamos a «Datos»->»Obtener datos externos»->»Desde texto»
Entonces os preguntará como son los campos. Le decimos que están delimitados. Y en la siguiente ventana le decimos que están delimitados por Comas.
Entonces se os abrirá una hoja excel, con las cabeceras que hemos creado y todos los datos que hemos ido guardando. Probablemente tendréis que borrar la primera línea, que es lo que ha ido guardando hasta que ha obtenido la localización GPS.
Ahora podéis utilizar estos datos con alguna de las aplicaciones que hay para dibujar el recorrido en un mapa usando Google Maps, o para lo que se os ocurra. Pero eso os lo dejamos para vosotros.
Resumen de la sesión
En esta sesión hemos aprendido varias cosas importantes: