Problems with Serial Bus

Hello,

If I enter the String "W1-1356834120-20-60/2-1356834140-20-60/3-1356834160-20-60/4-1356834120-20-60/5-1356834140-20-60/6-1356834160-20-60/7-1356834120-20-60/8-1356834140-20-60/" to the Serial Monitor, the Arduino return this: "1-1356834120-20-60/2-1356834140-20-60/3-1356834160-20-60/4-135"

My Code:

void setup ()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    char SI = Serial.read();
    if (SI == 'W')
    {
      String Input;
      while (Serial.available())
      {
        Input = Input + char(Serial.read());
      } 
    
      Serial.println(Input);
    }
}

Why the Arduino don´t return "1-1356834120-20-60/2-1356834140-20-60/3-1356834160-20-60/4-1356834120-20-60/5-1356834140-20-60/6-1356834160-20-60/7-1356834120-20-60/8-1356834140-20-60/"?

Thank You,
bluefix

Hmm. How much SRAM does your Arduino have?

Arduino Uno rev. 3

SRAM 2KB

My Code is much longer.

Global Variables:

unsigned long end_of_ch[38];
int Channels[8];
boolean IsOpen[8];

Your code assumes that once you see a 'W', all the other characters will be delivered back to back. That isn't necessarily so - there may be a time when transmission is in process, but nothing is available to read yet. If that occurs, you'll print what you have at that point and go back to looking for a 'W'. Since there isn't another, no more input will be read.

There's more to it than that I suspect. You're only processing 64 characters, which by a remarkable coincidence is the size of the serial read buffer.

Concur with wildbill.

The serial input buffer is 64 characters. You are only getting the first 64-ish of your 154 characters of input. So right away we have to think "timing problem with buffer overflow".

The second Serial.available() test seems to have the intention of looking for the end of the line. But checking Serial.available() is not a reliable way to detect line endings.

It would be better to loop looking for a line ending character like '\n', and wait on serial available within that loop, if that makes sense. Accumulate characters to the end of the line, not until random timing gives you serial.available of zero.

-br

Ah, that's not all your code. If the missing code does time consuming stuff or has, God forbid, delay in it, then depending on when you send the serial data, it may well overflow the buffer. Try running the code you posted - does it work?

With This Code:

void setup ()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    char SI = Serial.read();
    if (SI == 'W')
    {
      String Input;
      char c = char(Serial.read());
      while (c != '\n')
      {
        Input = Input + c;
        c = Serial.read();
      } 
      Serial.println(Input);
    }
}

it returns nothing.

If I use this Code (for Debugging):

void loop()
{
  if (Serial.available())
  {
    char SI = Serial.read();
    if (SI == 'W')
    {
      String Input;
      char c = char(Serial.read());
      while (c != '\n')
      {
        Input = Input + c;
        Serial.print(c);
        c = Serial.read();
      } 
      Serial.println();
      Serial.println(Input);
    }
}

it returns "1-1356834120-20-60/2-1356834140-20-60/3-1356834160-20-60/4-135ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(...)"

The chip isn't receiving \n from you, so doesn't exit the while loop..

In the inner loop you are doing Serial.read without first assuring that Serial.available is greater than zero. That's why it doesn't work, and why you get those y-umlaut characters. They show up when you read when zero characters are ready.

-br

void setup ()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    char SI = Serial.read();
    if (SI == 'W')
    {
      String Input;
      char c;
      while (Serial.available() > 0)
      {
        c = Serial.read();
        Input = Input + c;
      } 
      Serial.println(Input);
    }
  }
}

I get Nothing back... =(

Um, what happened to checking for the end of line?

If you're simply going to thrash around, without trying harder to understand what's going on, you'll get nowhere. Maybe a little break would help.

One more time.

You need to capture characters up to the end of line.

To capture each character, you must be sure it is there first.

-br

I´m sorry, but i´m really desperate, because i´m sitting on this problem for a week...

Ok.
What is the character for an end of the line, if it isn´t '\n'?

void setup ()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    char SI = Serial.read();
    if (SI == 'W')
    {
      String Input;
      char c = Serial.read();
      while (Serial.available() && c != [end of line character])
      {
        Input = Input + c;
        if (Serial.available)
        {
          c = Serial.read();
        }
      } 
      Serial.println(Input);
    }
  }
}

Would it be now correct?

P.S. And Yes a coffee would be the right now :wink:

Your problem is that serial communications are very slow compared to the Arduino's ability to process them, especially at 9600 baud. As I said earlier, you cannot depend on the string you are sending all arriving at the same time. I believe that the only reason your original version was close to working was because other parts of your code slowed things down so that the data you sent filled the read buffer and the rest was thrown away. Given that it was then sitting on the arduino ready to be read, you could use your while loop to pull the data without fear that nothing would be there.

Now that does not apply. Before you read each character, you must be sure that one is available. Get rid of your while loop. In loop, if a character is available, read it and then check what it is. If it was 'W', set your collection string to "". If it was '\n' print the string and set it to "". any other character, add it to the string.

That should do it. A switch would be handy for replacing the ifs. Then get rid of String and use char arrays instead. Then add some logic that ignores characters until you see 'W'. Get the absolute minimum working first though.

You´re right. The rest of my code (about 500 rows) is very long.
One loop() last about 200ms. But I´ve got an idea how to fix the buffer problem.

Thank you all!
(And sorry for my stupidity :wink: )

bluefix:
I´ve got an idea how to fix the buffer problem.

I hope your idea is very very similar to the approach suggested by wildbill.

You're going to need to service serial quite frequently to avoid buffer overflow. Every 200ms is not going to cut it - theoretically, you could get ~190 characters delivered in that time. Post (attach) your code if you need assistance in refactoring it to achieve this.

I put a , on the end of your string and the below code returned the entire string to the serial monitor.

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
  
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      //do stuff
      Serial.println(readString); //prints string to serial port out
      readString=""; //clears variable for new input      
     }  
    else {     
      readString += c; //makes the string readString
    }
  }
}