What pins does the Adafruit Ultimate GPS logger shield use?

Hi!
I am using the GPS shield from Adafruit(Adafruit Ultimate GPS Logger Shield - Includes GPS Module : ID 1272 : $29.95 : Adafruit Industries, Unique & fun DIY electronics and kits) and I am planning to use ultrasonic sensors with the Uno along side the shield. I tried using them together but the ultrasonic sensor sometimes spits out a bad reading and when I just use the ultrasonic sensors, and they work consistently. My assumption is that the GPS and ultrasonic sensors are using the same pins which leads to bad readings from the ultrasonic sensor.

So my question is, what Digital pins are being used by the GPS shield so I can plug my ultrasonic sensor around it. My latest attempt was using pins 4 and 5 but it seemed that the readings were still off. Here is my code:

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

#define TRIGGER_PIN  5 
#define ECHO_PIN     4  
#define MAX_DISTANCE 200

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

NewPing sonar(TRIGGER_PIN, ECHO_PIN, 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(true);
  pinMode(10, OUTPUT);
    SD.begin(chipSelect);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
}

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;  //sonar sensor part
  int myInts[25];
  for (int pin = 0; pin < 25; pin++) {
  unsigned int uS = sonar.ping();
  myInts[pin]=uS;
  delay(200);
  
  }
  for (int i=0; i<25;i++){
    if (myInts[i] > 1){
        total = total + myInts[i];
        final = final + 1;
        
    }

  
  }
  total = total/final;
  if (total < 0){
  total = total*-1;
  }


Serial.println(total);
  if (! usingInterrupt) { // gps stuff

    char c = GPS.read();

    if (GPSECHO)
      if (c) Serial.print(c);
  }
  

  if (GPS.newNMEAreceived()) {

  
    if (!GPS.parse(GPS.lastNMEA()))   
      return; 
  }


  if (timer > millis())  timer = millis();


  if (millis() - timer > 2000) { //file stuff
    timer = millis(); 
      File dataFile = SD.open("datalog.txt", FILE_WRITE);
    dataFile.print(total);
    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();
    
  }
  total = 0;
}

Thanks a bunch in advance!

The issue is that SoftwareSerial uses interrupts, and spends a lot of time receiving GPS data, so characters arrive while NewPing is trying to take a reading, using timer interrupts which are a lower priority than pin change interrupts. So, the time that NewPing things has elapsed for the echo to return is wrong.

You need a Mega or other Arduino with multiple hardware serial ports.

Or, you need to explain why you need ping sensors and GPS. I need a good laugh.

PaulS:
The issue is that SoftwareSerial uses interrupts, and spends a lot of time receiving GPS data, so characters arrive while NewPing is trying to take a reading, using timer interrupts which are a lower priority than pin change interrupts. So, the time that NewPing things has elapsed for the echo to return is wrong.

You need a Mega or other Arduino with multiple hardware serial ports.

Or, you need to explain why you need ping sensors and GPS. I need a good laugh.

Would the Arduino Due work with the shield?

As for the use, we are sending up a weather balloon and we wanted to see how much the speed of sound changed by seeing the difference in ping times. We also needed the altitude which is where the GPS comes in.

Would the Arduino Due work with the shield?

It should.

As for the use, we are sending up a weather balloon and we wanted to see how much the speed of sound changed by seeing the difference in ping times.

What are you going to ping from the balloon? The signal sent by the sensor has to bounce off of something. In your case, something a known distance away.

We also needed the altitude which is where the GPS comes in.

My GPS does a lousy job of determining altitude. A barometric pressure sensor will be much more accurate, if temperature compensated.

We have the sensors in a closed styrofoam box where they will ping off the opposite side from a fixed position. From the testing of the GPS shield for me, the attitude has stayed between a range of about 15 feet which is more than acceptable for this particular use. Though if GPS loses a fix, then the barometer idea would be much better. Thanks for the help!

You could disable the GPS input while the ping is going. After the ping time is determined, do the same GPS.begin you did in setup, and handle the GPS data for a second or two, which gets the latest fix data. Then do a GPS.end(). Don't use_interrupt(true)! This will also mess up the ping timings.

You are then free to print or save some things after the two seconds of GPS processing. Printing before this will cause interrupts, which interferes with SoftwareSerial. Finally, do a Serial.flush() to make sure the printing is completed before exiting loop() and starting the ping again:

