GPS.encode always return false

Hello :slight_smile: ,
i'm new to this so hope i can explain it well. I'm trying to get latitude and longitude value from neo-m8n gps module from ublox using arduino uno. I use code form tinyGPS example, here the code :

#include <SoftwareSerial.h>

#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(10, 11);

void setup()
{
  Serial.begin(115200);
  ss.begin(9600);
  
  Serial.print("Simple TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
}

void loop()
{
  bool newData = false;
  unsigned long chars;
  unsigned short sentences, failed;

  // For one second we parse GPS data and report some key values
  for (unsigned long start = millis(); millis() - start < 1000;)
  {
    while (ss.available())
    {
      char c = ss.read();
      //Serial.write(c); // uncomment this line if you want to see the GPS data flowing
      if (gps.encode(c)) // Did a new valid sentence come in?
        newData = true;
    }
  }

  if (newData)
  {
    float flat, flon;
    unsigned long age;
    gps.f_get_position(&flat, &flon, &age);
    Serial.print("LAT=");
    Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
    Serial.print(" LON=");
    Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
    Serial.print(" SAT=");
    Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
    Serial.print(" PREC=");
    Serial.print(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
 
  }
 
  gps.stats(&chars, &sentences, &failed);
  Serial.print(" CHARS=");
  Serial.print(chars);
  Serial.print(" SENTENCES=");
  Serial.print(sentences);
  Serial.print(" CSUM ERR=");
  Serial.println(failed);
  if (chars == 0)
    Serial.println("** No characters received from GPS: check wiring **");
}

but GPS.encode(c) always return false, i already check it indoor and outdoor and still get the same result. For the baud rate value i get it from the datasheet of m8n. The attachment below is the output of the code (gps.png) and the raw data from my gps (raw-data.png)

So i'm stuck here and dont know what else to do
thanks

      //Serial.write(c); // uncomment this line if you want to see the GPS data flowing

So, why didn't you?

PaulS:

      //Serial.write(c); // uncomment this line if you want to see the GPS data flowing

So, why didn't you?

Thanks for the reply, i already tried to uncomment those line and see the gps raw data, but even so the gps.encode() still return false

the raw data is in the attachments in my first post

The raw data looks good to me. However, TinyGPS is out-of-data. You should be using TinyGPS++.

http://arduiniana.org/libraries/tinygpsplus/

fiersome:
So i'm stuck here and dont know what else to do
thanks

For me it is very likely that your problem is caused by using SoftwareSerial and HardwareSerial at the same time.

Solution is simple: Use an Arduino board which provides MORE than one Serial!
Arduino MEGA2560 has 4 hardware serial ports (Serial, Serial1, Serial2, Serial3

Connect the USB cable to the PC and you can send output to the serial monitor by printing to Serial
Connect the GPS module to one of the additional hardware Serials like "Serial1" perhaps.

Then read the GPS data from Serial1 and send output to Serial.

Using two hardware serial ports at the same time is no problem.
Using one hardware serial port and one software serial causes conflicts when baudrate is more than 4800 baud (as far as I have tested this combination).
So better use a board which provides at least two serial ports on-board to avoid problems with corrupted data.

Other solution: Try to use the altSoftSerial library as a software emulated serial port instead of softwareSerial. AltSoftSerial is the much better serial port emulation library!
But it is not included in the IDE distribution, you have to download and install it as an additional third-party library.
And with altSoftSerial you are NOT free in choice of pins for RX/TX emulation:
Pins with altSoftSerialserial are fixed and depend on the Arduino board you use:
With "UNO" boards the transmit-pin is 9 and the RX pin is 8 when using altSoftSerial and pin-10 becomses unusable for PWM.

PaulS:
The raw data looks good to me. However, TinyGPS is out-of-data. You should be using TinyGPS++.

TinyGPS++ | Arduiniana

thanks, sorry for the late reply, i download tinyGPSPlus and used the fullExample sketch, here is the code :

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
/*
   This sample code demonstrates the normal use of a TinyGPS++ (TinyGPSPlus) object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 4(rx) and 3(tx).
*/
static const int RXPin = 10, TXPin = 11;
static const uint32_t GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

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

  Serial.println(F("FullExample.ino"));
  Serial.println(F("An extensive example of many interesting TinyGPS++ features"));
  Serial.print(F("Testing TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
  Serial.println(F("Sats HDOP Latitude   Longitude   Fix  Date       Time     Date Alt    Course Speed Card  Distance Course Card  Chars Sentences Checksum"));
  Serial.println(F("          (deg)      (deg)       Age                      Age  (m)    --- from GPS ----  ---- to London  ----  RX    RX        Fail"));
  Serial.println(F("---------------------------------------------------------------------------------------------------------------------------------------"));
}

void loop()
{
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;

  printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  printInt(gps.hdop.value(), gps.hdop.isValid(), 5);
  printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  printInt(gps.location.age(), gps.location.isValid(), 5);
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.value()) : "*** ", 6);

  unsigned long distanceKmToLondon =
    (unsigned long)TinyGPSPlus::distanceBetween(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON) / 1000;
  printInt(distanceKmToLondon, gps.location.isValid(), 9);

  double courseToLondon =
    TinyGPSPlus::courseTo(
      gps.location.lat(),
      gps.location.lng(),
      LONDON_LAT, 
      LONDON_LON);

  printFloat(courseToLondon, gps.location.isValid(), 7, 2);

  const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);

  printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);

  printInt(gps.charsProcessed(), true, 6);
  printInt(gps.sentencesWithFix(), true, 10);
  printInt(gps.failedChecksum(), true, 9);
  Serial.println();
  
  smartDelay(1000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

// This custom version of delay() ensures that the gps object
// is being "fed".
void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

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);
}

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);
}

