Add Altitude to GPS sketch

Thank you. Tried the sketch as suggested.

Altitude: 999999999 cm

Did you adapt it to your serial port? Did you see the NMEA messages especially the $GPGGA? Remember the $GPGGA message is the one with the altitude. TinyGPS is just extracting the information.

Apologise Klaus, my VK2828 appears to has gone mad. It flashes green and produces some output, but not what we want.

I have tried another, and it is giving:- Altitude: 21290 cm which is pretty close.

My second VK2828u7g5lf is now outputting the false altitude. It seems to have flipped to another format:

$GPVTG,,T,,M,0.362,N07K*
7,583E,1419,.,0195,,5.2*
GV,101,050,0101201,,4417$G3,,,,5,,2,*
PL119S7.9,090,7
$GPRMC,032911.00,A,4112.16395,S,17452.81936,E,0.326,,171219,,,A*61
Altitude: 999999999 cm

What does that, and how dou you get back to $GPGGA?

I suspect this is the software serial. If you look there are lines which are incomplete. The software serial is likely missing some bits and therefore some messages are incomplete and cannot be parsed properly.

What Arduino board are you using?

johngxnz:
My second VK2828u7g5lf is now outputting the false altitude.

I would concur with @Klaus_K, that looks like a problem with your code.

The boards I have used are UNO and UNO R3.
I have been testing using the Klaus sketch posted Dec 14 2019 05:14pm page 3; and that sketch with added code attempting to display SerialMonitor and LCD display of Lon, Lat, and Altitude.

The results are very inconsistent

Looking at the data string from each sketch is different, and different at different times. Sometimes the GPGGA string includes the altitude value, often it is incomplete.

On a "good day", the string looks like this:

$GPVTG,,T,,M,0.070,N,0.130,K,A*26
$GPGGA,233237.00,4112.16234GA,233239.00,4112.16232,S,17452.81858,E,1,08,1.79,209.6,M,16.0,M,,*4D
$GPGSA,A,3,17,28,06,01,30,03,22,11,,,,,2.49,1.79,1.73*0C
$GPGSV,4,1,14,01,20,138,33,02,05,329,,03,19,096,33,06,41,347,33*78
$GPGSV,4,2,14,11,12,128,30,12,01,238,,13,03,304,,17,73,181,33*76
$GPGSV,4,3,14,18,00,142,,19,67,251,08,22,16,117,26,24,22,228,22*78
$GPGSV,4,4,14,28,58,080,39,30,17,007,33*7B
$GPGLL,4112.16232,S,17452.81858,E,233239.00,A,A*75
$GPRMC,233240.00,A,4112.16233,S,17452.81852,E,0.025,,171219,,,A*63
   Lon: 174.88031  Lat: -41.20270   Altitude: 20980 cm

At another time, the Klaus sketch gave:

$GPVTG,,T,,M,0.268N.,A4GG7.5E,,680,0,4$9,,0.,53PV102,2,89,,1,,36237,,8*
P,2,,3,,00,9,,5637
G,3,,2,302*
P,153,583,49,A4$GPRMC,034700.00,A,4112.15548,S,17452.81693,E,0.793,,181219,,,A*69
   Lon: 174.88029  Lat: -41.20259   Altitude: 999999999 cm

My extended sketch gave:

$GPVTG,,T,,M,0.043,N,0.080,K,A*2C
$GPGGA,032328.00,4112.162847D
$GPGSV,3,3,10,29,21,235,22,31,00,215,29*7B
$GPGLL,4112.16272,S,17452.81645,E,032346.00,A,A*79
$GPRMC,032347.00,A,4112.16272,S,17452.81640,E,0.089,,181219,,,A*67
   Lon: 174.88027  Lat: -41.20271   Altitude: 999999999 cm

While outputting the string above, the LCD on my extended sketch was displaying the $GPRMC values above (999999999 cm).

I have seen the true altitude using the Klaus sketch, but more often it gives 999999999 cm

The issue could be the software serial. Because the protocol is asynchronous and has no clock it is susceptible to timing errors. Using a hardware UART gives you a better chance of working correctly.

Here are a few options. Let me know which one you would like to try.

  1. Use another Arduino which has a free hardware UART available. Ether one with two UARTs or one where the Serial Monitor is handled directly by a USB peripheral (likely that one will have even more UARTs).

  2. Use a Sketch without Serial Monitor and after downloading the sketch connect the GPS module to the hardware serial port. You can use your LCD to view the data.

  3. Share the UART between the Serial Monitor and the GPS. Again, with this you can connect the GPS module only after the sketch has been downloaded. So, you would connect the GPS Tx to the Arduino Rx and leave the GPS Rx disconnected or better pull it to high with a 10KOhm resistor. The Arduino Tx pin is connected to the Serial Monitor and you must not send any data from the Serial Monitor.

