Ultimate GPS Logger Shield with Garmin Sonar Readings

Hello everybody,

I'm having some troubles with the "Ultimate GPS Datalogger" from Adafruit. I have a Garmin Sonar connected to the "Ultimate GPS Datalogger" and the Arduino UNO. The Garmin sonar sends strings with information about the depth, which are read as strings by the datalogger. The shield is able to read/write both the GPS position and string.

However, the problem is that after a couple of readings stops. Sometimes after 10 readings, sometimes after 3 readings. During the last reading, the shield logs first the reading from the sonar and then stops at the moment when it should read the GPS signal. What surprises me most is that if I reset the datalogger, without any problem it starts logging again, and stops after a seemingly random number of good strings. However, when I try to log only the GPS signal, with another code, there is no problem.

Anyone encountered similar problem with Adafruit Ultimate GPS Datalogger? Can it be that my Arduino UNO hasn't sufficient capacity to run the code? In case anyone has experience with logging string coming out from the sonar, your advice would be highly appreciated.

Thanks beforehand,

Esteban Caligaris,
Asuncion, Paraguay

P.D.: This is the code I'm using:

#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
 
SoftwareSerial sonar(6,5); // RX, TX
SoftwareSerial gps(8,7);
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
String inputString1 = ""; 
String inputString2 = "";         // a string to hold incoming data
const int chipSelect = 10;
File dataFile;
boolean stringComplete = false;  // whether the string is complete
int a=0;
 
void setup() 
{
 //Serial.begin(57600); // Xbee
  Serial.begin(115200); // Terminal
  sonar.begin(4800);
  gps.begin(9600);
  inputString1.reserve(200);
  inputString2.reserve(200);
  gps.println(PMTK_SET_NMEA_OUTPUT_RMCONLY);
    
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening datalog.txt");
    // Wait forever since we cant write data
    while (1) ;
  }
}
 
void loop() {
 sonar.listen();
 while(a==0){
 while (sonar.available()) {
 char inChar = (char)sonar.read(); 
 inputString1 += inChar;
 if (inChar == '\n') {
 stringComplete = true;
 } 
 }
 if (stringComplete) {
 if (inputString1.startsWith("$SDDBT")){
 a=1;
 
 dataFile.println(inputString1);
 Serial.print(inputString1);
 dataFile.flush();
 }
  inputString1 = "";
 stringComplete = false;
 }
 }
 gps.listen();
 while(a==1){
 while (gps.available()) {
 char inChar = (char)gps.read(); 
 inputString2 += inChar;
 if (inChar == '\r') {  
 stringComplete = true;
 } 
 }
 if (stringComplete) {
 if (inputString2.startsWith("$GPRMC")){
 dataFile.println(inputString2);
 Serial.print(inputString2);
 dataFile.flush();
 
 
 a=0;
 
 }
 inputString2 = "";
 stringComplete = false;
 }
 }
}

I'd say "get rid of all the Strings".

But then, I don't like Strings, and never use them.

The String class can cause memory corruption in the small memory on an Arduino.

I don't understand why you are using WHILE - in general IF is better because it does not block.

Have a look at the examples in Serial Input Basics for simple reliable ways to receive data.

I suspect SoftwareSerial is not suitable for what you are doing. It can only listen on one instance at a time but both of your devices (sonar and GPS) are probably transmitting even when SoftwareSerial is not listening.

I suggest you use a Mega which has 3 extra hardware serial ports.

Please use the AutoFormat tool to lay out your code in a readable manner.

...R