void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

the output is in the attachment below. The value always have the value of *, except the charRx

jurs:
For me it is very likely that your problem is caused by using SoftwareSerial and HardwareSerial at the same time.

Solution is simple: Use an Arduino board which provides MORE than one Serial!
Arduino MEGA2560 has 4 hardware serial ports (Serial, Serial1, Serial2, Serial3

Connect the USB cable to the PC and you can send output to the serial monitor by printing to Serial
Connect the GPS module to one of the additional hardware Serials like "Serial1" perhaps.

Then read the GPS data from Serial1 and send output to Serial.

Using two hardware serial ports at the same time is no problem.
Using one hardware serial port and one software serial causes conflicts when baudrate is more than 4800 baud (as far as I have tested this combination).
So better use a board which provides at least two serial ports on-board to avoid problems with corrupted data.

Other solution: Try to use the altSoftSerial library as a software emulated serial port instead of softwareSerial. AltSoftSerial is the much better serial port emulation library!
But it is not included in the IDE distribution, you have to download and install it as an additional third-party library.
And with altSoftSerial you are NOT free in choice of pins for RX/TX emulation:
Pins with altSoftSerialserial are fixed and depend on the Arduino board you use:
With "UNO" boards the transmit-pin is 9 and the RX pin is 8 when using altSoftSerial and pin-10 becomses unusable for PWM.

Thanks for the reply, can't get mega right now so i tried your suggestion using altSoftSerial. Using tinyGPS++ fullExample, the output is the same as when i used SoftwareSerial, every value end up being *.

The attachment below (output3.png) is the raw data of the gps, i think its because i used it indoor, will try it outdoor tomorrow

jurs:
For me it is very likely that your problem is caused by using SoftwareSerial and HardwareSerial at the same time.

Solution is simple: Use an Arduino board which provides MORE than one Serial!
Arduino MEGA2560 has 4 hardware serial ports (Serial, Serial1, Serial2, Serial3

Connect the USB cable to the PC and you can send output to the serial monitor by printing to Serial
Connect the GPS module to one of the additional hardware Serials like "Serial1" perhaps.

Then read the GPS data from Serial1 and send output to Serial.

Using two hardware serial ports at the same time is no problem.
Using one hardware serial port and one software serial causes conflicts when baudrate is more than 4800 baud (as far as I have tested this combination).
So better use a board which provides at least two serial ports on-board to avoid problems with corrupted data.

Other solution: Try to use the altSoftSerial library as a software emulated serial port instead of softwareSerial. AltSoftSerial is the much better serial port emulation library!
But it is not included in the IDE distribution, you have to download and install it as an additional third-party library.
And with altSoftSerial you are NOT free in choice of pins for RX/TX emulation:
Pins with altSoftSerialserial are fixed and depend on the Arduino board you use:
With "UNO" boards the transmit-pin is 9 and the RX pin is 8 when using altSoftSerial and pin-10 becomses unusable for PWM.

Thanks for the reply, can't get mega right now so i tried your suggestion using altSoftSerial. Using tinyGPS++ fullExample, the output is the same as when i used SoftwareSerial, every value end up being *.

The attachment below is the raw data of the gps, i think its because i used it indoor, will try it outdoor tomorrow

Looks like the GPS library you are using is not recognizing any of the sentences ("SENTENCES=0"). It looks like your GPS is using the $GN prefix instead of the more common $GP for many of the sentences. You may have to tweak the GPS library to understand that prefix.

The raw data looks good to me. However, TinyGPS is out-of-data. You should be using TinyGPS++.

TinyGPS++ won't parse that data, either. TinyGPS++ is also out-of-date.

Looks like the GPS library you are using is not recognizing any of the sentences ("SENTENCES=0"). It looks like your GPS is using the $GN prefix

Yes, the Neo-M8N uses different talker IDs. I wrote NeoGPS to be smaller, faster and more robust than other libraries. It will handle different talker IDs, ublox-specific sentences and the UBX binary protocol, if you want to go that direction. The examples are properly structured, and can be modified without breaking (usually :wink: ).

Regarding the software serial port, if you can put the GPS on pins 8 & 9, the AltSoftSerial library is much, much better than SoftwareSerial. Next best is a library I maintain, NeoSWSerial. It will work on any two pins. Absolute last choice is SoftwareSerial, because it blocks interrupts for long periods of time. That can interfere with other parts of your sketch.

Cheers,
/dev

/dev:
TinyGPS++ won't parse that data, either. TinyGPS++ is also out-of-date.
Yes, the Neo-M8N uses different talker IDs. I wrote NeoGPS to be smaller, faster and more robust than other libraries. It will handle different talker IDs, ublox-specific sentences and the UBX binary protocol, if you want to go that direction. The examples are properly structured, and can be modified without breaking (usually :wink: ).

Regarding the software serial port, if you can put the GPS on pins 8 & 9, the AltSoftSerial library is much, much better than SoftwareSerial. Next best is a library I maintain, NeoSWSerial. It will work on any two pins. Absolute last choice is SoftwareSerial, because it blocks interrupts for long periods of time. That can interfere with other parts of your sketch.

Cheers,
/dev

I tried to read the data with your library and wow it works perfectly, thanks for your reply ;D