As noted in the comments, since your prototype is receiving data from the serial port, you need some way for the user to indicate to the program that they are finished entry, since a 4-character entry is a necessary point along the way to a 5-character entry.
What you are doing now, by checking if Serial.available()>5
is letting the serial buffer hold 6 characters before you read from it (note: 5 is not >5), but then your else
statement:
else if (Serial.available() < 4)
{
Serial.read();
}
Clears out the buffer (Serial.read()
removes one character from the buffer), so you will never get to 5 characters anyway, unless all 6 characters come in between runs of loop()
, which is not likely at 19200 baud.
Not to mention that while data is sitting in the buffer, you don't know what it is and can't act on it. It is better to use the buffer as intended, which is to allow the Arduino to collect serial data, even while your program is working on other things, and then grab any pending data from the buffer as the program loop()
s.
You have declared the userInput[5]
array to hold user input, but note that if you only declare it at 5 char
s long, it cannot hold the null-character terminator that is standard for C-style strings. It would be better to declare this as:
char userInput[6]; // Holds 5 user characters, plus null terminator.
In your loop()
, you should copy out the contents of the buffer into your userInput
, check the length or for a termination character, such as a carriage return or newline (i.e., pressing 'Enter' on the serial terminal.) and act accordingly. Here is an example, showing just the relevant bits for the user input and hiding the rest in [...]:
char userInput[6]; // Holds 5 user characters, plus null terminator.
void setup() {
userInput[0] = '\0'; // Initialize string to empty
Serial.begin(9600);
}
void loop() {
uint8_t processInput = 0; // Set to 1 if we have complete entry
while (Serial.available()>0) {
char input = Serial.read();
if (input=='\r' || input=='\n') {
// Have received a terminating character,
// Flush the rest of the buffer
while (Serial.available()) {
Serial.read();
}
processInput = 1;
} else {
int s_len = strnlen(userInput, 5); // Get current length of userInput
if (s_len<5) {
userInput[s_len++] = input; // Append character
userInput[s_len] = '\0'; // Null-terminate string
} else {
// User has entered more than 5 characters and no terminating
// character; here is where you can decide to clear the userInput
// and start over, or just drop the first character and care
// about the most recent 5, etc. Here, we will clear the input
// and start over; The 6th character is dropped/ignored and
// user input starts again. It is as though the 6th character
// entered is like pressing Enter, but it does not process
// the incoming data, beacuse 6 characters is an invalid input.
userInput[0] = '\0';
s_len = 0;
processInput = 0;
// Invalid input
Serial.println("Error: invalid data");
}
}
}
if (processInput) {
Serial.print("User input - ");
Serial.println(userInput);
if (strnlen(userInput, 5)==5) {
// Do something **here** with the input string!!
// Reset input string
userInput[0] = '\0';
} else {
// Invalid input
userInput[0] = '\0';
Serial.println("Error: invalid data");
}
processInput = 0;
}
}
Note, this code is not fully tested and may contain bugs. In particular, I did not intensely check if the while (Serial.available()) {}
properly handles a lot of extra data.
One final note, you don't need the delay()
with this code.
EDIT:
I tried the sample code above and it had a couple of bugs, one of which was that after a successful 5-digit entry, the input string was not reset to empty. I have now updated the code and it's a valid, working program to receive and process a 5-character input on the serial port and to toss an error if fewer than 5 or more than 5 characters are entered. Entry is terminated with a carriage return or newline (enter key).