No coordinates from gps

Hello,
i have a ublox-M8N + compass (HMC5883) module connected to an arduino uno and i use the tinygps++ library to parse the incoming NMEA sentences. The problem is that i never receive coordinates. I took it out to my balcony and to my yard, both with clear view to the sky but nothing. Even though the LED on the gps module started blinking, i didn't receive coordinates. Anyone knows why?

Normally i transmit the coordinates to a receiver connected to my laptop but i cut this part of the code as it is unnecessary

// Arduino Uno
// ---------------
/*
   This sketch parses the incoming data from the gps to the arduino
   GPS device hooked up on pins 2(rx) and 3(tx) and a HMC5883 Magnetic
   Compass connected to the SCL/SDA pins.
*/

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
#include <stdlib.h>

static const int RXPin1 = 2, TXPin1 = 3, RPin1 = 4, RPin2 = 6;
static const uint32_t GPSBaud = 9600;
static double lat = 0.0,lon = 0.0;


// Assign a Uniquej ID to the HMC5883 Compass Sensor
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the NEO-M8N GPS module
SoftwareSerial s1(RXPin1, TXPin1);

void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void setup()
{
  pinMode(RPin1, OUTPUT);
  digitalWrite(RPin1, HIGH);
  pinMode(RPin2, OUTPUT);
  digitalWrite(RPin2, HIGH);
  Serial.begin(GPSBaud);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  s1.begin(GPSBaud);

  Serial.println(F("Debugging attached NEO-M8N GPS module and LoRa"));
  Serial.print(F("Using TinyGPS++ library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println();
  displaySensorDetails();
}

void loop()
{
  Serial.println("Data from gps:");
  delay(1000);
  // This sketch displays information every time a new sentence is correctly encoded from the GPS Module.
  while (s1.available() > 0) {
    if (gps.encode(s1.read())) {
      displayGpsInfo();
    }
  }
}

void displayGpsInfo()
{
  // Prints the location if lat-lng information was recieved
  Serial.print(F("Location: "));
  if (gps.location.isValid())
  {
    lat = gps.location.lat();
    lon = gps.location.lng();
    Serial.print(lat, 6);
    Serial.print(F(","));
    Serial.print(lon, 6);
  }
  // prints invalid if no information was recieved in regards to location.
  else
  {
    Serial.print(F("INVALID"));
  }

  Serial.print(F("  Date/Time: "));
  // prints the received GPS module date if it was decoded in a valid response.
  if (gps.date.isValid())
  {
    Serial.print(gps.date.day());
    Serial.print(F("/"));
    Serial.print(gps.date.month());
    Serial.print(F("/"));
    Serial.print(gps.date.year());
  }
  else
  {
    // prints invalid otherwise.
    Serial.print(F("INVALID DATE"));
  }

  Serial.print(F(" "));
  // prints the recieved GPS module time if it was decoded in a valid response.
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(F(":"));
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(F(":"));
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(F("."));
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.print(gps.time.centisecond());
  }
  else
  {
    // Print invalid otherwise.
    Serial.print(F("INVALID TIME"));
  }
  Serial.println();
  if (mag.begin())
  {
    displayCompassInfo();
  }
}

void displayCompassInfo()
{
  /* Get a new sensor event   */
  sensors_event_t event;
  mag.getEvent(&event);

  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  "); Serial.println("uT");

  // Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  float declinationAngle = 0.081;
  heading += declinationAngle;

  // Correct for when signs are reversed.
  if (heading < 0)
    heading += 2 * PI;

  // Check for wrap due to addition of declination.
  if (heading > 2 * PI)
    heading -= 2 * PI;

  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180 / M_PI;

  Serial.print("Heading (degrees): "); Serial.println(headingDegrees);
  delay(1000);
}

float bearingCalc(char var[])
{
  int i;
  float y, x, b, lat, lon;
  float lat_ar[8];
  float lon_ar[8];
  for (i = 0; i < 9; i++) {
    lat_ar[i] = var[i];
    lon_ar[i] = var[10+i];
  }
  //lat = atof
  
  return b;
}

Serial monitor from inside the house:

Location: INVALID  Date/Time: 30/05/2020 11:32:24.00
X: 4.55  Y: -32.27  Z: 88.98  uT
Heading (degrees): 282.66

Raw data from gps module from inside the house:

$GNVTG,,,,,,,,,N*2E
$GNGGA,,,,,,0,00,99.99,,,,,,*56
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GNGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*2E
$GPGSV,1,1,00*79
$GLGSV,1,1,00*65
$GNGLL,,,,,,V,N*7A

No satellite fix yet. Take it clear outside, far away from buildings. It can take many minutes for a factory fresh GPS module to get a "cold start" fix.

Use the "raw data" sketch to keep track of the process, i.e. the sketch that produced this output:

$GNVTG,,,,,,,,,N*2E
$GNGGA,,,,,,0,00,99.99,,,,,,*56
...

Hint: ALWAYS use the minimum configuration possible to test new hardware additions. In other words, get rid of the compass and use the library-supplied TinyGPS++ test sketch (FullExample) to verify operation.

$GPGSV,1,1,00*79
$GLGSV,1,1,00*65

This means:
GPS Satellites in view, 1 messages, 1st message, zero satellites in view. (*79 is the message checksum)
GLONASS Satellites in view, 1 message, 1st message, zero satellites in view. (*65 is the message checksum)

Does your GPS have an antenna attached?

Please post a link to the exact module you have.

The first post is not providing consistent information. The output from the says the GPS is producing at least the time\date but the 'Raw data from gps module from inside the house' does not show this, the GGA sentence is empty, no time. So the output from the program and the GPS are taken at different times or locations. So of little diagnosting help.

Be sure to be using an upto data version of the TinyGPS++ library.

A factory fresh GPS will get a fix if its outside and with a clear view of the sky, within a minute. If it takes longer assume it or its antenna is faulty. I was testing a factory fresh Quectel L70 last week, it only had a short wire as an antenna (no fancy ceramic patch) it got a fix in my garden in 32 seconds.

Dump the code you are using, go back to something a lot simpler.

If its the GPS module I think it is, labelled as M8N and with a magnetic sensor, I have one and its a fake. Its e labeled inside as a UBLOX8, bit its reporting as a UBLOX7, and it could be a fake UBLOX7 as well.

I tested it again outside at my balcony using the raw stream code and it worked within seconds! So the problem is in the tinygps and tinygps++ library. I assume that the library can't distinguish successfully the NMEA sentences. Also i noticed that the arduino using the code at reply #1 misses a lot of gps data while the stream is constant.

Here is the raw data from outside:

$GNRMC,102126.00,A,3757.68099,N,02258.87914,E,0.091,,310520,,,A*63
$GNVTG,,T,,M,0.091,N,0.168,K,A*3A
$GNGGA,102126.00,3757.68099,N,02258.87914,E,1,05,3.28,56.8,M,32.9,M,,*7D
$GNGSA,A,3,29,31,21,,,,,,,,,,4.44,3.28,3.00*18
$GNGSA,A,3,79,78,,,,,,,,,,,4.44,3.28,3.00*13
$GPGSV,2,1,07,14,,,31,18,38,196,19,21,23,208,37,25,,,28*7F
$GPGSV,2,2,07,29,70,342,36,31,41,296,31,49,42,208,35*4D
$GLGSV,1,1,04,77,40,151,,78,82,315,35,79,27,327,35,88,,,34*58
$GNGLL,3757.68099,N,02258.87914,E,102126.00,A,A*77

PS Dont raid my house

So the problem is in the tinygps and tinygps++ library.

How did you reach that conclusion ?

If the GPS can't get messages from the satellites then no amount of code is going to be able to compensate for that.

Isn’t the raw data I posted everything you require from a gps?

sirick:
So the problem is in the tinygps and tinygps++ library. I assume that the library can't distinguish successfully the NMEA sentences

That possible, older copies of TinyGPS++ do not recognise the $GNGGA style sentences, which is why I mentioned it in post #4.

Apart from that, if TinyGPS++ is not recognising the stuff your giving it as geniune output from a GPS, the problem is yours.

If the latest version of TinyGPS++ doesn't work, either you have connected the GPS module incorrectly, configured the Baud rate incorrectly, or you forgot to take everything outside.

Hmm i found the problem while testing outside. It was the timing. Even though data from gps module is constant with correct latlng, tinygps++ will encode only after many tries while the loop is going even without delays. So the timing is the problem. How can i make the code in such way that arduino will catch the serial data from the gps in time for the library to encode the raw data successfully every time?
Also i noticed that while (s1.available() > 0) goes out of the loop without getting the whole NMEA sentences for some unknown reason so that's why i need to find other way.

You're printing a lot of data to serial. That may be causing your code to block. Try bumping up the speed for serial - there's no need for it to run as slow as your GPS.

As to not reading complete NMEA sentences at a time, there's no reason that it should - serial data transfers are slow and the Arduino can easily exhaust the data in its read buffer and go on to other things. It doesn't matter though, you'll pick up more data on subsequent iterations of loop and when you have enough you'll get lat lon data.

Indeed every time a complete sentence is encoded, you dissapear off and do a heap of stuff. By the time you get back to reading the GPS the next sentence might have alread started and is missed.

A loop develops, you always miss decoding the two sentences you need to a fix to be valid.

I have used this way of reading the GPS for many years, it reliable, there is a timeout so the program dows not get stuck if the GPS fails;

bool gpsWaitFix(uint16_t waitSecs)
{
  //waits a specified number of seconds for a fix, returns true for good fix

  uint32_t endwaitmS;
  uint8_t GPSchar;

  Serial.print(F("Wait GPS Fix "));
  Serial.print(waitSecs);
  Serial.println(F(" seconds"));

  endwaitmS = millis() + (waitSecs * 1000);

  while (millis() < endwaitmS)
  {
    if (GPSserial.available() > 0)
    {
      GPSchar = GPSserial.read();
      gps.encode(GPSchar);
      Serial.write(GPSchar);
    }

    if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated())
    {
      endFixmS = millis();                                //record the time when we got a GPS fix
      return true;
    }
  }

  return false;
}

