Software Serial using multiple ports

I have a Parallax GPS module and a Sparkfun serial-enabled LCD. When I have them both running, I must "begin(9600)" the LCD first or else the GPS doesn't talk. I have attached the code I used to test it. This version works. Why does it make a difference??

sketch_GPS_LCD_Test.ino (1.61 KB)

Please use the # button to post code so we can read it inline - much more likely to get people replying that way. Which Arduino board is this on?

// test for multiple Software Serial Ports - GPS and LCD

#include <SoftwareSerial.h>

#define r1c1  0x00    //row 1, col 1
#define  lcd_Tx_Pin  22      // transmit to LCD on pin 22
#define  null_pin    13      // Receive not used
#define  gps_Rx    11        // GPS Receive on 11
#define  gps_Tx    10        // GPS Tx on 10

SoftwareSerial gps = SoftwareSerial(gps_Rx, gps_Tx);      // Rx=11, Tx=10
SoftwareSerial lcd = SoftwareSerial(null_pin, lcd_Tx_Pin);

#define GetAlt  0x07
#define lcdcmd  0xFE
#define curpos  0x80
#define clrLCD  0x01

long  timeout = 1000;

void setup()
  {
    pinMode(gps_Rx, INPUT);
    pinMode(null_pin, INPUT);
    pinMode(gps_Tx, OUTPUT);
    pinMode(lcd_Tx_Pin, OUTPUT);
    Serial.begin(9600);
    lcd.begin(9600);              //reversing this and next line causes
    gps.begin(9600);              // GPS not to work??
           
  }
  
  void loop()
  {
    delay(5000);
    if(sendGps(GetAlt, 2) == 2)
    {
    long altD = gps.read()<<8;
    altD += gps.read();
    long altF =altD/10;
    Serial.print("\n Alt = ");
    Serial.print(altF);
    Serial.println(" meters");
    lcd_cmd(clrLCD);
    lcd_cmd(curpos|r1c1);
    lcd.print(altF);
    lcd.print(" Meters");
    }
    else
    {
    Serial.println(" no GPS ");
    lcd.print("  no GPS ");
    }
  }
  
  void  lcd_cmd(int command)
  {
    lcd.write(lcdcmd);
    lcd.write(command);
  }

  
  byte sendGps (byte cmd, byte numBytes) 
{
  gps.print("!GPS");  
  gps.write(cmd);
  unsigned long oldMillis = millis();
  while(gps.available() < numBytes) 
  {
    if (millis() - oldMillis > timeout)
      return (0);
  }
  return(gps.available());
}

Its on the Mega 2560

Why are you using software serial on a Mega?

Because I want to learn how to use that feature. I wrote it originally to use the extra Serial Ports the Mega has and that worked. I just wanted to know if I overlooked something in the setup.

It's probably because only one 'listener' is active at a time. If you do the lcd.begin() second, it will make that the active 'listener' and anything sent to gps will be discarded. To test the theory, you could try:

   gps.begin(9600);
   lcd.begin(9600);
   gps.listen();

You are right! That worked. If you had an application that required monitoring multiple serial lines for input, could you not do that? Could you commutate the "listener" through the list of lines watching for input?

Yes, you could do that. The problem is that the non-listening ports are not buffered, so anything sent to a port while it isn't listening is lost.

OK - Thanks for your help!

dxw00d:
Yes, you could do that. The problem is that the non-listening ports are not buffered, so anything sent to a port while it isn't listening is lost.

Keep in mind that's only for software serial ports. The hardware ports (UARTs) don't have that limitation, so it's back to using the hardware serial ports on the ATmega 2560 ...