Error in Serial.available()

I'm writing a routine to read the Serial Buffer into a String Object. It depends on getting a accurate value of characters entered before a return.
Here is the code

/*
  Get String Example
  Reads the Serial input into a string. Using a pointer to a String Object.
 
 This example code is in the public domain.
 */
/****************************************************************************/
/* Routine to store the contents of the serial buffer into a                */
/* String Object location passed to the function                            */
/****************************************************************************/
int getString(String& newString) {
  int stringLength = Serial.available();
  newString = "";                        // Clear the string for the new data
  while (Serial.available()) {
    newString += (char) Serial.read();   // Concatinate each charageter onto 
                                         // the String Object 
  }
  Serial.print("getString: ");           // DEBUG print out the string length
  Serial.print(stringLength, DEC);       // and the string object 
  Serial.print(":");   
  Serial.println(newString);
  return stringLength;
}

void setup() {                
  // Open serial communications:
  Serial.begin(19200);

  // send an intro:
  Serial.println("Arduino Duemilanove");
  Serial.println("Get String Example");
  Serial.println();
}

void loop() {
  int count = 0;
  String myString = "";
  if (Serial.available() > 0) {
    count = getString(myString);
    Serial.print("myString: ");    // Show what was read
    Serial.print(count, DEC);
    Serial.print(":");
    Serial.println(myString);
//    count = parseString(myString, ' ');
//    Serial.println("No. of Sub Strings is: " + count);
  }
}

Here is the result after typing in HELLO followed by a return

Arduino Duemilanove
Get String Example

getString: 1:H
myString: 1:H
getString: 4:ELLO
myString: 4:ELLO

I expect a to get HELLO once and not split up like it is.
What am I doing wrong? Isn't Serial.available() suppose to return the number of characters entered?

Thanks

It returns the number of characters in the buffer. Since characters are sent one-at-a-time you can't assume that all characters will have been received by the time you check.

You can add a bit of delay to give more characters time to arrive:

  if (Serial.available())
     {
     delay(100);  // Time for about 19 characters to arrive
     count = getString(myString);
     [...]

If you use "while (Serial.available())" you will need to account for the times the serial input buffer has not been filled with a character (the arduino loops and checks the buffer much faster than the usual serial serial input can put something in the buffer. A slight delay can be one solution (a 1 ms delay may be all that is needed). There are also other various approaches to capturing strings.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

String readString;

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

void loop() {

        while (Serial.available()) {
        delay(10);  
    	if (Serial.available() >0) {
        char c = Serial.read();
        readString += c;}
        }
        
      if (readString.length() >0) {
      Serial.println(readString);
      
      readString="";
      } 
   }

delay(100); // Time for about 19 characters to arrive

sp. "Time for the buffer to overflow by 64 characters" :wink:

AWOL:

delay(100); // Time for about 19 characters to arrive

sp. "Time for the buffer to overflow by 64 characters" :wink:

Did I get my calculation wrong?

19200 bits per second.
about 1920 characters per second.
about 192 characters in a tenth of a second... oops.

I guess I meant delay(10) and not delay(100). Sorry.

As what AWOL said, a delay is a heuristic solution and is prone to overflow ;). I would suggest the OP use end-of-message character, such as '\n' to indicate the end of one line of message so arduino will keep reading the serial port (when there is data) and buffer the data in memory until it receives this end-of-message character and then takes the whole string and processes it.

OK, so my fundamental mistake was thinking the serial buffer updated after a carriage return. I think I like the option of looking for a carriage return then just delaying. Someone might be slow at typing. But I should have a timeout so it does not just sit waiting indefinitely.

  while (Serial.peek |= /n && Some Timeout Test) {
    newString += Serial.read();
  }

Thanks

I've tried my solution and I'm back to thinking that Serial.available() is not working right.

  1. It does appear that it waits for the carriage return before reporting the available charters. i.e. type something into the serial monitor and don't press the carriage return and it will never report any characters available.
  2. When polling Serial.available() it always returns 1 character and the the rest
  3. Serial.read() never returns a carriage return or line feed. It seems to be stripping them out.

I will look into the the Serial object next to try and confirm these observations.

Any Thought?

Serial monitor doesn't send anything at all until you hit the "send" key.
I don't think the problem is with Serial.available
Remember that serial communications are really, really slow.

I've tried my solution and I'm back to thinking that Serial.available() is not working right.

Yes, it is.

  1. It does appear that it waits for the carriage return before reporting the available charters. i.e. type something into the serial monitor and don't press the carriage return and it will never report any characters available.

Because the serial monitor doesn't send anything until you hit the send button.

  1. When polling Serial.available() it always returns 1 character and the the rest

Serial.available() returns the number of bytes in the serial buffer. Your code is looping, checking on how many characters are available. As soon as one is, it begins reading them.

  1. Serial.read() never returns a carriage return or line feed. It seems to be stripping them out.

No. The serial monitor doesn't send them, unless you have chosen that option (only available in 0022 and later).

Thank for the clarification on the serial monitor. That makes sense. I'll switch to something else to test the code.