Problema utilizando el GPS de SparkFun y Arduino Mega

Buenas.

Llevo un par de días trabajando con Arduino Mega y el GPS Logger Shield de Sparkfun. He intentado seguir la guía del GPS (no paso la url porque no sé si puedo ponerla aquí o no), y no consigo que me funcione.
Debido a que uso Arduino Mega, tengo que conectar de forma manual los pines GPS-TX y GPS-RX a los pines A8 y A9 del arduino (en realidad pueden ser otros dos, pero yo he elegido estos). Cuando conecto los pines 5V, 3.3V y GND a la placa arduino, así como los pines A8 y A9, al ejecutar el código sólo obtengo 0. Es decir, obtengo Latitud 0, Longitud 0, etc. Creo que el problema está en el código, así que si alguien tiene alguna idea de que puede estar sucediendo agradecería si me lo explicara.

El código que utilizo es el siguiente:

#include <TinyGPS++.h>
TinyGPSPlus tinyGPS;

#include <SoftwareSerial.h>
#define ARDUINO_GPS_RX A9 // GPS TX, Arduino RX pin
#define ARDUINO_GPS_TX A8 // GPS RX, Arduino TX pin
SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX); // Create a SoftwareSerial

#define gpsPort ssGPS 
#define SerialMonitor Serial

#define GPS_BAUD 9600 

void setup()
{
  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);
}

void loop()
{
  printGPSInfo();

  delay(1000);
}

void printGPSInfo()
{
  SerialMonitor.print("Lat: "); SerialMonitor.println(tinyGPS.location.lat(), 6);
  SerialMonitor.print("Long: "); SerialMonitor.println(tinyGPS.location.lng(), 6);
  SerialMonitor.print("Alt: "); SerialMonitor.println(tinyGPS.altitude.feet());
  SerialMonitor.print("Course: "); SerialMonitor.println(tinyGPS.course.deg());
  SerialMonitor.print("Speed: "); SerialMonitor.println(tinyGPS.speed.mph());
  SerialMonitor.print("Date: "); printDate();
  SerialMonitor.print("Time: "); printTime();
  SerialMonitor.print("Sats: "); SerialMonitor.println(tinyGPS.satellites.value());
  SerialMonitor.println();
}

// printDate() formats the date into dd/mm/yy.
void printDate()
{
  SerialMonitor.print(tinyGPS.date.day());
  SerialMonitor.print("/");
  SerialMonitor.print(tinyGPS.date.month());
  SerialMonitor.print("/");
  SerialMonitor.println(tinyGPS.date.year());
}

// printTime() formats the time into "hh:mm:ss", and prints leading 0's
// where they're called for.
void printTime()
{
  SerialMonitor.print(tinyGPS.time.hour());
  SerialMonitor.print(":");
  if (tinyGPS.time.minute() < 10) SerialMonitor.print('0');
  SerialMonitor.print(tinyGPS.time.minute());
  SerialMonitor.print(":");
  if (tinyGPS.time.second() < 10) SerialMonitor.print('0');
  SerialMonitor.println(tinyGPS.time.second());
}

Bienvenido. En primer lugar debes editar tu mensaje y poner el código entre las etiquetas code. Si tienes dudas lee las normas del foro en el primer mensaje de este foro.

SoftwareSerial debe trabajar con 2 pines digitales no analogicos. Cambialos.

Buenas. En primer lugar, pido disculpas por lo del código, ya he editado el mensaje.

Gracias por responder. He probado a cambiar a dos pines digitales: para TX he usado el 14 y para RX el 15. Sigo teniendo el mismo problema: sólo recibo valores 0.
Me he fijado en que las señales TX y RX en los pines 14 y 15 se llaman "TX3" y "RX3". No sé si esto afecta en algo al código, porque he visto por internet que en algunos sitios llaman algo así como:

#define SerialMonitor Serial1

Y no sé si ese 1 es por el número que tiene asociado el TX. El caso es que he probado a utilizarlo con Serial3, pero entonces no se escribe nada por el puerto serie.

La verdad es que soy bastante novato en esto, así que no tengo ni idea de que puede estar fallando. El código que estoy utilizando es el original del primer post, pero modificando lo del TX y RX para los pines 14 y 15.

Saludos y gracias.

SoftwareSerial debe trabajar con 2 pines digitales no analogicos. Cambialos.

SoftwareSerial puede trabajar con dos pines analogicos cuando se configuran como digitales. No hay restriccion Kike.

