Why do I get crazy GPS altitudes?

Hi!
I currently have a problem with my Ultimate Adafruit GPS shield in that it spits out weird altitudes every maybe hundred loops. I am using other sensors but when the GPS is running I make sure that nothing else is running. Would it be because I don’t have a good fix or is it because something in my code is messing it up? I am using the Uno and the code uses about 78 percent of memory if that makes a difference(If you see a place where I could cut down on memory, let me know). The goal of the program is to get data from 3 ultrasonic sensors and average them individually and get the GPS altitude and log it to the SD card. This is for an experiment on a weather balloon so that is why I am using ultrasonic sensors and a GPS shield.

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#include <NewPing.h>

#define TRIGGER_PIN  6 
#define ECHO_PIN     5  
#define TRIGGER_PINS  9 
#define ECHO_PINS     3 
#define TRIGGER_PIN_THREE     7 
#define ECHO_PIN_THREE     4 
#define MAX_DISTANCE 200

SoftwareSerial mySerial(8, 7);
const int chipSelect = 10;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
NewPing second_sonar(TRIGGER_PINS, ECHO_PINS, MAX_DISTANCE);
NewPing third_sonar(TRIGGER_PIN_THREE, ECHO_PIN_THREE, MAX_DISTANCE);
Adafruit_GPS GPS(&mySerial);

#define GPSECHO  true

boolean usingInterrupt = false;
void useInterrupt(boolean); 
int total;
void setup()  
{

  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");
  
  GPS.begin(9600);
  

  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);

  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   
  GPS.sendCommand(PGCMD_ANTENNA);

  useInterrupt(false);
  pinMode(10, OUTPUT);
    SD.begin(chipSelect);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
  mySerial.flush();
  mySerial.end();
}

SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;   
#endif
}

