NewSoftSerial glitches

I had a FTDI breakout board as a serial receiver.
An arduino board transmitter sends a line(at 9600 baud) to the receiver in 3 parts every 3 seconds.

"T= 19.00 z= 43984 N= 4889 S= 4764 e= -51 w= 5.88....z= -25065 E= 4141 W= 4261 e= 8 w= -3.35.....Aw= 6 Dw= 29"

So the transmit line is high most of the time.
3 times in each line some characters are sent - the last characters are CR LF to start on a new line.

This works fine for weeks with millions of characters received without a single error. (I have other code checking the data)

I then wanted to use an arduino board as the receiver so using digital 2 as the receive line, I used the following code:

#include <NewSoftSerial.h>

NewSoftSerial mySerial(2, 3);

void setup()
{
Serial.begin(9600);
// set the data rate for the NewSoftSerial port
mySerial.begin(9600);
}

void loop() // run over and over again
{
if (mySerial.available()) //send each character as its received
Serial.print((char)mySerial.read());
}

Now at random times I get a received character error. Very random it can be 1 in a 100 or 1 in 1000.

The error always occurs at the end of one of the three groups of characters.

"T= 19.0? z= 43984 N= 4889 S= 4764 e= -51 w= 5.88....z= -25065 E= 4141 W= 4261 e= 8 w= -3.35.....Aw= 6 Dw= 29"

OR

"T= 19.00 z= 43984 N= 4889 S= 4764 e= -51 w= 5.8?....z= -25065 E= 4141 W= 4261 e= 8 w= -3.35.....Aw= 6 Dw= 29"

Note a ? has appeared instead of a numerial which would be the last character in a group.

It sure looked like a timing problem. The interupt is enabled soon after the last character has been received.
Maybe we are catching the stop bit transition back to a high(PCINT18).
This would give an apparent start edge and the data would be all 1's ie 0x7f(? is 0x3f - its close)

I notice that the examples use 4800 baud maybe 9600 is too fast.

I tried a fix. At 9600 baud the individual pulse width is 0.104 ms(1.04 ms for start, 8 data & stop). So I slip in a 5 ms delay this would well and truly get pass the stop bit(I tried smaller delays but no joy):

void loop() // run over and over again
{
if (mySerial.available()) //send each character as its received
{
delay(5); //wait to empty buffer
char t = (char)mySerial.read();
Serial.print(t);
}//end of print character
}

It seems to be working sofar.

As the error is alway ? and q does not occur anywhere else I could replace "?" with "0". I'm not happy with that fix.

I am not happy with my explaination or the fix's.

How about some ideas?

Which version of Newsoftserial are you using?

The version I had is from the zip file:

NewSoftSerial10c

Using the following in the sketch I get 10. Meaning version 10.

Serial.println(NewSoftSerial::library_version());

This morning I downloaded the zip from:

http://arduiniana.org/libraries/newsoftserial/

It's the same as above(version 10). So I must have the latest version.

I ran the program for 12 hours overnight with the 5 ms delay and I got one character error.
So that does not completely solve the problem.

I was asking because that version is vastly improved over other available. The part you can't escape is that you are bit banging serial. When I was working with it, I ended up doing OK with short strings at high speed but I needed to add more delays, similar to what you have done whan my strings increased in size. I was working with S.N.A.P. protocol when I was messing with it.

I'm wondering if you might want to collect the whole string first and then print it to the PC.

Thanks for your idea. It seemed to me that it might work so I tried:

#include <NewSoftSerial.h>

NewSoftSerial mySerial(2, 3);
char data[200]; //my buffer
int i = 0; //counter
boolean endline = false;
boolean startline = false;

void setup()
{
Serial.begin(9600);
// set the data rate for the NewSoftSerial port
mySerial.begin(9600);
}

void loop() // run over and over again
{
if (mySerial.available())
{
char t = (char)mySerial.read(); //get character from serial buffer

if (t == 0x54) //have we started a line - starts with a "T"
startline = true;
if (startline) //we started a line
{
data*=t; //start filling the buffer*

  • if ( t == 0x0A ) // line feed last character*

  • endline = true;*

  • i +=1; //move on to next character*

  • }//end of add to our buffer*

  • if (endline)*

  • {*

  • int j = 0; //counter*

  • for ( j=0; j < i; j++)*

  • Serial.print(data[j]);*

  • endline = false;*

  • startline = false;*

  • i = 0; //reset counter and line flags*

  • }//end of send line to PC*
    }//end of data available
    }//end of loop
    [/quote]
    It seems to be working- without any added delays.
    I'll run it for a few days and get back with the hard results.

