0
votes

I'm trying to get GPS and pressure readings from my Arduino Uno. However, when I try to get pressure/temperature readings off of the pressure sensor (code snippet below), the GPS starts sending malformed packets to my serial monitor. I'd like to be able to get good GPS and pressure readings from my Arduino. (Hardware details provided below)

  float temperature_c, temperature_f;
  double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;

  String dataString = ""; 

  pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}

Here's the full code:

#include <SoftwareSerial.h>

//pressure sensor libraries
#include <Wire.h>
#include <SparkFun_MS5803_I2C.h>

//datalogger library
#include <SPI.h>
#include <SD.h>

// set up datalogger
const int chipSelect = 4;

/*-----------GPS-----------*/
SoftwareSerial gpsSerial(10, 11); // RX, TX (TX not used)
const int sentenceSize = 80;

// the $GPGGA, $GPGSA, etc. are sentences and are sent 1 character at a time from the GPS
char sentence[sentenceSize];

/*------------Pressure sensor-------*/
// Begin class with selected address
// available addresses (selected by jumper on board) 
// default is ADDRESS_HIGH

//  ADDRESS_HIGH = 0x76
//  ADDRESS_LOW  = 0x77

MS5803 sensor(ADDRESS_HIGH);

// Create Variable to store altitude in (m) for calculations;
double pressure_baseline;
double base_altitude = 1655.0; // Altitude of SparkFun's HQ in Boulder, CO. in (m)

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

  /*----------Pressure sensor stuff----------*/
    Serial.println("\ntemperature (C), temperature (F), pressure (abs), pressure (relative), change in altitude");
    //Retrieve calibration constants for conversion math.
    sensor.reset();
    sensor.begin();

    pressure_baseline = sensor.getPressure(ADC_4096);
    Serial.println(pressure_baseline);
    Serial.println("\n");
}

void loop()
{
  static int i = 0;
  if (gpsSerial.available())
  {
//    Serial.print("GPS Serial is available\n");
    char ch = gpsSerial.read();
    if (ch != '\n' && i < sentenceSize)
    {
      sentence[i] = ch;
      i++;
    }
    else
    {
     sentence[i] = '\0';
     i = 0;
//     Serial.println("\n");
     Serial.println(sentence);
//     Serial.println("\n");
     displayGPS();
    }
  }

  /*----------------------PRESSURE SENSOR-------------------------*/
  float temperature_c, temperature_f;
  double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;

  String dataString = ""; 

  pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}

/*--------------------------Pressure sensor methods----------------*/
// Thanks to Mike Grusin for letting me borrow the functions below from 
// the BMP180 example code. 

 double sealevel(double P, double A)
// Given a pressure P (mbar) taken at a specific altitude (meters),
// return the equivalent pressure (mbar) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
  return(P/pow(1-(A/44330.0),5.255));
}

double altitude(double P, double P0)
// Given a pressure measurement P (mbar) and the pressure at a baseline P0 (mbar),
// return altitude (meters) above baseline.
{
  return(44330.0*(1-pow(P/P0,1/5.255)));
}

void displayGPS()
{
  char field[20];
  getField(field, 0);
  if (strcmp(field, "$GPGGA") == 0)
  {
    Serial.print("Lat: ");
    getField(field, 2);  // number
    Serial.print(field);
    getField(field, 3); // N/S
    Serial.print(field);

    Serial.print(" Long: ");
    getField(field, 4);  // number
    Serial.print(field);
    getField(field, 5);  // E/W
    Serial.println(field);

    Serial.print("Altitude: ");
    getField(field, 9);
    Serial.println(field);

    Serial.print("Number of satellites: ");
    getField(field, 7);
    Serial.println(field);
    Serial.println("-----------------------\n");
  }
}

void getField(char* buffer, int index)
{
  int sentencePos = 0;
  int fieldPos = 0;
  int commaCount = 0;
  while (sentencePos < sentenceSize)
  {
    if (sentence[sentencePos] == ',')
    {
      commaCount ++;
      sentencePos ++;
    }
    if (commaCount == index)
    {
      buffer[fieldPos] = sentence[sentencePos];
      fieldPos ++;
    }
    sentencePos ++;
  }
  buffer[fieldPos] = '\0';
} 

