Serial read problem

Hi,
I am new to the forum and indeed to the arduino so firstly hello.

I have been experimenting to get the hang of the arduino syntax and I have come up with a problem with the Serial.read() function that I am hoping someone may be able to explain. I have done a search but couldn't find any relavant info.

I am trying to read from the serial port, put the data (a series of integers) into an array and then write that array back out to the port.

Instead of the data being read as a single series of ascii chars the first is read and actioned and then the rest are read: heres what I mean

Input:
1234

Expected Output:
Message received :- 1 2 3 4 -:

Actual Output:
Message received :- 1 -:
Message received :- 2 3 4 -:

and here is the code:
/*

  • Serial IO
    */

int rxByte[100]; //array to hold the message
int inx = 0; //index through the array

void setup()
{
Serial.begin(9600); // set up Serial connection to 9600 bps
}

void loop()
{
//while there is data available read the port
while(Serial.available() > 0)
{
rxByte[inx] = Serial.read() - 48; //put the data in an array and ascii to int

/*
Serial.println("Debug rxByte[inx], inx");
Serial.print(rxByte[inx]);
Serial.println(inx);
*/

inx++;

}

//if a valid message has been received
//write it out again
if(inx > 0)
{
Serial.print("Message received :- ");

//output format is "Message received :- 1 2 3 4... -:"
for (int i = 0; i < inx; i++)
{
Serial.print(rxByte*);*

  • Serial.print(" ");*

  • }*

  • Serial.println("-:"); *

  • inx = 0;*

  • } *
    }
    Many thanks in advance. Rich
    Oh one last thing if I uncomment the debug code in the while loop the output behaves as I am expecting it to.

Welcome, richiet!

Here's my analysis. The instant first character arrives, you quickly stuff it into the buffer and immediately go check whether more characters are available. They aren't! At 9600 baud, those characters are arriving very SLOOOOWWWLY compared to the speedy little Atmel processor. So you send "Message received" over the port. Because this is a serial activity also, it also goes very SLOOOOWWLY, giving plenty of time for the remaining 2-3-4 to arrive. By the time you go check again, the remainder of your message is waiting for you to collect it.

Savvy?

The lesson is to never use Serial.available() <= 0 as a message delimiter. Use a character as a delimeter. For example, you probably got a linefeed character (10) across the wire when you pressed Enter. Use that as a delimiter.

Edit: The Arduino console doesn't send the newline across.

Mikal

It would be really nice if you did get a linefeed or could set something in properties.txt that would allow a linefeed. I haven't seen it if it exists though.

I checked out the app code, let me see how hard it would be to add.

Ok, took a closer look. It would take a code change to make appending a linefeed happen, something like this perhaps:

in:
processing/app/EditorStatus.java

change:
editor.serialPort.write(serialField.getText());

to:
editor.serialPort.write(serialField.getText() +
(Preferences.getBoolean("serial.addLinefeeds")?"\n":""));

then add:
serial.addLinefeeds=true

to preferences.txt to enable it.

Nice work, dcb. Thanks.

In that case, richiet, I would replace your while (Serial.available() > 0) loop with something like

while(true)
{
  if (Serial.available())
  {
    int c = Serial.read();
    if (c == 10 || inx == 100) break; // Check for linefeed AND buffer overflow!
    rxByte[inx] = c - '0';    //put the data in an array and ascii to int
    // debug stuff
    ...
    inx++;
  }
}

Mikal

Thanks for the replies guys. It all makes sense. I can't find the file processing/app/EditorStatus.java though.

You wont, at least not in the release, it is in the source code repository for the ide. Low level stuff.

If your curious:

why not just add a line feed in the Processing sketch

public static final char LF = 10; // declare LF

myPort.write(value); // your existing code
myPort.write(LF); // add this to send a line feed

Just to prove Mikal's point using my original code I added a 1ms delay between reading each char and the problem is fixed.

It's good that you have verified Mikal's point but I doubt he would recommend adding delays as the solution :wink:

Testing for an end of message character is much more robust should the baud rate be changed later on.

Thanks mem. Yes I accept that this is not a solid solution but since I am only playing around with this code the objective was really to discover why it was doing what it was doing but I take your point. Rich