void loop()
{
  // Ping 25 times and average
  ...

  // Handle GPS data for 2 seconds
  GPS.begin( ... )
  uint32_t start_time = millis();
  do {

    while (GPS.available()) {
      GPS.read();
      if (GPS.newNMEAreceived())
        GPS.parse( GPS.lastNMEA() );
    }

  } while (millis() - start_time < 2000);
  GPS.end()

  // Write to SD
  ...

  // Print some things
  ...
  Serial.flush();

This is more of a round-robin approach, instead of trying to do multiple things at the same time. Printing is one of those things.

Maybe someone else knows for sure, but I think you should switch to SDFat instead of the older SD. And make sure you're appending to the SD file, not replacing it every two seconds. Note that the GPS processing introduces a 2-second pace to loop(), so you don't need to wait before doing the SD write.

Cheers,
/dev

/dev:

void loop()

{
 // Ping 25 times and average
 ...

// Handle GPS data for 2 seconds
 GPS.begin( ... )
 uint32_t start_time = millis();
 do {

while (GPS.available()) {
     GPS.read();
     if (GPS.newNMEAreceived())
       GPS.parse( GPS.lastNMEA() );
   }

} while (millis() - start_time < 2000);
 GPS.end()

// Write to SD
 ...

I get this error message when trying to run the code:

sketch_nov03b.ino:94:16: error: 'class Adafruit_GPS' has no member named 'available'
sketch_nov03b.ino:101:7: error: 'class Adafruit_GPS' has no member named 'end'

To answer your original question, the shield uses pins 7, 8, 10 and 11-13. Those last three are the SPI bus so they can be shared. You could have looked this up yourself by reading the Adafruit tutorial. Their documentation is one of the reasons to buy stuff from them. And their support too.

Paul is right about SoftwareSerial. Buying a different board is one way to get around it but you don't absolutely have to. There are other software serial libraries that don't block the way SoftwareSerial does. You could use the UART on the Uno, with some care. Or you could do what /dev is suggesting and turn off SoftwareSerial while reading your sensors.

/dev:
Maybe someone else knows for sure, but I think you should switch to SDFat instead of the older SD.

SdFat is a better library but SD works okay. It's pretty low on the list here.

Does anyone know why I get "sketch_nov03b.ino:94:16: error: 'class Adafruit_GPS' has no member named 'available' "?

Oh, right. AdaFruitGPS doesn't have the available method. Just do this:

  // Handle GPS data for 2 seconds
  GPS.begin( ... );
  uint32_t start_time = millis();
  do {

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

  } while (millis() - start_time < 2000);
  GPS.end();

Cheers,
/dev

/dev:
Oh, right. AdaFruitGPS doesn't have the available method. Just do this:

  // Handle GPS data for 2 seconds

GPS.begin( ... );
  uint32_t start_time = millis();
  do {

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

} while (millis() - start_time < 2000);
  GPS.end();




Cheers,
/dev

It also says the same thing for "GPS.end()"

It also says the same thing for "GPS.end()"

Doh!

  mySerial.end();

Also, at the end of setup(), do the same thing:

  mySerial.println(PMTK_Q_RELEASE);
  mySerial.flush();
  mySerial.end();
}

With AdaFruitGPS, I keep forgetting that GPS knows about mySerial.

Cheers,
/dev

...added a flush()[TT] above.

This seems like a perfect candidate for NeoGPS and gSoftSerial. The latter has listen() and ignore() methods with exactly this sort of thing in mind.

I'm curious about the rest of the project though. How high and for how long will this balloon be in flight? What's it pinging?

/dev:
...added a

flush()[TT] above.

[/quote]

With this current code, it just returns 0's for the GPS altitude. Am I supposed to delete something or add something?


#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 MAX_DISTANCE 200

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

NewPing sonar(TRIGGER_PIN, ECHO_PIN, 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(true);
  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;  //sonar sensor part
  int myInts[25];
  for (int pin = 0; pin < 25; pin++) {
  unsigned int uS = sonar.ping();
  myInts[pin]=uS;
  delay(200);
  
  }
  for (int i=0; i<25;i++){
    if (myInts[i] > 1){
        total = total + myInts[i];
        final = final + 1;
        
    }

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

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

  } while (millis() - start_time < 2000);
    mySerial.flush();
mySerial.end();
      File dataFile = SD.open("datalog.txt", FILE_WRITE);
    dataFile.print(total);
    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();

  
}

I appreciate all the help you and others have given!

I think it is just pinging inside the insulated box. A fixed distance, with ping times that change with altitude.

gSoftSerial could be used instead, should probably be used, even. NeoGPS would require more changes, so I was reluctant to suggest it at this point. If RAM becomes an issue, it would help. The round-robin approach means speed probably won't be an issue. Besides, we've only said its name twice. :wink:

Cheers,
/dev

GPS.begin(9000);

You need to change to this:

use_interrupt( false );

And you may not have a good enough fix to get an altitude. Do you have the original example to try?

/dev:
You need to change to this

No, that's not it. It's just a typo with the baud rate.