Difficulty Reading Serial Data PROBLEM SOLVED!

I'm trying to read serial data from a GPS. That effort has devolved into just trying to do a serial echo test, and the serial echo tests have been unsuccessful.

I can see the serial data stream on my oscilloscope coming from the GPS, but the Arduino can't read the data. After changing GPS units and Arduino (Uno) units, I tried something much simpler: just a serial echo.

I've read many posts about problems with SoftwareSerial and with AltSoftwareSerial, but none of them have helped me solve my problem. Both the SoftwareSerial and the AltSoftwareSerial seem to produce garbage characters coming in to the Arduino. I've checked baud rates and delay times, and I still get garbage. I'll show you the actual readings appended to my code sample later in this plaintive cry for help.

The latest iteration is using the AltSoftwareSerial echo test code available online.
Arduino Uno, Pin 0 (hardware Rx) jumpered to Pin 9; Pin 1 (hardware Tx).

Here's the code, with the result appended in a Comment:

// NOTE: This AltSoftSerial REQUIRES that Pin 9 be the Tx Pin and Pin 8 be the Rx Pin
// Connect Arduino Uno Pin 0 (Rx) to Pin 9 (Tx), and connect Arduino Uno Pin 1 (Tx) to Pin 8 (Rx)

#include <AltSoftSerial.h>

AltSoftSerial altSerial;

void setup() {
  Serial.begin(9600);
  Serial.println("AltSoftSerial Test Begin");
  altSerial.begin(9600);
  delay(100);
  altSerial.println("Hello World");
}

void loop() {
  char c;

  if (Serial.available()) {
    c = Serial.read();
    altSerial.print(c);
  }
  delay(200
  );  //This makes the looping go very slowly
  if (altSerial.available()) {
    c = altSerial.read();
    Serial.print(c);
  }
}
// RESULTS:
/*
AltSoftSerial Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

So, looking online, I found a second echo program that I tried, and it gives an error because the data received doesn't match the data sent - again, I append the output from the Serial Monitor as a Comment section at the end:

//
// Transmit data with Serial1 and try to receive
// it with AltSoftSerial.  You must connect a wire
// from Serial1 TX to AltSoftSerial RX.

#include <AltSoftSerial.h>

AltSoftSerial altser;
const int mybaud = 9600;

// Board            Serial1 TX   AltSoftSerial RX
// -----            ----------   ----------------
// Teensy 3.x            1              20
// Teensy 2.0            8 (D3)         10 (C7)
// Teensy++ 2.0          3 (D3)          4 (D4)
// Arduino Leonardo      1              13
// Arduino Mega         18              48

// Serial1 on AVR @ 16 MHz minimum baud is 245
// Serial1 on Teensy 3.2 @ 96 MHz minimum baud is 733

byte sentbyte;
unsigned long prevmillis;
byte testbyte=0xF0;

void setup() {
  delay(200);
  Serial.begin(9600);
  while (!Serial) ;  // wait for Arduino Serial Monitor
  Serial.begin(mybaud); // connect a wire from TX1
  altser.begin(mybaud);   // to AltSoftSerial RX
  Serial.println("AltSoftSerial Receive Test");
  prevmillis = millis();
}

void loop() {
  // transmit a test byte on Serial
  if (millis() - prevmillis > 250) {
    sentbyte = testbyte++;
    Serial.write(sentbyte);
    prevmillis = millis();
  }
  // attempt to receive it by AltSoftSerial
  if (altser.available() > 0) {
    byte b = altser.read();
    Serial.println(b);
    if (b != sentbyte) Serial.println("***** ERROR *****");
    
while(1) { } // This stops the program if the error occurs.
  }
}
/* RESULTS:

I know I have some very fundamental problem, and I appreciate your patience and indulgence and any insights you can provide. I'm definitely preparing myself to feel stupid. Thanks!

Here, the program will stop no matter what is received:

    if (b != sentbyte) Serial.println("***** ERROR *****");
    
while(1) { } // This stops the program if the error occurs.

You need

    if (b != sentbyte) {
 Serial.println("***** ERROR *****");
while(1) { } 
}// This stops the program if the error occurs.

Thank you, aarg. I actually had that in my program, but I didn't copy and paste the ending correctly. I'll try to do that here:

//
// Transmit data with Serial1 and try to receive
// it with AltSoftSerial.  You must connect a wire
// from Serial1 TX to AltSoftSerial RX.

#include <AltSoftSerial.h>

AltSoftSerial altser;
const int mybaud = 9600;

// Board            Serial1 TX   AltSoftSerial RX
// -----            ----------   ----------------
// Teensy 3.x            1              20
// Teensy 2.0            8 (D3)         10 (C7)
// Teensy++ 2.0          3 (D3)          4 (D4)
// Arduino Leonardo      1              13
// Arduino Mega         18              48

// Serial1 on AVR @ 16 MHz minimum baud is 245
// Serial1 on Teensy 3.2 @ 96 MHz minimum baud is 733

byte sentbyte;
unsigned long prevmillis;
byte testbyte=0xF0;

void setup() {
  delay(200);
  Serial.begin(9600);
  while (!Serial) ;  // wait for Arduino Serial Monitor
  Serial.begin(mybaud); // connect a wire from TX1
  altser.begin(mybaud);   // to AltSoftSerial RX
  Serial.println("AltSoftSerial Receive Test");
  prevmillis = millis();
}

void loop() {
  // transmit a test byte on Serial
  if (millis() - prevmillis > 250) {
    sentbyte = testbyte++;
    Serial.write(sentbyte);
    prevmillis = millis();
  }
  // attempt to receive it by AltSoftSerial
  if (altser.available() > 0) {
    byte b = altser.read();
    Serial.println(b);
    
    if (b != sentbyte) {
 Serial.println("***** ERROR *****");
while(1) { } //This stops the program if an error occurs
    }
  }
}

    
/* RESULTS:
AltSoftSerial Receive Test

65

***** ERROR *****

*/

