Use serial and NewSoftSerial together

I've been pulling my hair out for the past few days trying to get my XBees and GPS to play nice together. I have them connected both with their respective shields from SparkFun to my Arduino Uno. I want to run the XBee off uart, and the GPS off digital pins 2 and 3 using NewSoftSerial. But, as soon as I turn on the NewSoftSerial, I start getting interference and packet losses on the rx pin. However, the tx seems to work fine because I have my Arduino send some text, and that always comes through fine.

Here is my code:

NewSoftSerial gpsSerial(2,3);
char inData[5];
TinyGPS gps;
PWMServo servo; //have to use the servo library from 0016 otherwise NewSoftSerial messes up the servo

void setup() {
  servo.attach(10);
  servo.write(90);
  Serial.begin(57600);
  gpsSerial.begin(4800); //this seems to be causing the problem
  Serial.print("Hello there!");
}

void loop() {
  if(Serial.available() >=5) { //every command I send is 5 characters long
    for(int i=0; i < 5; i++) {
      inData[i] = Serial.read();
    }
  }
if(strcmp(inData, "right")==0) { //right
    servo.write(135);
  }
  else if(strcmp(inData, "lleft")==0) { //left
    servo.write(40); 
  }
 if(strcmp(inData, "strai")==0) { //straight
    servo.write(90);
  }
}

Interestingly enough, this setup works fine if I connect over USB.

Thanks everyone!

Interestingly enough, this setup works fine if I connect over USB.

As opposed to how?

How are you powering this whole collection of parts - GPS, XBee, servo?

The strcmp function expects NULL terminated strings. Yours are not NULL terminated. You don't even have room add the NULL.

Okay, thanks. How do NULL terminate the string?

If I don't connect over USB, I am powering the setup using a 9V battery connected to the bullet connector on the Arduino and (attempting) to communicate using the XBee. (I have a SparkFun USB explorer board attached to my computer).

How do NULL terminate the string?

Try

 for(int i=0; i < 5; i++) {
      inData[i] = Serial.read();
    }
   inData[i] = '\0';   // terminate the string

Also, if you have 5 chars you need a 6-byte array to allow for the NULL terminator.

char inData[6];

Also, is a 9v battery up to powering all that, some Xbees draw 250mA by themselves.


Rob

for(int i=0; i < 5; i++) {

inData[i] = Serial.read();
   }
  inData[i] = '\0';   // terminate the string

Okay, I did what you said, but if I do this, nothing works. It's like inData is cleared before I can do anything else.

If I put,

if(Serial.available() >0) {
    for(int i=0; i<5; i++) {
      inData[i] = Serial.read(); 
    }
      inData[5] = '\0';
  Serial.println(inData);
  }

I get junk output if I echo what is read in. For example, if I send the command "right," I can get r???? or ight? or ri??? or any other combination of something that resembles "right" but replaces some letter with ?. This happens on both the XBee and USB.

The last code you posted won't work because you don't wait for 5 chars, so you get the first char then overwrite the array with 0s.

Also, my example did something similar because I had the

inData[i] = '\0';

in the wrong place. Try this.

NewSoftSerial gpsSerial(2,3);
char inData[5];
TinyGPS gps;
PWMServo servo; //have to use the servo library from 0016 otherwise NewSoftSerial messes up the servo

void setup() {
  servo.attach(10);
  servo.write(90);
  Serial.begin(57600);
  gpsSerial.begin(4800); //this seems to be causing the problem
  Serial.print("Hello there!");
}

void loop() {
  if(Serial.available() >=5) { //every command I send is 5 characters long
    for(int i=0; i < 5; i++) {
          inData[i] = Serial.read();
    }
    inData[i] = '\0';   // terminate the string
    
    if(strcmp(inData, "right")==0) { //right
        servo.write(135);
      }
      else if(strcmp(inData, "lleft")==0) { //left
        servo.write(40); 
      }
     if(strcmp(inData, "strai")==0) { //straight
        servo.write(90);
    }
  }

}

Plus I've moved the servo stuff into the "if(Serial.available() >=5)" code block, there's no point running it until there are 5 chars to test.


Rob

new softserial works pretty good for me. I have a GPS and a serial display, but I have them both connected to digital pins so I can use the usb port to debug. The thing I had to learn (the hard way) is that new softserial can lose characters if you don't attend to it often enough. Also it is interrupt driven, but I haven't gone through the source to understand this completely. Your problem matches the problems I had at first before I realized that you have to check it a lot and quickly or the characters get lost. So what I had to do was only watch the GPS until I got the sentence from it that I needed then go look at the other port for what I needed there. You'll notice that the GPS port will lose data while you're watching anything else. Works pretty well that way.

try dropping the serial baud rate to match the gps rate, i.e. Serial.begin(4800); For a different project than yours, that solved the gibberish for me.