A0...A5 para un UNO pueden usarse como SoftwareSerial. Sino que pasaría con A4 y A5 y los dispositivos I2C? obvio que son I2C hardware pero.. se entiende la idea no?

Ahora en un MEGA usar SoftwareSerial me parece una DESPROPOSITO y lo pongo en MAYUSCULAS una vez mas.

4 puertos hardware tiene.. el 0 usado por el monitor serie o disponible para lo que gustes pero quedan Serial1, 2 y 3, y aún asi buscan un SoftwareSerial?

Hay que ver que hardware se tiene antes de copiar y pegar sin analizar como son las cosas.

Releyendo todo el hilo ahora veo el problema.

TyniGPS es una LIbrería vieja que no se ha adaptado a los cambios y no contempla el uso de otros puertos.
Asi que para TinyGps solo hay un UNO posible como lector de un GPS, por eso busca un SoftwareSErial.

Para un MEGA hay que cambiar cosas

  Serial1.begin(GPSBaud);

Esto define el puerto que usarás

Luego hay que cambiar como le envias datos al GPS

// Esta modificación de delay() asegura que el objeto gps funcione bien

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do  {
    while (Serial1.available())
      gps.encode(Serial1.read());
  } while (millis() - start < ms);
}

Gracias surbyte por responder. La verdad es que llevo muy poco tiempo usando Arduino y soy bastante novato en estos temas, por lo que no tenía ni idea de los SofwareSerial y puertos hardware. He probado a añadir lo que comentabas, tanto el smartDelay como el Serial1.begin, y sigo recibiendo 0. Dejo aquí el código que estoy utilizando, por si hay algo más que tengo que cambiar y no lo sé. He probado a cambiar varios Serial y demás pero no consigo que funcione. Ah, y también he vuelto a utilizar los pines A8 y A9:

//Librerías
#include <SoftwareSerial.h>
#include <TinyGPS++.h>

//Definicion pines GPS
#define ARDUINO_GPS_RX A9
#define ARDUINO_GPS_TX A8
#define GPS_BAUD 9600
#define SerialMonitor Serial;

SoftwareSerial gpsPort(ARDUINO_GPS_TX, ARDUINO_GPS_RX);
TinyGPSPlus tinyGPS;

void setup() {
//Inicialización GPS
  gpsPort.begin(GPS_BAUD);
  Serial.begin(GPS_BAUD);
  Serial1.begin(GPS_BAUD);
}

void loop() {

 /*Serial.print("Lat: "); Serial.println(tinyGPS.location.lat(), 6);
  */
  
  printGPSInfo();
  smartDelay(1000);
}

void printGPSInfo()
{
  // Print latitude, longitude, altitude in feet, course, speed, date, time,
  // and the number of visible satellites.
  Serial.print("Lat: "); Serial.println(tinyGPS.location.lat(), 6);
  Serial.print("Long: "); Serial.println(tinyGPS.location.lng(), 6);
  Serial.print("Alt: "); Serial.println(tinyGPS.altitude.feet());
  Serial.print("Course: "); Serial.println(tinyGPS.course.deg());
  Serial.print("Speed: "); Serial.println(tinyGPS.speed.mph());
  Serial.print("Date: "); printDate();
  Serial.print("Time: "); printTime();
  Serial.print("Sats: "); Serial.println(tinyGPS.satellites.value());
  Serial.println();
}

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    // If data has come in from the GPS module
    while (Serial1.available())
      tinyGPS.encode(Serial1.read()); // Send it to the encode function
    // tinyGPS.encode(char) continues to "load" the tinGPS object with new
    // data coming in from the GPS module. As full NMEA strings begin to come in
    // the tinyGPS library will be able to start parsing them for pertinent info
  } while (millis() - start < ms);
}



// printDate() formats the date into dd/mm/yy.
void printDate()
{
  Serial.print(tinyGPS.date.day());
  Serial.print("/");
  Serial.print(tinyGPS.date.month());
  Serial.print("/");
  Serial.println(tinyGPS.date.year());
}

// printTime() formats the time into "hh:mm:ss", and prints leading 0's
// where they're called for.
void printTime()
{
  Serial.print(tinyGPS.time.hour());
  Serial.print(":");
  if (tinyGPS.time.minute() < 10) //Por ejemplo, 13:07
    Serial.print('0'); //Escribe 0
  Serial.print(tinyGPS.time.minute()); //Escribe 7
  Serial.print(":");
  if (tinyGPS.time.second() < 10) 
    Serial.print('0');
  Serial.println(tinyGPS.time.second());
}

