0

I am want to receive a 5 character hexadecimal input from user over serial port of arduino Uno.

int count = 0;                                    // count = 0
char userInput[5];

void setup()
{
  delay(1000);
  Serial.begin(19200);                            // begin serial port with baud rate 9600bps

}
void loop()
{
  if (Serial.available() > 5)
  {
    Serial.read();
  }

  else if (Serial.available() < 4)
  {
    Serial.read();
  }

  else if (Serial.available() == 5)
  {
    for (int i = 0; i < 5; i++)
    {
      userInput[i] = Serial.read();
    }

    Serial.print("User Input - ");
    Serial.println(userInput);
  }

  delayMicroseconds(10000);
}

But I want to discard the input if user inters less than 5 characters or more than 5?

Since the Serial.flush() have a different meaning now, I can not clear the buffer if user enters less than or more than 5 characters and the characters gets added to next input.

e.g. If I upload above program and entered input in following sequence:

abcde
abcd
abcd
abcd
abcd
abcdef
abcde

I got the following output:

User Input - abcde
User Input - dabcd
User Input - dacbd
User Input - bcdef
User Input - abcde

Two invisible characters appear in output which are not visible but when I copied the output from serial monitor but these characters appear when I copy paste the output into Text Editor.

So How can I modify the program to receive only 5 hex character input from user (Which user will input from Hex Keypad)? And if user enters more or less character I want to clear the input buffer for next user input so that characters from previous input doesn't get added to next one.

  • Does your keypad or data-entry procedure have an "enter" or submit or other termination indicator which, or is your program supposed to react at the moment the 5th character is pressed/entered? In other words, is there a way for the user to indicate "I'm done" entering characters? – jose can u c Feb 13 '18 at 14:29
  • Right Now I test testing this Program on Arduino IDE on Laptop over Serial Monitor. – CrownedEagle Feb 13 '18 at 14:31
  • So right now on IDE I am Pressing "ENTER" key on laptop keyboard to indicate "I'm Done" But in future I will modify the program to auto react when 5th character in entered.. – CrownedEagle Feb 13 '18 at 14:32
  • The solution now I seek is, How to receive only 5 Character input and reject smaller or bigger input? – CrownedEagle Feb 13 '18 at 14:33
  • You need something to synchronize. You need to know where the begin is of the 5 characters. It can be very simple, for example a 'stx' or a '[' character. Or you can use a character at the end of the 5 characters, for example a carriage return or line feed. If you have no control over the serial keypad, then you can use timeouts to identify the start of the 5 characters. In that case you have to describe very careful all the timeouts and the data. – Jot Feb 13 '18 at 14:53
2

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 chars 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).

  • else if (Serial.available() < 4) { Serial.read(); } Sorry it is < 5. Now Program rejects all entries below 5 characters. But if user enters more than 5 characters the 1st character is neglected and only 5 characters from 2nd to 6th characters are printed. – CrownedEagle Feb 13 '18 at 15:38
  • Thanks for the answer.. I will try your suggestions with delay and other necessary edits.. – CrownedEagle Feb 13 '18 at 15:40
-1

I wrote following program, it receives 5 character input from user and if user enters input more than 5 characters then program store only 1st 5 characters and if user inputs less than 5 characters long the it rejects than input altogether..

char userInput[5];
void setup()
{
//delay(1000);
Serial.begin(9600); // begin serial port with baud rate 9600bps
}

void loop()
{
if (Serial.available() < 5)
{
   Serial.read();
}
else if (Serial.available() >= 5)
{
      for (int i = 0; i < 5; i++)
      {
        userInput[i] = Serial.read();
      }
     while (Serial.available() > 0)
     {
       Serial.read();
     }
Serial.print("User Input - ");
Serial.println(userInput);
}
delay(100);
}
  • 1
    The code assumes that the user input always comes in a single block, which is unrealistic. The code must work even if it receive chars one at the time, or two, or three ... whatever. – user31481 Feb 15 '18 at 18:33
  • 1
    Not only does it assume user input always comes in a single block, anything less than a full block of 5 characters gets thrown in the garbage and is lost forever. – jose can u c Feb 15 '18 at 18:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.