I ran the new receiver program for 24 hours - no errors at all.

The program I'm using to look at the data plots the data values on the pc screen.
I can detect any error in the data visually.

The program also saves all the data in a text file(size is over 1 Mbyte).
Just to be sure I did a search for "?".

I could not believe it. There are just as many "?" as in the first program without the delay.
They appear at random and at the end of character blocks in the line as before.

But there is a small difference.

T= 21.4? first version -send each character as it comes

T= 21.46? second version -send a line

The send line version does not generate a error in my display program.
You don't even know that it has occurred.

I checked back on the many meg's of the data received using the FTDI. It's perfect no sign of any odd changes.

This change is trying to tell me something very profound about NewSoftSerial's problem.
Unfortunately the tiny starfish brain cannot work it out.

At the moment the new program does what I want it to do so I will leave it at that.
I will make a note in the program about the odd "?" showing up.

I will be watchful when using NewSoftSerial in the future.

When I can(next transmitter upgrade) I will try using 4800 baud - it may be that 9600 is to fast or that having both at 9600 causes conflict.

Thanks for your time.

Why don't you use the UART for the incoming data (thereby gaining the benefit of the buffer) and use the SoftSerial for the output where the buffering is not important?

Thanks for the idea.

But, I'm using a Arduino 2009 board and USART0 uses PD0(digital 0) and PD1(digital 1) these are hardwired to the FTDI chip.
The FTDI chip then interfaces to the pc via the usb connection. It simulates a serial port. Mine is COM8.

I suppose you could use a ATmega328 with a FTDI breakout.
Program using bootstrap on PD0 and PD1 then change around to use PD2 and PD3 with newsoftserial to talk to the FTDI and onto the PC. Leaves USART0(and the arduino 128 byte buffer) free for
reception from the transmitter.

Maybe I have misunderstood what you are intending?

Yeah, having only 1 uart in the AVR chip is sort of limiting.

The only GUESS I can make about why you still have some non-ascii printable "junk" in your stream is that you are likely sending to the PC "while" you are receiving on the pins with no hardware uart. While I'm no expert, the reason I recommended printing a line at a time was because it would reduce the number of times Serial.Print() would interrupt your NewSoftSerial routines.

Is there way to halt (flow control) your incoming stream?

While I'm no expert..

But you could just skim through the code of HardwareSerial and SoftwareSerial, and then you would no longer have to rely upon your guesswork.. The code is not so long....

I suppose you could use a ATmega328 with a FTDI breakout.
Program using bootstrap on PD0 and PD1 then change around to use PD2 and PD3 with newsoftserial to talk to the FTDI and onto the PC. Leaves USART0(and the arduino 128 byte buffer) free for reception from the transmitter.

Sorry. I use Veroboard and breadboard prototypes exclusively and forgot about the hardwired FTDI on the Arduino. If you didn't mind springing for a FTDI breakout board/cable like those from Modern Devices or Sparkfun, then you could easily do as you have outlined above. I think the UART input buffer will solve your problems.

pwillard thanks.

I have no control over the transmitter it sends data in groups of 3 every 3 seconds or so.

It is an ultrasonic wind sensor:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1283073954

I did try one more thing. I loaded a full line into the NewSoftSerial buffer before then outputing that line with Serial.Print().
I had to increase the NewSoftSerial buffer:

#define _NewSS_MAX_RX_BUFF 200 // RX buffer size

Then the sketch:

#include <NewSoftSerial.h>

NewSoftSerial mySerial(2, 3);
char data[200]; //my print buffer-line will always be shorter than 200
int i = 0; //counter

void setup()
{
Serial.begin(9600);
// set the data rate for the NewSoftSerial port
mySerial.begin(9600);
}

void loop() // run over and over again
{
if (mySerial.available() > 130) //have we got at least one line
{
i = 0;
while (mySerial.available())
{
char t = (char)mySerial.read(); //get character from serial buffer
data*=t; //start filling the buffer*

  • i +=1; //move on to next character*

  • if ( t == 0x0A) //if LF then we have a full line*

  • break;*

  • }//empty the NewSoftSerial copy to my buffer*

  • int j = 0; //counter*

  • for ( j=0; j < i; j++)*

  • Serial.print(data[j]); //send the print buffer to the PC*
    }//end of data available
    }//end of loop
    [/quote]
    This gave no change in operation just as many "?" show up.
    lemming thanks.
    I's easier for me to test things with the arduino board.
    Eventually the arduino board will be replace by a standalone.
    Then I will definately look at using USART0.