So now I still have the problem of getting garbage characters, whether from the GPS or from the echo test. Anyone have any wise guidance for me? Thanks!

For your test: Are you getting garbled characters that cause the program to halt and show "***** ERROR *****" or are they just printing weird characters?

I ask the latter because you start with:

byte testbyte=0xF0;

You send this and then, when received, print it:

        byte b = altser.read();
        Serial.println(b);

0xF0, 0xF1 etc are just going to print nonsense to the serial monitor.

If you start at 0x20 and print up to 0x7E and then go back to 0x20 do you still see garbled chars?

What does the datasheet of the GPS-module say about the serial parameters?

If your prgram is not adjusted to the exact same parameters as the GPS-module is sending data you receive garbage because your program does process the bit-stream in the wrong way

Do you have a an extra TTL-to-USB-adapter that could be connected directly to your GPS-module?
This would enable to read-in the serial data directlyto your computer. To do so I recommend using a serial terminal program that can adjust all parameters

best regards Stefan

Thanks to all who have offered their wisdom. Much appreciated - great community!
Blackfin: The program prints 65, then apparently gets a garbled message that causes it to stop with the ERROR message. If I don't stop the loop, it just continues to print ERROR, line after line. Similarly, in first echo test program, I get repeated partially garbled text lines after the first message:
// RESULTS:
/*
AltSoftSerial Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin

±ÑM½™ÑM•É¥…±�Test Begin
...etc.

StefanL38 - While my ultimate aim is to parse the GPS data stream, I have had to regress to just trying to get clear ASCII text in simple loop tests, so my GPS units are not in my current test setup at all. I'm fairly confident I can handle the GPS data stream if I can just get the Arduino Uno to interpret an ASCII character stream properly.

I thought about possible problems with number of stop bits, parity, etc., but those seem pretty unlikely. I think the default is 8N1 (i.e., 8 data bits, no parity, one stop bit). Maybe it's a timing issue of some sort?

Any help would be greatly appreciated. Thanks!

Excuse me, but if you use the echo mode, anything you print on Serial will end in the AltSoft serial input buffer.

If for example you print in your setup() function

Serial.println("AltSoftSerial Receive Test");

then the AltSoft serial buffer will contain the string

"AltSoftSerial Receive Test"

and the first time you will use AltSoft, you will read the first character, e.g. 'A', ASCII code 65.

So your AltSoft serial works.

OK, I made the problem MUCH simpler. I send one character out on the hardware serial port (Pin 1) and read it back on the AltSoftwareSerial port (Pin 9). It gets garbled.

// NOTE: This AltSoftSerial REQUIRES that Pin 9 be the Tx Pin and Pin 8 be the Rx Pin
// Connect Arduino Uno Pin 0 (Rx) to Pin 9 (Tx), and connect Arduino Uno Pin 1 (Tx) to Pin 8 (Rx)

#include <AltSoftSerial.h>

AltSoftSerial altSerial;

void setup() 
{
  Serial.begin(9600);
  Serial.println("1");
  altSerial.begin(9600);
}

void loop() 
{
  char c;
  
  if (altSerial.available()) 
  {
    delay(1000);  //This makes the looping go slowly
    c = altSerial.read();
    Serial.print(c);
  }
}

RESULTS as shown in the Serial Monitor:
1
LCáLCáLCáLCáLCáLCáLCáLCáLCáLCáLCáLCáL....(ad infinitum)

silkrip:
OK, I made the problem MUCH simpler. I send one character out on the hardware serial port (Pin 1) and read it back on the AltSoftwareSerial port (Pin 9). It gets garbled.

// NOTE: This AltSoftSerial REQUIRES that Pin 9 be the Tx Pin and Pin 8 be the Rx Pin

// Connect Arduino Uno Pin 0 (Rx) to Pin 9 (Tx), and connect Arduino Uno Pin 1 (Tx) to Pin 8 (Rx)

#include <AltSoftSerial.h>

AltSoftSerial altSerial;

void setup()
{
 Serial.begin(9600);
 Serial.println("1");
 altSerial.begin(9600);
}

void loop()
{
 char c;
 
 if (altSerial.available())
 {
   delay(1000);  //This makes the looping go slowly
   c = altSerial.read();
   Serial.print(c);
 }
}



RESULTS as shown in the Serial Monitor:
1
LCáLCáLCáLCáLCáLCáLCáLCáLCáLCáLCáLCáL....(ad infinitum)

In what appears at first glance as a potential "weakness" in the AltSoftSerial library, try changing the order of your setup:

void setup()
{
    Serial.begin(9600);    
    altSerial.begin(9600);
    Serial.println("1");    
  
}//setup

I was able to replicate your error and when I put the call to altSerial.begin(9600) before the first character is sent out the program worked fine.

The weakness I mention might exist is that the library may not have a timeout or sync feature; if pin 8 is transitioning when begin() is called, it's like the library gets misaligned and has no mechanism (e.g. a timeout) to get back in sync again.

Even a small delay to let any sent characters to complete before calling begin() works:

void setup()
{
    Serial.begin(9600);    
    Serial.println("1");    
    delay(50);
    altSerial.begin(9600);
  
}//setup

In your setup() function, you initialize altSerial after you called Serial.println(), you should initialize altSerial before;

plus Serial.println() will add a newline (maybe a carriage return too), so will send 2 (or 3) char to altSerial, use Serial.print instead to send only the char '1'

void setup()
{
Serial.begin(9600);
altSerial.begin(9600);

Serial.print("1");
}

now your code will print ad infinitum '1' because after you read the char with

c = altSerial.read()

you reinsert it in the altSerial input buffer calling

Serial.print(c)

Wow, you guys are good! :slight_smile:

Many thanks to Blackfin and vic0617.

Now I'll try to get more adventurous and hook up the GPS.

The GPS data comes in perfectly. :slight_smile: