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
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
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
 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';
}
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
[/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.*_
/*
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.
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++.