I have attached the code for a working GPS checker that displays whats coming from the GPS to serial monitor and when it has an updated fix will display; Latitude, Longitude, Altitude, Number
of satellites in use, the HDOP value, time and date.

29_GPS_Checker_With_Display.ino (9.44 KB)

Can you please describe the physical setup you use to capture the raw NMEA sentences that you posted earlier (the successful ones).

What devices were involved? Were you processing the data through a sketch?

John.

a generic thought appropriate to many things: thousands of people use tinygps and tinygps++ every day all day, and your first thought is the library is the problem? that's right up there with saying Windows is the source of your problem. consider the vast base of daily users to be at least as clever as you, and do not conclude that what is probably the most used GPS library in existence to be the problem until you have eliminated every conceivable alternative.

HillmanImp:
Can you please describe the physical setup you use to capture the raw NMEA sentences that you posted earlier (the successful ones).

What devices were involved? Were you processing the data through a sketch?

John.

Yes of course i used another sketch. The physical connection is: arduino uno->4bit shift converter(5v-3.3V)->NEO-M8N
Here is the code for the raw data:

/ Arduino Uno
// ---------------
/*
   This sketch parses the incoming data from the gps to the arduino
   and then sends them to the lora transmitter via serial connection.
   GPS device hooked up on pins 2(rx) and 3(tx) and a HMC5883 Magnetic
   Compass connected to the SCL/SDA pins.
*/

