Reading an input from Serial Monitor

Hi Everyone,

I just came across a problem when trying to wait for and read an input from the Serial monitor. I don't know why the loop runs that many times. Would you please take a look for me :slight_smile:
Another question is. Is it okay in Arduino to use String str and return the result as a String instead of declaring it as a char array and returning the pointer?

char *getPassword()
{
  char str[5];
  char c;
  int i = 0;
  while(Serial.available() == 0) {}   // Wait for input
  if(Serial.available())
  {
    Serial.println("In if");
    while( (c = Serial.read()) != '\n')
    {
      str[i] += c;
      i++;
      Serial.println(i);
    }
    str[i] = '\0';
  }
  return str;

The following is the sample output of i when I entered the value 1 in the serial monitor.

In if
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

Thank you very much for your time

Kenny

The techniques in the serial input basics tutorial allow non-blocking reading of serial input without using Strings.

Your basic problem is the way that you wait for '\n' in a while-loop without checking if there are more characters available. Once one character is available, you use a while-loop to read until there is a '\n'. However, if there was only one character available, you still read in that while-loop and Serial.read() will return -1 (indicating that there nothing).

Another problem in your code is the line
* *str[i] += c;* *
. Your str variable is not initialised (because it has local scope) and can contain any value; you need to initialise that array with zeroes first or you can use
* *str[i] = c;* *
.

The last problem is that str goes out of scope at the moment that the function finishes. Your function will return the correct pointer, but the location that it points can be re-used and hence the entered password can be corrupted.

Next, this is a bit silly :wink:

  while (Serial.available() == 0) {}  // Wait for input
  if (Serial.available())

The first line waits till something is available. Next you check if something is available which will always be the case because the code managed to get past the first line when one or more characters are available.

Although I agree that Robin has a nice universal approach and I would use that, the below code (loosely based on your code) addresses the above points.

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

void loop()
{
  Serial.println("password please");
  char pwd[5];

  getPassword(pwd, sizeof(pwd) - 1);
  Serial.println(pwd);
}


/*
  blocking password entry
  In
    password: char array to store password
    len: number of allowed characters
*/
void getPassword(char *password, uint8_t len)
{
  uint8_t i = 0;

  while (true)
  {
    if (Serial.available())
    {
      password[i] = Serial.read();
      Serial.println(i);
      // break if we received newline
      if (password[i] == '\n')
      {
        break;
      }

      // only increment i if there's still space
      if (i < len)
      {
        i++;
      }
    }
  }
  password[i] = '\0';
}

groundFungus:
The techniques in the serial input basics tutorial allow non-blocking reading of serial input without using Strings.

Thank you very much for the information. I appreciate it :slight_smile:

sterretje:
Your basic problem is the way that you wait for '\n' in a while-loop without checking if there are more characters available. Once one character is available, you use a while-loop to read until there is a '\n'. However, if there was only one character available, you still read in that while-loop and Serial.read() will return -1 (indicating that there nothing).

Another problem in your code is the line
* *str[i] += c;* *
. Your str variable is not initialised (because it has local scope) and can contain any value; you need to initialise that array with zeroes first or you can use
* *str[i] = c;* *
.

The last problem is that str goes out of scope at the moment that the function finishes. Your function will return the correct pointer, but the location that it points can be re-used and hence the entered password can be corrupted.

Next, this is a bit silly :wink:
[/i][/i]

  while (Serial.available() == 0) {}  // Wait for input

if (Serial.available())




_*The first line waits till something is available. Next you check if something is available which will always be the case because the code managed to get past the first line when one or more characters are available.*_
_*Although I agree that Robin has a nice universal approach and I would use that, the below code (loosely based on your code) addresses the above points.*_



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

void loop()
{
 Serial.println("password please");
 char pwd[5];

getPassword(pwd, sizeof(pwd) - 1);
 Serial.println(pwd);
}

/*
 blocking password entry
 In
   password: char array to store password
   len: number of allowed characters
*/
void getPassword(char *password, uint8_t len)
{
 uint8_t i = 0;

while (true)
 {
   if (Serial.available())
   {
     password[i] = Serial.read();
     Serial.println(i);
     // break if we received newline
     if (password[i] == '\n')
     {
       break;
     }

// only increment i if there's still space
     if (i < len)
     {
       i++;
     }
   }
 }
 password[i] = '\0';
}

Thank you very much for your help. I just have one little question. Is it considered normal to use pointers in Arduino? I know they have been used extensively in C, but am not sure if it is okay to use them in programming microcontrollers.

Kenny

If pointers have you worried, just change it to:

void getPassword(char password[], uint8_t len)

It will still be passed as a pointer but it won't look like a pointer.

johnwasser:
If pointers have you worried, just change it to:

void getPassword(char password[], uint8_t len)

It will still be passed as a pointer but it won't look like a pointer.

Thank you very much for your reply. So... I assume it is okay to use pointers when coding microcontrollers? It's just me that I have the notion pointers are only used in C or C++.

Kenny

You are programming in C++