Go Down

Topic: Software Serial using multiple ports (Read 677 times) previous topic - next topic

dchapma6

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??

MarkT

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?
[ I won't respond to messages, use the forum please ]

dchapma6

Code: [Select]
// 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());
}


dxw00d

Why are you using software serial on a Mega?

dchapma6

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.

dxw00d

#6
Feb 21, 2012, 05:51 pm Last Edit: Feb 21, 2012, 05:54 pm by dxw00d Reason: 1
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:

Code: [Select]
  gps.begin(9600);
  lcd.begin(9600);
  gps.listen();


http://arduino.cc/en/Reference/SoftwareSerialListen

dchapma6

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?

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.


jfhaugh


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 ...

Go Up