Issue with SoftwareSerial library and repeated input characters? [SOLVED]

Hello,

I'm developing a complex program on the Leonardo, and seem to have come up against a bug in one of the libraries I'm using.

The problem stems from SoftwareSerial (I think), where repeated character input is not being read in correctly for my app.

I have made a small example program which seems to have the same problem. You enter in a line of text to a buffer into D8 (through a MAX232 or similar) and after pressing carriage return, it echoes this buffer to the normal Serial port viewable through the IDE. I'm using 2400 baud for both ports.

If I type more than two repeated characters, then the third and some subsequent repeats don't get decoded properly.

I'm using Arduino 1.0.4 on Windows, and the headerless version of the Leonardo board.

Can anyone else replicate this problem?

Yours,

Ross 7WED

#include <SoftwareSerial.h>

SoftwareSerial mySerial(8,9); // RX, TX

void setup() {
  mySerial.begin(2400);
  Serial.begin(2400);
}
  
char buffer[128];
byte pointer = 0;
byte index = 0;
  
void loop() {
  if (mySerial.available()) {
    buffer[pointer] = mySerial.read();
    if (buffer[pointer] == char(0x0A)) { // we are ready to process the data after receiving a CR signal
      for (index=0; index < pointer; index++) Serial.print(buffer[index]);
      pointer = 0;
      index = 0;
    }
    pointer++;
  }
}
    buffer[pointer] = mySerial.read();

Does it matter that you might be writing off the end of the array?

    if (buffer[pointer] == char(0x0A)) { // we are ready to process the data after receiving a CR signal

Code like this:

    if (buffer[pointer] == '\n')

doesn't need a comment. It's obvious what the code is doing.

The Leonardo has two serial ports - the TX/RX one and the USB one. Do you need SoftwareSerial?

The serial port on the Leonardo (pin 0 and 1) is not used, and you can use it to communicate with other hardware as PaulS wrote.
The serial monitor and the sketch upload uses a software serial port via the usb.

The SoftwareSerial library has some problems.
That is why there is an alternative, AltSoftSerial Library, for an extra serial port

But also your sketch causes a problem.
If 0x0A is detected (which is LineFeed), the pointer is set to 0. But right after that, the pointer is incremented. So the buffer is filled from [ 1 ], but printed from [ 0 ].

Thanks for the feedback so far. And for pointing out the errors in my program... yes, I changed the spec and turned CR into LF in the code, and also as I was copying and pasting my example from a larger program, I didn't notice the missing

} else

lines of code. As for the buffer running over, my program will only see 52 characters between LFs, so even a garbled one will get cleaned up in the next turn. [I could fix this, but only have six bytes free in the Leonardo's memory after compile.]

However, I'm still stuck with the repeated character issue, so I'll try the AltSoftSerial alternative and report if it works. It's worth pointing out that I've been experiencing this problem even when typing one letter at a time on a terminal, at 2400 baud with long gaps in between each input character, so it's not as if the SoftwareSerial routine is being slammed with data faster than it should be able to handle...

My full program contains the following headers

#include <Wire.h>
#include "RTClib.h"
#include <SD.h>
#include <SoftwareSerial.h>

and its purpose is to take incoming data from the SoftwareSerial port from an industrial machine, and format it for output to a POS printer on TX pin 1, with various formatting and paper cut commands. Unfortunately, I can't use the RX pin 0, as this is a PC terminal interface for changing parameters, and I can't use the USB serial port, since there will be no PC attached to this project. That's why I needed to use SoftwareSerial in the first place.

Somewhere, I have an Uno board and a Freeduino Duemilanove, and I'll dig them out tomorrow and try the same code on this, to see if the SoftwareSerial library struggles here, too.

So, I was really wondering whether there is a known fault in the SoftwareSerial library, and if so, if there were alternatives. So, I'm particularly interested in the AltSoftSerial library, and will give this a try tomorrow too.

Cheers,

Ross

That starts me thinking... Is it possible to reorganize the serial ports ?
But I don't know all the baudrates, so I'm not sure if some can be combined.

Is that terminal reliable ? Perhaps the SoftwareSerial library is more reliable than the terminal. Could you measure the baudrate ? Some old devices create the baudrate clock from the X-tal of the microcontroller. That could result into a slighty different baudrate.

Are all the serial signals good 5V logic level signals and not accidently a 3.3V level signal ?

Incoming data from the industrial machine is important. Using the hardware buffer of the serial port Serial1 seems a logical choice.

If you use a Mega board, you have 4 hardware serial ports.

I've managed to solve this, but I don't really know how or why...

Since I'm developing on my desk, I was using HyperTerminal (comes with Windows XP) as my terminal emulator, to pretend to be the industrial machine my Arduino will end up connected to.

I was using a USB -> Serial FTDI chipset adapter, going into my SoftwareSerial input pin, through a MAX232 chip. When I saw the repeated character problem, I then tried an Arduino USB2SERIAL board, with the outputs going straight into the TTL Arduino pins (no MAX232). None of this made any difference. I also tried using several different input pins on the Arduino as SoftwareSerial to check if this was pin-related, to no effect. Tried using a different Leonardo and an Uno, but this didn't change things either. When sending to D0 on the Arduino (which I am already using somewhere else in my full program) repeated characters come out fine. That's why I suspected SoftwareSerial.

In desperation, I tried a different terminal emulator (PuTTY). This works perfectly, and there seems to be no problem at all sending data through the same hardware, and the same code on the board.

I'm wondering if there's a timing issue in HyperTerminal which occasionally rears its ugly head, or if its timing is screwed up by using a modern CPU, or selecting a slow baudrate.

Thanks for all those who submitted comments,

Ross

I think it is your sketch.
The HyperTerminal would perhaps add CR LF, and puTTY perhaps only CR.

If you want to be sure if something is wrong with HyperTerminal, you can make a test sketch that shows the problem. So we could try it to see if we have the same result.

The empirical program:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(8,9);

void setup() {
  Serial.begin(2400);
  mySerial.begin(2400);
}

void loop() {
  if (mySerial.available()) Serial.write((char)mySerial.read());
}

exhibits the same behaviour using HyperTerminal / SoftwareSerial (I tried several input pins on both Uno / Leonardo), but is fine with a hardware serial port.

I tried using a Win7 machine (with hyperterm.exe / hyperterm.dll copied from WinXP) as well as a standard Windows XP machine.

Using PuTTY, there is no problem.

If the same character is repeated three times, the third character is the ASCII value +128, and then subsequent characters alternate between correct and +128.

I tried to test it in Windows XP, but I was not able to install a driver for any of the usb-to-serial adapters I have. And Windows XP crashed, so something is wrong with it. Sorry, I can't try HyperTherminal. I use linux.

I have some good news and bad news.

First of all, it was not your sketch. Sorry for that.

You have done some extensive testing.
I ran HyperTerminal and got that error right away with the second character. I tried other pins, some delays, but nothing stopped receiving the wrong data.
I can't tell what the problem is, but the SoftwareSerial library doesn't receive the data by HyperTerm correctly.

This is the post I created for the problem with the SoftwareSerial library, http://arduino.cc/forum/index.php/topic,163082.0.html