Re: Corrupted characters with NewSoftSerial

Sure. Only the hardware serial function actually implements the available method. The software serial functions include the method, but it is not implemented. It simply returns true.

You need to actually examine the value returned by nss.read(). If it's negative, don't use it.

Only the hardware serial function actually implements the available method

http://arduiniana.org/libraries/NewSoftSerial/

The software serial functions include the method, but it is not implemented. It simply returns true.

At 0016, the method was not implemented at all.

If it was not defined, wouldn't that cause a compilation error?

If it was defined, but not implemented, wouldn't that cause an unresolved external reference at link time, preventing the production of a hex file?

Since OP has a working program, although not producing the results expected, it think that the available method must be defined and implemented.

It's not documented because it does not do anything useful, and therefore is not to be used.

You need to actually examine the value returned by nss.read(). If it's negative, don't use it.

Strange, how come the first one runs without any corruption?

Tried your idea but no dice unfortunately (unless I'm doing it wrong).

  nss.println("cmd");

  char linebuffer[255];
  uint8_t idx;
  char c;
  uint8_t maxlen = 254;
  
  for (idx=0; idx < maxlen; ) {
    linebuffer[idx] = 0;
    if (nss.available()) {
      c = nss.read();
      if (c == '\n') {
        continue;
      }
      else if (c > 0) {
        linebuffer[idx] = c;
        idx++;
      }
    }
    else
    {
      break;
    }
  }
  
  Serial.println(linebuffer);

Gives me:

+MD
 kjD=so
+5lj=sol
cskj=sol
+MD
 kjD=so
cskj=sol

@PaulS:
The "available" method is not implemented in the SoftwareSerial library, but is in NewSoftSerial.

You are doing something wrong.

What is in linebuffer[0], linebuffer[1], etc. at any given time?

The Serial.print(ln) function prints each character in linebuffer until it encounters a NULL. Your linebuffer array only randomly contains NULLs.

Each time you put a character in linebuffer, at a specified location, you need to put a NULL in the next location.

Change this:

        linebuffer[idx] = c;
        idx++;

to this:

        linebuffer[idx] = c;
        idx++;
        linebuffer[idx] = '\0';

@AWOL

The "available" method is not implemented in the SoftwareSerial library, but is in NewSoftSerial.

But that's the serial library we are talking about.

But that's the serial library we are talking about.

Just to clarify, talking about NewSoftSerial (NSS)

It looks like it's implemented and I'm assuming it's doing something useful...?

uint8_t NewSoftSerial::available(void)
{
  // A newly activated object never has any rx data
  if (activate())
    return 0;

  return (_receive_buffer_tail + _NewSS_MAX_RX_BUFF - _receive_buffer_head) % _NewSS_MAX_RX_BUFF;
}

You are doing something wrong.

That is definately the assumption I was running on :slight_smile:

Each time you put a character in linebuffer, at a specified location, you need to put a NULL in the next location.

Sorry my bad... doing that now but still seeing similar corruption as before (if not a bit more random)...

CMD
+
 kjD=so
CMD
cskhj=sol
CMD
+klj=sol
CMD
csklj=sol

This is very very strange...

I tried:

  uint8_t i;
  for (i=0; i < idx; i++)
  {
    Serial.print((char)i); Serial.print(": "); Serial.println((char)linebuffer[i]);
  }

instead of just normal Serial.println.

And it returns:

: C
: M
: D
:
:

: +
:
: c                                                                                                                                                                                                            : s
        : k

: h

: j
: =
: s
: o

As well as making my terminal window scroll up and down?!

I would move the nss.available() call out of the if's conditional area, and print out the returned value:

int bytesAvail = nss.available();
Serial.print("Bytes available: ");
Serial.println(bytesAvail);

Then, I'd echo each character read:

c = nss.read();
Serial.print("Read a ");
Serial.print(c);
Serial.print(" which has a decimal value of ");
Serial.println(c, DEC);

Finally, I'd indicate where I stored that value:

linebuffer[idx] = c;
Serial.print("Stored character in position: ");
Serial.println(idx);

Something may become obvious from doing this.

Where is the data on the software serial port coming from?

Right... I'm getting what I'd expect which is good output at the start (the CMD), and good output after =solar onwards, but still the corruption of course - just to remind, I didn't get this corruption when using the first program so it isn't the actual device itself which is outputting this corruption. The bit before =solar should be SSID (again, which I get on the first program)

Here's the main part:

Bytes available: 18
Read a C which has a decimal value of 67
Read a M which has a decimal value of 77
Read a D which has a decimal value of 68
Read a 
 which has a decimal value of 13
Read a 
 which has a decimal value of 10
Read a 
 which has a decimal value of 3
Read a c which has a decimal value of 99
Read a s which has a decimal value of 115
Read a k which has a decimal value of 107
Read a l which has a decimal value of 108
Read a j which has a decimal value of 106
Read a = which has a decimal value of 61
Read a s which has a decimal value of 115
Read a o which has a decimal value of 111
Read a l which has a decimal value of 108
Read a a which has a decimal value of 97
Read a r which has a decimal value of 114
Read a 
 which has a decimal value of 13

Just for information this is coming over UART from a Wifly GSX at 9600 baud (any faster and NSS gave me a ton of corruption)

I'm confused, after reading the User Manual for the WiFly. The CMD string is returned as a prompt after the WiFly enters command mode. Command mode is entered by sending "+++" to the device.

But, you are sending "cmd", and getting CMD back, and then you continue to read data.

I would expect that you would send a command after receiving the CMD string (followed by the carriage return/line feed).

Am I missing something?

Whoops sorry, I pasted the wrong section of code in the first part... I'm not sending cmd...:

I'm doing:

  nss.print("$$");
  nss.flush();
  delay(400);
  nss.println("get wlan");

I'm getting CMD back at first because I'm not giving the module a proper chance to respond before flushing, adding a 400msec delay before flushing fixes this, but still get corrupted chars:

Bytes available: 15
Read a + which has a decimal value of 43
Read a 
 which has a decimal value of 3
Read a k which has a decimal value of 107
Read a l which has a decimal value of 108
Read a j which has a decimal value of 106
Read a = which has a decimal value of 61
Read a s which has a decimal value of 115
Read a o which has a decimal value of 111
Read a l which has a decimal value of 108
Read a a which has a decimal value of 97
Read a r which has a decimal value of 114
Read a 
 which has a decimal value of 13
Read a 
 which has a decimal value of 10

Again... I continue recieving a bunch of data after that (just a snippet) but it's all perfect apart from those first few chars which should be SSID(=solar)...

I don't think I'm going to be able to help you any more. I am curious, though, why you switched from the hardware serial interface to a software serial interface.

I don't think I'm going to be able to help you any more. I am curious, though, why you switched from the hardware serial interface to a software serial interface.

No worries, thanks for your help so far Paul, I'll keep playing myself.

Switched purely so I could keep using the hardware serial interface for debugging etc... I've been using NewSoftSerial for ages on Lantronix devices without any problems at all which is why I'm so confused!