void useInterrupt(boolean v) {
  if (v) {

    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {

    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}

uint32_t timer = millis();

void loop()
{
  int final = 0; 
  int another=0; //sonar sensor part
  int myInts[20];
  int moreInts[20];
  delay(100);
  for (int pin = 0; pin < 20; pin++) {
  unsigned int first = sonar.ping();
  myInts[pin]=first;
  delay(100);
  unsigned int sec = second_sonar.ping();
  moreInts[pin]=sec;
  delay(100);

  }
  for (int i=0; i<20;i++){
    if (myInts[i] > 1){
        total = total + myInts[i];
        final = final + 1;
        another = another+moreInts[i];
    }

  
  }
  total = total/final;
  another = another/final;
  if (total < 0){
  total = total*-1;
  }
  if (another < 0){
  another = another*-1;
  }
  GPS.begin(9600);
  uint32_t start_time = millis();
  do {

    GPS.read();
    if (GPS.newNMEAreceived())
      GPS.parse( GPS.lastNMEA() );

  } while (millis() - start_time < 2000);
    mySerial.flush();
mySerial.end();
delay(100);
      File dataFile = SD.open("datalog.txt", FILE_WRITE);
    dataFile.print(total);
    dataFile.print(" / ");
    dataFile.print(another);
    dataFile.print(" / ");
    dataFile.print(something);
    dataFile.print(" : ");
    dataFile.print(GPS.altitude);
    dataFile.print(" ; ");
    dataFile.print(GPS.hour, DEC); 
    dataFile.print(".");
    dataFile.print(GPS.minute, DEC);
    dataFile.print(".");
    dataFile.println(GPS.seconds, DEC);
    dataFile.close();

  
}

Any help would greatly be appreciated!

#define TRIGGER_PIN_THREE     7
#define ECHO_PIN_THREE     4
#define MAX_DISTANCE 200

SoftwareSerial mySerial(8, 7);

So, what IS pin 7 being used for?

You can't assume that GPS data will arrive only while you aren't pinging.

bb12jo: Would it be because I don't have a good fix or is it because something in my code is messing it up?

If you find "fast jumping data" that change more in quick jumps rather than in increasing/decreasing values over several seconds, the problem is caused by the worst of all Arduino libraries that you are using: SoftwareSerial.

You cannot use hardware "Serial" and "SoftwareSerial" at the same time without SoftwareSerial garbling your data.

If you need to operate "Serial" and "SoftwareSerial" at the same time, don't use any of the ports with a speed more than 4800 baud!

If you need a software serial emulation to work flawlessly with Serial, you better switch over to: https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

But for the advantage that AltSoftSerial works flawlessly with Serial at the same time, you get the disadvantage that the pins are fixed. For example with an UNO board, the AltSoftSerial-TX is Pin-9 and AltSoftSerial-RX is Pin-8 (and Pin-10 becomes unusuable for PWM output).

I currently have a problem with my Ultimate Adafruit GPS shield in that it spits out weird altitudes every maybe hundred loops. I am using other sensors but when the GPS is running I make sure that nothing else is running. Would it be because I don’t have a good fix or is it because something in my code is messing it up?

Well, ‘something’ is not defined in your program! :slight_smile:

As jurs said, you are using a terrible combination of libraries: Adafruit_GPS and SoftwareSerial. In your previous posts, you said “If this doesn’t work down the line, I can always try out the other libraries that you recommended.” Please consider NeoGPS plus NeoSWSerial. Together, they will easily address these performance and reliability issues.

I am using the Uno and the code uses about 78 percent of memory if that makes a difference(If you see a place where I could cut down on memory, let me know).

NeoGPS will save you several hundred bytes of RAM with this code:

#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include <NewPing.h>

#define TRIGGER_PIN  6 
#define ECHO_PIN     5  
#define TRIGGER_PINS  9 
#define ECHO_PINS     3 
#define TRIGGER_PIN_THREE     7 
#define ECHO_PIN_THREE     4 
#define MAX_DISTANCE 200

const int chipSelect = 10;

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
NewPing second_sonar(TRIGGER_PINS, ECHO_PINS, MAX_DISTANCE);
NewPing third_sonar(TRIGGER_PIN_THREE, ECHO_PIN_THREE, MAX_DISTANCE);

int total;
int something;

#include "NMEAGPS.h"

#include <NeoSWSerial.h>
NeoSWSerial gps_port( 8, 7 );

static NMEAGPS  gps; 
static gps_fix  fix_data;

//------------------------------------

static void GPSloop()
{  
  while (gps_port.available()) {

    if (gps.decode( gps_port.read() ) == NMEAGPS::DECODE_COMPLETED) {
      fix_data |= gps.fix();
    }
  }
} // GPSloop

//--------------------------

#define PMTK_SET_NMEA_OUTPUT_GGAONLY (str_P) F("$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
#define PMTK_SET_NMEA_UPDATE_1HZ  (str_P) F("$PMTK220,1000")
#define PMTK_ANTENNA_UPDATES (str_P) F("$PGCMD,33,1")
#define PMTK_Q_RELEASE (str_P) F("$PMTK605")

void setup()
{
  // Start the normal trace output
  Serial.begin(9600);
  
  // Start the UART for the GPS device
  gps_port.begin( 9600 );
  gps.send_P( &gps_port, PMTK_SET_NMEA_OUTPUT_GGAONLY ); // don't need RMC
  gps.send_P( &gps_port, PMTK_SET_NMEA_UPDATE_1HZ );
  //gps.send_P( &gps_port, PMTK_ANTENNA_UPDATES );
  //gps.send_P( &gps_port, PMTK_Q_RELEASE );
  //gps_port.flush();  // not needed for NewSWSerial
  
  gps_port.ignore(); // until we're ready...
}

//--------------------------

void loop()
{
  // Get some sonar data

  int final = 0; 
  int another=0; //sonar sensor part
  int myInts[20];
  int moreInts[20];

  for (int pin = 0; pin < 20; pin++) {
    delay(100);
    unsigned int first = sonar.ping();
    myInts[pin]=first;
    delay(100);
    unsigned int sec = second_sonar.ping();
    moreInts[pin]=sec;
  }

  for (int i=0; i<20;i++){
    if (myInts[i] > 1){
      total = total + myInts[i];
      final = final + 1;
      another = another+moreInts[i];
    }
  }
  total = total/final;
  another = another/final;
  if (total < 0){
    total = total*-1;
  }
  if (another < 0){
    another = another*-1;
  }

  // Get some fresh GPS data

  gps.data_init();
  fix_data.init();
  gps_port.listen();
  uint32_t start_time = millis();
  do {
    GPSloop();
  } while (millis() - start_time < 2500);
  gps_port.ignore();

  // Log what we have so far

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  dataFile.print(total);
  dataFile.print( F(" / ") );
  dataFile.print(another);
  dataFile.print( F(" / ") );
  dataFile.print(something);

  dataFile.print( F(" : ") );
  if (fix_data.valid.altitude)
    dataFile.print(fix_data.altitude());
  else
    dataFile.print('-'); // or print nothing? or '?'
  dataFile.print( F(" ; ") );

  if (fix_data.valid.time) {
    dataFile.print(fix_data.dateTime.hours, DEC); 
    dataFile.print('.');
    dataFile.print(fix_data.dateTime.minutes, DEC);
    dataFile.print('.');
    dataFile.println(fix_data.dateTime.seconds, DEC);
  } else
    dataFile.println('-'); // or whatever

  dataFile.close();

}

The whole sketch uses 1k of RAM, about 50%, instead of 78%. GPSfix_cfg.h only enables TIME and ALTITUDE, and NMEAGPS_cfg.h only enables NMEA_GPS_PARSE_GGA. NeoGPS is using only 47 bytes, the rest is used by sonar, SD and the normal IDE stuff. BTW, you should probably switch to SDFat from SD…

As you can see, there is much less code, and I’d like to think it’s much more readable. Also notice that all the double-quoted strings are inside the F() macro, which saves a little more RAM.

But most importantly, PaulS points out that you appear to be using one pin for two things. You cannot use pin 7 for GPS and third_sonar. They will both try to drive pin 7.

Cheers,
/dev