Issues with SoftwareSerial

Hi,

I’ve been battling SoftwareSerial for a few weeks now. And I think I tried everything I can throw at it. But intermittently (about 35-50% of the time) I am not able to receive any messages I’m sending over.

I’m using MAX485 for RS-485 communication. I managed to reduce my code to reveal the problem. This code works just fine:

  if (dev.available() && dev.read() == 2) {
    // Stuff to do some calculation while not meaning anything
    if (timeout < millis()) {}
    int timeoutTime = millis() + timeout;
    byte Checksummm = byte(0x00);
    
    char c = dev.read();
    digitalWrite(8, HIGH);
    dev.print(c);
    delay(50);
    digitalWrite(8, LOW);
  }

This expects transmission to begin with a certain character, and then read 1 more character after that, sending it back.

Now if I modify to wait for timeout, or end of transmission (marked by a new line), then it works only half the time.

  if (dev.available() && dev.read() == 2) {
    int timeoutTime = millis() + timeout;
    lastMessage = "";
    while (timeoutTime > millis()) {
      char c = (char)dev.read();
      if (c == byte(0x0A)) {
        break;
      }
      lastMessage += c;
    }
    digitalWrite(8, HIGH);
    dev.print(lastMessage);
    delay(50);
    digitalWrite(8, LOW);
  }

pin 8 controls MAX485 pins 2 & 3.

When it stops working, it’s quite persistent for a number of seconds/minutes. It’s never just 1 message that’s dropped. It’s always over a certain period of time. And every time I reset the board, it starts working just fine again (for an unpredictable period of time).

Any ideas as to what might be the culprit?

PS: I can’t seem to get hardware serial to work, and tried AltSoftSerial with same results (can’t get it to work). I can receive, but when transmitting, get nothing on the other end. But that’s an entirely different topic, which I can post if I can’t get SoftwareSerial to work.

Thanks for any help and/or pointers to try out!

The first pointer I would give you is that if you want help, post your code, or at least enough to show the failure. It sounds like you have a memory problem, and if that's the case, you can't expect anyone to figure out the problem without full failing code.

Of you could ask at http://snippets-r-us.com/

Oh, and your timeout may well be the problem. See http://gammon.com.au/blink to find out how to do it right.

You should not be adding time variables to get a time in the future. You should be using now - then >= interval to determine if you've been spinning your wheels waiting for too long.

      lastMessage += c;

You really shouldn't be using Strings.

 if (dev.available() && dev.read() == 2)

look at this one.. I guess i'd use a set of extra ()

int timeoutTime = millis() + timeout;

millis() are measured as unsigned long. An int would wrap within a 40 seconds... giving unexpected effects (and of course you should use subtraction in time math but that is said already)

Aww, snap! int owerflow for millis()!!! Arrrg, second time I step on the same problem. That's the issue. Makes perfect sense, and explains all symptoms, why it works only in increments of 30-40 seconds.

@PaulS: thanks for the tip, I'll change the math to do subtractions, not additions. But why shouldn't I use Strings (most my background is in PHP which is type agnostic, so it's quite an adjustment to always thinking about data types and structures).

PS: @lar3ry, I posted full content of the loop() function, leaving off only dev.begin(9600) and variable declarations. Is that not visible, or are you saying I should've posted the full file?

Thanks for the help, I'll try it out tonight when I'm back home. I'm sure it'll be fixed.

Yup, that fixed it! Now communication is reliable during extensive periods of time!

Thanks for help!

But why shouldn't I use Strings (most my background is in PHP which is type agnostic, so it's quite an adjustment to always thinking about data types and structures).

I'm not aware of a port of PHP to the Arduino, so I'll presume that you mean that most of your experience is writing code for an operating system that has many megabytes of real memory, and many more gigabytes of virtual memory using a programming language that manages memory for you.

What you can do in those circumstances is a bit different from what you can do on an embedded processor with 2K (Yes, that's a K, not an M, not a G, and certainly not a T) of memory.

Think of trying to overhaul a car engine in a phone booth, instead of an aircraft hangar (for 747s).

The String class thinks it's running on a PC with gobs of memory. It isn't.

...I'll presume that you mean that most of your experience is writing code for an operating system that has many megabytes of real memory...

Yes, that's what I meant.

Ouch, that's going to be quite a bit more challenging. Thanks for the tip. Will start refactoring!