Reading From NewSoftSerial

I have two Arduino devices, and am using NewSoftSerial to communicate between them. The problem is that whenever I read data with NewSoftSerial's read, the data is corrupted. I found a pattern by repeatedly sending byte '240'. What I receive:

Decimal Binary
240 1111 0000
248 1111 1000
120 1111 1000
124 0111 1100
60 0011 1100
62 0011 1110
30 0001 1110
31 0001 1111
15 0000 1111

NewSoftSerial seems to be losing its place in the stream of bits. At each byte the offset between where it thinks the start of a byte is, and where the start actually is, gets worse and worse. In my example, it's off by 4 bits at the end. Here's how I'm reading the data:

while (!finished)
{
if (softLink.available() > 0)
{
touchBuffer[touchIndex] = softLink.read();//data corrupted here
touchIndex++;

if (touchIndex >= TOUCH_BUFFER_SIZE)
finished = true;
}//if available()

else if (digitalRead(LS_TOUCH_PIN) == LOW)
finished = true;
}//while !finished

What to do?

What is the baud rate you are using? The soft side of the new soft serial library might be affecting the max baud rate. Also what arduino board are you using? Either one of them using internal oscillator?

Post all the code for both sides - sender and receiver. The problem could be at either end.

Pete

Are you using parity and/or stop bits? The purpose of these is to maintain sync with the bitstream and detect bit errors. You can get serial comms to work without them under ideal conditions, but when conditions aren't ideal you'll find them very useful.

I'm using 38400 baud. The receiving board is an Arduino Nano, and the sending board is a TouchSlide Shield. It describes itself as an "Atmel Butterfly Development Board".

I should mention that the sender (Touchshield) is using the built-in UART, only the receiver (Nano) is using NewSoftSerial. However, the Nano can send data to the Touchshield continually for the better part of an hour with not even one bit out of place. It's the reverse that's causing me headaches.

The sender code looks like this:

//Stores touch data received from the touchscreen
char touchBuffer[TOUCH_BUFFER_SIZE];

//The index of the current element in touchBuffer to write to
int touchIndex = 0;

...

for (touchIndex = 0; touchIndex < 10; touchIndex++)
touchBuffer[touchIndex] = 240;

...

for (int i = 0; i < touchIndex; i++)
Serial.print(touchBuffer*);//there's no write in this version of Arduino*

  • Serial.flush();*
  • touchIndex = 0;*
  • SET_PIN12(0);*
    [/font]

Are you using parity and/or stop bits?

Erm, no. Is this something I should add in manually, or is it built in to the Arduino API?

I was unable to use that baud rate on my duemilanove boards so consider dropping the rate. If you are not constantly using that bandwidth, you face two things: data corruption (software delay and possible line noise) and receiving buffer overflow (cause you transferred too many bytes before the receiver finds time to process). Try 19200 instead.

I'm afraid I'm stuck using 38400 - I need to send images to the touchscreen as fast as I can. Even at 38400 baud, I'm still only sending 1 image every 4 seconds. I also found that 38400 was too high, but I only send at 19200 over the link. Since I'm using software serial, this results in a speedup for me, since the Nano is only hung up doing blocking sends for half as long.

I'd rather monitor the offset in software, and compensate for it, than reduce the baud rate any lower. The Touchshield only has a small amount of data to send, and I could always use a series of four zero bits to indicate a single 0, and four 1 bits to indicate a single 1.

Let me try just once more because "The sender code looks like this" doesn't help at all, in fact the little bit of code you posted suggests that there is very likely to be a bug somewhere there.

So, - Post all the code for both sides.

Pete

The code is too long to post - "The message exceeds the maximum allowed length (9500 characters).".

I've uploaded it here:

www.junction404.com/Receiver.c
www.junction404.com/Sender.c

I must say, if you're willing to go through all that to help a stranger, then I tip my hat to you.

The way that you describe the problem with the bit shifting of the input character doesn't look "possible" under normal conditions. However, with a software UART you can always have a problem that it can't keep up at higher transmission rates. If it is having trouble keeping up, then the sequence that you post is precisely the kind of thing that will occur.
Can you configure the sending end to transmit two stop bits? - i.e. 8-n-2 ? The extra stop bit would give the receiver software time to catch up.

Pete

Serial.print(touchBuffer);//there's no write in this version of Arduino

Which version is that? I've used all the versions from 15 on up and they all have Serial.write().

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

The char datatype is a signed type, meaning that it encodes numbers from -128 to 127. For an unsigned, one-byte (8 bit) data type, use the byte data type.

240 is NOT between -128 and 127.

for (int i = 0; i < touchIndex; i++)
                Serial.print(touchBuffer);//there's no write in this version of Arduino
            
            Serial.flush();

Why do a flush? Do you want to throw the data away?

And can you use the [ code ] tags please? Half of your post is in italics because you didn't.

The code is too long to post - "The message exceeds the maximum allowed length (9500 characters).".

Receiver.c is 5432 bytes. You could post that.

iMac5:Downloads nick$ ls -l Receiver.c 
-rw-r--r--  1 nick  staff  5432 13 Jan 15:03 Receiver.c

It isn't clear which version you are using exactly, but the SoftwareSerial I have turns interrupts off during a write (because it has to get the timing right). I'm not particularly surprised that, with a fast baud rate, and doing other serial comms at the same time, that data is being corrupted.

You could try swapping them (make the hardware one the software one and vice versa).

Why do a flush? Do you want to throw the data away?

Ehhh... good point. The manual says: "Waits for the transmission of outgoing serial data to complete. (Prior to Arduino 1.0, this instead removed any buffered incoming serial data.) " I'm using Arduino version 0018, which I assume means 1.8 though... so I would expect to see the newer behaviour.

Which version is that? I've used all the versions from 15 on up and they all have Serial.write().

Well, here's what I get when I try it:

[apply] /tmp/build2430831250169278482.tmp/tmp/touchslide/touchslide.pde: In function 'void sendTouches()':
[apply] /tmp/build2430831250169278482.tmp/tmp/touchslide/touchslide.pde:165: error: 'class HardwareSerial' has no member named 'write'

It's version 0018, but is a custom version for the TouchSlide Shield called 'Antipasto'.

Can you configure the sending end to transmit two stop bits? - i.e. 8-n-2 ?

I'm not sure how to approach this using Arduino's Serial library... however, after sleeping on it I now feel that the baud rate is the issue here.

I'm going to try a design like so:

Main Link (38400 baud) Nano (NewSoftSerial) <-----> TouchSlide (Hardware UART)
-Nano endlessly streams drawing commands to the TouchSlide.
-TouchSlide sends a few bytes to the nano when it's ready to transmit (these will be garbled as in my first post)

Secondary Link (9600 baud) Nano (NewSoftSerial) <-----> TouchSlide (SoftSerial)
-TouchSlide sends touch data to the Nano
-The Nano stops sending on the Main Link whenever it receives any data there, and switches the NewSoftSerial to the Secondary Link
-The Nano resumes sending on the Main Link when the transmission ends.

My only concern is that I'm not sure the Main Link is full-duplex, in which case it could take a while for the Nano to get the notification to switch to the secondary link.

I'm using Arduino version 0018, which I assume means 1.8 though

Version 1.0 is the first 'production' release. The 00nn versions are betas (or pre-production, or something), the last of which was 0023.