When the line to get pressure is commented like so...

  float temperature_c, temperature_f;
  double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;

  String dataString = ""; 

  // pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}

...my GPS gives me proper packets of data:

$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120208.000,V,24006,,,N*71
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120209.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*61

Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------

$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120209.000,V,24006,,,N*70
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120210.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*69

Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------

$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120210.000,V,240006,,,N*78
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120211.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*68
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------

But when my line to get pressure is uncommented...

  float temperature_c, temperature_f;
  double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;

  String dataString = ""; 

  pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}

My GPS packets become malformed:

$GPGGA,120125.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,$0,0T,$GPGGA,12
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------

126.000,2400.0000,N,120,00..
$GPGGA,120127.000,2400.0000,N,100,$GPGGA,120128.000,2400.0000,N,1200,20*0$GPGGA,
Lat: 2400.0000N Long: 100$GPGGA
Altitude: 1200
Number of satellites: 2400.0000
-----------------------

20129.000,2400.0000,N,120G.4,,*$GPGGA,120130.000,2400.0000,N,1060$GPGGA,120131.0
0,2400.0000,N,12,*..E
0$GPGGA,120132.000,2400.0000,N,120A00.0
$GPGGA,120133.000,2400.0000,N,1M,
0,,$GPGGA,120134.000,2400.0000,N,1200,1070$GPGGA,120135.000,2400.0000,N,10,,,0,0
GPGGA,120136.000,2400.0000,N,120G0,0V,$GPGGA,120137.000,2400.0000,N,1,,30000
$GP
GA,120138.000,2400.0000,N,0G00V0VK$GPGGA,120139.000,2400.0000,N1,,VP,6,$GPGGA,12
140.000,2400.0000,N,1.,0*.0.
$GPGGA,120141.000,2400.0000,N,0A*00*N$GPGGA,120142.000,2400.0000,N,.,,110,0$GPGG
Lat: 2400.0000N Long: 0A*00*N$GPGGA120142.000
Altitude: ,110
Number of satellites: N
-----------------------

,120143.000,2400.0000,N,1,,P$02,$GPGGA,120144.000,2400.0000,N,10.0$GPGGA,120145.
00,2400.0000,N,10A*00000$GPGGA,120146.000,2400.0000,N,0G.020,*$GPGGA,120147.000,
400.0000,N0,,20,0$GPGGA,120148.000,2400.0000,N,120P,,0P,$GPGGA,120149.000,2400.0
00,N,1.S0000*$GPGGA,120150.000,2400.0000,N,1.,,,0,0$GPGGA,120151.000,2400.0000,N
100,50E,$GPGGA,120152.000,2400.0000,N,120S.00,N$GPGGA,120153.000,2400.0000,N,1.A
0002$GPGGA,120154.000,2400.0000,N,1.,,00N,$GPGGA,120155.000,2400.0000,N,1E*..0A0
GPGGA,120156.000,2400.0000,N,120S0400N$GPGGA,120157.000,2400.0000,N,1.A0.000$GPG
A,120158.000,2400.0000,N,100,2.N.$GPGGA,120159.000,2400.0000,N,100,906,$GPGGA,12
200.000,2400.0000,N,120,*000*$GPGGA,120201.000,2400.0000,N,10,,,.GN$GPGGA,120202
000,2400.0000,N,11,,C160$GPGGA,120203.000,2400.0000,N,12,6.00
,$GPGGA,120204.000
2400.0000,N,100,00*,$GPGGA,120205.000,2400.0000,N,120,300.
$GPGGA,120206.000,2400.0000,N,1.,R,0M$GPGGA,120207.000,2400.0000,N,12,00007N$GPG
Lat: 2400.0000N Long: 1.R
Altitude: N
Number of satellites: 120207.000
-----------------------

A,120208.000,2400.0000,N,12,A*000
$GPGGA,120209.000,2400.0000,N,007,$GPGGA,12021
.000,2400.0000,N,12,A*.00
$GPGGA,120211.000,2400.0000,N,10,,20N2$GPGGA,120212.00
,2400.0000,N,100,20N0$GPGGA,120213.000,2400.0000,N,120G040GN$GPGGA,120214.000,24
0.0000,N,1,,3.002$GPGGA,120215.000,2400.0000,N,1.,,,160$GPGGA,120216.000,2400.00
0,N,100,2.N,$GPGGA,120217.000,2400.0000,N,12,G0V.TK$GPGGA,120218.000,2400.0000,N
10G04,,0$GPGGA,120219.000,2400.0000,N,10,,10,0$GPGGA,120220.000,2400.0000,N,1,*,
0BN$GPGGA,120221.000,2400.0000,N,120S00002$GPGGA,120222.000,2400.0000,N,1M,
0,T$GPGGA,120223.000,2400.0000,N,1200,208N$GPGGA,120224.000,2400.0000,N,100,2.N,
GPGGA,120225.000,2400.0000,N,120G02.TN$GPGGA,120226.000,2400.0000,N,10,0000*$GPG
A,120227.000,2400.0000,N,1.,,00,,$GPGGA,120228.000,2400.0000,N,1E6..03,$GPGGA,12
229.000,2400.0000,N,12,,*0000$GPGGA,120230.000,2400.0000,N,1.,,0000$GPGGA,120231
000,2400.0000,N,100,2.,0$GPGGA,120232.000,2400.0000,N,12.S0000*$GPGGA,120233.000
2400.0000,N,1.S.20TK$GPGGA,120234.000,2400.0000,N,12M,$N0M$GPGGA,120235.000,2400
0000,N,10M,C160$GPGGA,120236.000,2400.0000,N,12,$.,0G0$GPGGA,120237.000,2400.000
,N,1,P,,0G,$GPGGA,120238.000,2400.0000,N,10,,C100$GPGGA,120239.000,2400.0000,N,1
,,C1,0$GPGGA,120240.000,2400.0000,N,12,G,2.G,$GPGGA,120241.000,2400.0000,N,10A00
0
$GPGGA,120242.000,2400.0000,N,1.,,00*N$GPGGA,120243.000,2400.0000,N,1,*0.,
0$G
GGA,120244.000,2400.0000,N,120A00000$GPGGA,120245.000,2400.0000,N,10,
0,,$GPGGA,120246.000,2400.0000,N,1200,407N$GPGGA,120247.000,2400.0000,N,12,,R16M
GPGGA,120248.000,2400.0000,N,1200,80
0$GPGGA,120249.000,2400.0000,N,10
,00,$.$GP
GA,120250.000,2400.0000,N,0,,1C1,0$GPGGA,120251.000,2400.0000,N,.S0,4,,*$GPGGA,1
0252.000,2400.0000,N,0
000,G0$GPGGA,120253.000,2400.0000,N,00,,.0.
$GPGGA,120254.000,2400.0000,N,,A*00002$GPGGA,120255.000,2400.0000,N,0A*00002$GPG
Lat: 2400.0000N Long: ,A*00002$GPGGA120255.000
Altitude: 
Number of satellites: N
-----------------------

Hardware:

Arduino board: Arduino Uno R3

GPS: Venus GPS (made by Sparkfun)

Pressure sensor: Ms5803-14BA Breakout (made by Sparkfun)

Data logger: OpenLog (made by Sparkfun)

Setup

What's causing my GPS to send bad packets? Evidently, the pressure sensor is somehow interfering with the GPS, but how is it doing that and how can I avoid interference?

1

1 Answers

0
votes

What's causing my GPS to send bad packets?

Well, the GPS is sending good packets, but the Arduino is too busy doing other things (pressure library) to watch the GPS characters come in. It's all because SoftwareSerial is a CPU hog. Other libraries, like AltSoftSerial (works on fewer pins), or the recent gSoftSerial would be better choices.

Do you really need to receive GPS while you're getting a pressure reading? Why not read GPS for two seconds to get a fix, then stop it and get the pressure reading. Stop the pressure interface and start the GPS again. Rinse and repeat.

I'll also throw in my obligatory pitch for NeoGPS. If nothing else, the examples show a different program structure that would help immensely... you may be able to take the pressure reading during the GPS quiet time, without stopping and starting the GPS and pressure interfaces.

NeoGPS also parses the characters as they are received, so you don't have to buffer the sentence. BTW, I recommend staying away from String, like many developers.

Edit to add: I just published NeoSWSerial, an alternative to SoftwareSerial that is much more reliable and uses much less CPU time. If the Input Capture pin 8 (and pin 9 for TX) is a possibility for you to use, you might consider NeoICSerial. They're both on github near NeoGPS.