#include <SoftwareSerial.h>
#include <stdlib.h>

static const int RXPin1 = 2, TXPin1 = 3;
static const uint32_t GPSBaud = 9600;
static int i = 0, c = 0;
static char varbuf[32];
unsigned long start, stop, time;


// The serial connection to the NEO-M8N GPS module
SoftwareSerial s1(RXPin1, TXPin1);



void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ; 
  }
  s1.begin(9600);

  Serial.println(F("Debugging attached NEO-M8N GPS module and LoRa"));
  Serial.println();
}

void loop()
{
  Serial.println("Data from gps:");
  //while (s1.available() > 0) { is quiting before the whole Raw Sentence is printed
  while (c == 0) {
    varbuf[i] = s1.read();
    Serial.print((char)varbuf[i]);
    i++;
    if (i == 32) {
      i = 0;
      //memset(varbuf, 0, sizeof(varbuf));
    }
  }
}

srnet:
I have attached the code for a working GPS checker that displays whats coming from the GPS to serial monitor and when it has an updated fix will display; Latitude, Longitude, Altitude, Number
of satellites in use, the HDOP value, time and date.

Your code works flawlessly. I ll base mine on that thank you very much! It basically does exactly what i wanted. Waits until it gets enough useful gps data.

There is an issue with using SoftwareSerial, which you were using to read the GPS, and breaking off to print lots of stuff to the Serial monitor.

The problem manifests itself as SoftwareSerial missing characters from the GPS. One missed character and a sentence is missed also.

NeoSWserial does not have the same issues.

srnet:
NeoSWserial does not have the same issues.

Or, better yet, use a board with an available hardware serial port.

gfvalvo:
Or, better yet, use a board with an available hardware serial port.

In an ideal World I would agree completly.