Advice on how to run SoftwareSerial simultaneously?

Hi guys

I have an Arduino Uno connected to a GPS and a OpenLog (from sparkfun). The idea is to have the OpenLog record certain data from the GPS. Because of my project, unfortunately I cannot use the hardware serial ports. Thus, I can only use other "virtual" ports. Using the sketch below, I can receive the GPS data just fine using SoftwareSerial. However, when I enable the software serial ports for my openlog (to print only the GPS data I need), the Arduino doesn't seem to read any GPS data at all.

Has anyone experienced anything like this before? Any suggestions on how I could solve this? Thanks so much!!

This is the output I am getting:

Testing TinyGPS++ library v.


05/03/2014 19:01:37 305 20.90 1
05/03/2014 19:01:38 245 20.90 1
05/03/2014 19:01:39 28 20.90 1
05/03/2014 19:01:40 361 20.90 1
05/03/2014 19:01:41 334 20.90 1

And when I enable the OpenLog software serial, I get:

Testing TinyGPS++ library v.






No GPS data received: check wiring


No GPS data received: check wiring


No GPS data received: check wiring


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

//Logger config
int loggerTX = 7;
int loggerRX = 10;
SoftwareSerial OpenLog(loggerRX, loggerTX);

//GPS config
static const int RXPin = 8, TXPin = 9;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
TinyGPSCustom fixqual(gps, "GPGGA", 6); // $GPGSA sentence, 6th element

void setup()
{
  Serial.begin(9600);
  ss.begin(GPSBaud);
//  OpenLog.begin(9600);
  
  Serial.print(F("Testing TinyGPS++ library v. "));
  Serial.println();
}

void loop()
{
  printDateTime(gps.date, gps.time);
  printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  Serial.print(fixqual.value());
//  OpenLog.print(fixqual.value());


    
  Serial.println(); 
  smartDelay(1000);

  if (millis() > 5000 && gps.charsProcessed() < 10)
    Serial.println(F("No GPS data received: check wiring"));
}

// This custom version of delay() ensures that the gps object
// is being "fed".
static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

static void printFloat(float val, bool valid, int len, int prec)
{
  if (!valid)
  {
    while (len-- > 1)
      Serial.print('*');
    Serial.print(' ');
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1); // . and -
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(' ');
  }
  smartDelay(0);
}

static void printInt(unsigned long val, bool valid, int len)
{
  char sz[32] = "*****************";
  if (valid)
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  smartDelay(0);
}

static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
  if (!d.isValid())
  {
    Serial.print(F("********** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
    Serial.print(sz);
  }
  
  if (!t.isValid())
  {
    Serial.print(F("******** "));
  }
  else
  {
    char sz[32];
    sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
    Serial.print(sz);
  }

  printInt(d.age(), d.isValid(), 5);
  smartDelay(0);
}

static void printStr(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  smartDelay(0);
}

From the SoftwareSerial reference page

The library has the following known limitations:
If using multiple software serial ports, only one can receive data at a time.

and

If your project requires simultaneous data flows, see Paul Stoffregen's AltSoftSerial library. AltSoftSerial overcomes a number of other issues with the core SoftwareSerial, but has it's own limitations. Refer to the AltSoftSerial site for more information.

You can also manage 2 or more soft serial ports using the listen() method but it is not exactly convenient.

Unless your machine is moving very quickly you probably only need to read the GPS once every minute so you should have plenty of time to save the data and then transmit it to the logging device.

...R

Thanks UKHeliBob & Robin2... your comments explain perfectly why I am seeing these errors.

It sounds like AltSoftSerial might be worth exploring. Ultimately, I'd like to use this in my ATmega1284P Bobuino (I know... this chip has 2 hardware serial ports, but I am already using them for something else). Does anyone know if I can use AltSoftSerial with the 1284 so that I could create a "virtual hardware" port for the GPS, and use one softwareserial port for the OpenLog?

Could always add an external dual-USART that you talk with via SPI.
http://www.nxp.com/documents/data_sheet/SC16IS752_SC16IS762.pdf