Buenas otra vez.

He probado a utilizar un Arduino Uno y el programa funciona correctamente si cambio los pines RX y TX a 8 y 9 respectivamente. Por lo que entiendo que el problema es que los pines que selecciono como TX y RX en el arduino Mega no son los correctos.

Navegando por la ayuda de Arduino, he llegado al siguiente enlace:

Donde se indica que el pin RX puede estar sólo en un determinado número de pines. En mi caso he utilizado ya unos cuantos: 10, A9, A8, y unos cuantos más y sigue sin funcionar. ¿Alguna idea?

Cual es el problema? SoftwareSerial en MEGA? Ya te respondi.

Pues ya lo he solucionado, he ido probando con lo que me has dicho y al final he conseguido que funcione. Era cuestión de utilizar los pins del SoftwareSerial. Muchas gracias por resolverlo :slight_smile:

Veo que sigues sin entender! pero bueno si lo resolviste, a otra cosa.

Pero ahora te hago una consulta?

Vienes al foro y pides ayuda. dices Lo resolví pero no pones cómo?
Entonces nosotros debemos ayudarte pero tu no ayudas a los demás? Seguramente se te pasó por alto pero recuerda... que es tu obligación informar como lo hiciste.

Yo se como usar SoftwareSerial y para mi la respuesta es la que te indiqué, usando Serial1 pero veamos como lo has hecho tu, seguramente usando algunos pines que no esten comprometidos con los puertos Serie.

surbyte:
Veo que sigues sin entender! pero bueno si lo resolviste, a otra cosa.

Pero ahora te hago una consulta?

Vienes al foro y pides ayuda. dices Lo resolví pero no pones cómo?
Entonces nosotros debemos ayudarte pero tu no ayudas a los demás? Seguramente se te pasó por alto pero recuerda... que es tu obligación informar como lo hiciste.

Yo se como usar SoftwareSerial y para mi la respuesta es la que te indiqué, usando Serial1 pero veamos como lo has hecho tu, seguramente usando algunos pines que no esten comprometidos con los puertos Serie.

Ya comenté en mi post anterior cómo lo hice: "Era cuestión de utilizar los pins del SoftwareSerial.". No he utilizado Serial1 al final, simplemente he ido cambiando el código hasta que me ha funcionado, y creo que el problema era que los pines no estaban bien utilizados (físicamente hablando). Vamos, que no conectaba los pines correctos.
De todas formas, dejo por aquí el código que he utilizado al final, por si alguien también tiene problemas con el arduino Mega y el GPS:

#include <TinyGPS++.h>
TinyGPSPlus gps;

static const int RXPin = A8;
static const int TXPin= A9;
static const int GPSBaud = 9600;

#include <SoftwareSerial.h>
SoftwareSerial ss(RXPin, TXPin);

int h; // Para corregir la diferencia horaria

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

void loop()
{
  Serial.print("Latitud: ");  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6); Serial.println(); // Latitud
  Serial.print("Longitud: "); printFloat(gps.location.lng(), gps.location.isValid(), 12, 6); Serial.println();// Longitud
  Serial.print("Altura: "); printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2); Serial.println();// Altura
  Serial.print("Orientación: "); printFloat(gps.course.deg(), gps.course.isValid(), 7, 2); Serial.println();// Orientación from GPS
  Serial.print("Speed: "); printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2); Serial.println();// Velocidad from GPS
  Serial.print("Date: "); printDate();
  Serial.print("Time: "); printTime();
  Serial.print("Sats: "); Serial.println(gps.satellites.value());
  Serial.println();

  // "Smart delay" busca datos para el GPS mientras Arduino no hace nada
  smartDelay(1000); 
}

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read()); 
  } while (millis() - start < ms);
}

// Fecha en formato dd/mm/yy.
void printDate()
{
  Serial.print(gps.date.day());
  Serial.print("/");
  Serial.print(gps.date.month());
  Serial.print("/");
  Serial.println(gps.date.year());
}

// Hora eno formato "hh:mm:ss"
void printTime()
{
  h=gps.time.hour();
  h=h+2;
  Serial.print(h);
  Serial.print(":");
  if (gps.time.minute() < 10) Serial.print('0');
  Serial.print(gps.time.minute());
  Serial.print(":");
  if (gps.time.second() < 10) Serial.print('0');
  Serial.println(gps.time.second());
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

Listo ahora si, hilo cerrado.