Are you still persisting with TinyGPS ?

It was last updated 6 years ago, I find the newer versions, TinyGPS++ or TinyGPSplus, much easier to use. No problems printing the altitude with this up to date code either.

My initial post seeking advice about the absence of altitude followed my creation of a sketch to write Date/Time, Lon, Lat, and Altitude to a SD text file in GPX format, and to display Lon, Lat, and Altitude on an LCD display as an independent portable battery powered device. There was no real need for a Serial Monitor except for diagnosis. Everything appeared to work except for altitude.

With that in mind, I’m not sure which of your three suggestion would best fit the above, and what I would be looking for hardware wise. Am I to understand that without the serial monitor, only one UART is needed??

I answer to srnet I am using TinyGPS. I tried TinyGPSPlus but i did no better.

The reason the other values are displayed, is that they are encoded in multiple messages formats. Altitude is only encoded in the $GPGGA. And as you can see that message format is long, so there is a higher chance of an error.

Just to be on the safe side. Are you sure your wiring between the Arduino and the GPS module is solid? You do not have very long wires, you have good connections and you have connected all pins e.g. EN to High for power enable, GND, ...?

Options 2 and 3 are free, but you need to remember that the GPS Tx signal needs to be disconnected from the Arduino Rx while you are reprogramming your device. And it is best to leave the GPS Rx disconnected or pulled high.

With option 3 you can even use the Serial Monitor to see whether the problem is actually the software serial. You can use this very simple loopback code to test this.

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

void loop()
{
  if ( Serial.available() )
  {
    char c = Serial.read();
    Serial.write( c );
  }
}

First just type a few characters into the Serial Monitor. They should appear in the Monitor window. Then connect the GPS Tx to the Arduino Rx. Now you should see the GPS messages.

The gps module is less than 200mm from the Arduino board, which is sitting on a window sill facing the equator. EN and TX are connected to +5v.

I tried your latest sketch (shown in full below to be sure), but I did not get any data on the serial monitor:

#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(2, 3);
#define Serial1


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

void loop()
{
  if ( Serial.available() )
  {
    char c = Serial.read();
    Serial.write( c );
  }
}

Meanwhile, to double check, one of your previous sketches displayed multiple satellite strings or another simple one displayed altitude.

Re your previous post, option 2 would be the preferred one.

Below are two identical sketches, except for the display. The first (sketch_dec15a) gives altitude on the serial monitor, the other (GPS1602_sketch_dec18a) gives a false (99999) altitude on the LCD:

//sketch15a

#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(2, 3);
#define Serial1

long lat, lon;

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

void loop()
{
  bool newData = false;

  if ( 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 )
  {
    long altitude;

    altitude = gps.altitude();

      gps.get_position(&lat, &lon);

      float lonx = lon;
      float latx = lat;

      Serial.print("   Lon: ");
      Serial.print(lonx / 1000000, 5);

      Serial.print("  Lat: ");
      Serial.print(latx / 1000000, 5);

    Serial.print( "   " );
    Serial.print( "Altitude: " );
    Serial.print( altitude );
    Serial.println( " cm" );
     
  }
}
//GPS1602_sketch_dec18a

#include <SoftwareSerial.h>
#include <TinyGPS.h>

TinyGPS gps;
SoftwareSerial ss(2, 3);
#define Serial1

long lat, lon;

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


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

  lcd.begin(16, 2);  // initialize the lcd for 16 chars 2 lines, turn on backlight

  lcd.backlight(); // finish with backlight on
  
}

void loop()
{
  bool newData = false;

  if ( 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 )
  {
    long altitude;

    altitude = gps.altitude();


      gps.get_position(&lat, &lon);


      float lonx = lon;
      float latx = lat;


   
      //      Send to LED

      lcd.setCursor(1, 0);               //Start at character 0 on line 0

      lcd.print(latx * -1 / 1000000, 5); // print latitude

//      lcd.print("m");

      lcd.setCursor(0, 1);
      //        lcd.print("Lon: ");
      lcd.print(lonx / 1000000, 5);  // print longitude

      
      lcd.setCursor(11, 1);
      lcd.print( altitude /10 );  
      lcd.print("m");
    
  }
}

I tried your latest sketch (shown in full below to be sure), but I did not get any data on the serial monitor:

No surprise there, since that sketch does not initialize or read from the SoftwareSerial connection.

Try this one, with connections and Baud rates set appropriately, of course.

//GPS echo
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); //(RX, TX) check correct pin assignments.

void setup() {
  mySerial.begin(9600);
  Serial.begin(9600);
  Serial.println("GPS echo starting");
}

void loop() {
  while (mySerial.available()) {
    Serial.write(mySerial.read());
  }
}

Thank you:

$GPGSV,3,2,12,11,55,080,37,13,27,236,18,15,05,215,23,17,26,321,0872
$GPGSV,3,3,12,18,37,096,34,19,09,322,15,28,49,249,14,30,82,267,20
7C
$GPGLL,4112.16761,S,17452.80800,E,203139.00,A,A7A
$GPRMC,203140.00,A,4112.16754,S,17452.80813,E,0.328,,231219,,,A
6A
$GPVTG,,T,,M,0.328,N,0.608,K,A*24
$GPGGA,203140.00,4112.16754,S,17452.80813,E,1,07,1.42,191.5,M,16.0,M,,4E
$GPGSA,A,3,30,11,01,13,07,17,28,,,,,,2.62,1.42,2.21
09

So altitude is 191.5m.

The sketch in post #50 should be used as is with the instructions below it. Because you had issues with the software serial, this is an attempt to use the hardware UART for both the Serial Monitor as well as the GPS module. This works only after programming the device and then connecting the GPS. You must enable the Serial Monitor window.

The reason this should work is that UARTs are asynchronous, so transmit and receive are independent (they share the same baudrate setting). The transmitter (TX) creates the signal from its timing.

Arduino UART TX → USB chip → Serial Monitor
Arduino UART RX ← GPS module TX

The software simply sends back what it reads. So, the GPS data is sent to the Serial Monitor. Because the timing is now hardware controlled there should not be any problems receiving the strings. This is just a test program to see whether you get any more communication issues.

You will have to connect the GPS module TX pin to the Arduino RX pin. Check the board markings and pinout to find that pin.

Re the post 50 sketch, I misunderstood the sketch and your reference to the Rx pin on the Arduino. My apologies. Reruning the sketch as you posted, and connecting the GPS Tx to the Arduino pin labelled Rx, I get:

x09,S,17452.81515,E,042324.00,A,A76
$GPRMC,042325.00,A,4112.16406,S,17452.81512,E,0.037,,241219,,,A
6F
$GPVTG,,T,,M,0.037,N,0.069,K,A28
$GPGGA,042325.00,4112.16406,S,17452.81512,E,1,07,1.98,201.6,M,16.0,M,,4F
$GPGSA,A,3,05,29,02,25,12,13,15,,,,,,4.23,1.98,3.74
09
$GPGSV,3,1,10,02,37,103,35,05,75,116,20,06,03,095,,12,19,343,33
7D
$GPGSV,3,2,10,13,21,043,33,15,15,010,35,21,05,263,,25,35,299,227A
$GPGSV,3,3,10,26,04,211,16,29,57,227,26
77
$GPGLL,4112.16406,S,17452.81512,E,042325.00,A,A*7F

I hope you had a Merry Christmas.

As you can see, you can use your GPS module without the Software Serial. You get the $GPGGA message with the altitude. So TinyGPS should run fine. We can apply this to your normal sketch.

How about you convert your sketch to use the Serial? If you have any questions or like me to review the code, post the sketch.

Thank you Klaus, and Seasons Greeting to you and yours.

I have adopted your suggestion, and now have an LCD displaying Lat, Lon, Time, AND Altitude.

Below is the complete sketch:

//GPS1602_noSerial_altitude_30DecRxDate
//#include <Wire.h>

#include <TinyGPS.h>

TinyGPS gps;

long lat, lon;
int  alt;

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


void setup()
{
  Serial.begin(9600 );

  while ( !Serial );


  lcd.begin(16, 2);  // initialize the lcd for 16 chars 2 lines, turn on backlight

  lcd.backlight();   // finish with backlight on
  
}

void loop()
{
  bool newData = false;

  if ( Serial.available() )
  {
    char c = Serial.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 )
  {

      gps.get_position(&lat, &lon);

      float lonx = lon;
      float latx = lat;
      float altitude;

      altitude = gps.altitude();
      alt = altitude /100, 0; 

   //date and time
     
  int year;
  byte month, day, hour, minute, second, hundredths;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths);
        
      
   
      //      Send to LED

      lcd.setCursor(1, 0);                //Start at character 0 on line 0
      lcd.print(latx * -1 / 1000000, 5);  // print latitude

      lcd.setCursor(0, 1);                //Start at character 0 on line 1
      lcd.print(lonx / 1000000, 5);       // print longitude

      lcd.setCursor(11, 0);
      lcd.print(hour, DEC); 
      lcd.print(":");
      lcd.print(minute, DEC);      
      
      lcd.setCursor(11, 1);
      lcd.print( alt );  
      lcd.print("m ");
    
  }
}

I am not a programmer, but have gathered together the bits that seem to work.
Thank you for your patience, very much appreciated.

This may not be the correct place to ask this question, but it is in context with previous posts.

Referring to the strings quoted in posts 46 and 56, how are these generated? Are they created within the GPS module combining data from three or more satellites??