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?
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="";
}
}
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();
}
I've tried my solution and I'm back to thinking that Serial.available() is not working right.
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.
When polling Serial.available() it always returns 1 character and the the rest
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.
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.
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.
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.
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).