Trying to spot what's wrong in the loop

Hey guys,

I'm pulling my hair out with this issue, it seems simple to solve but I can't spot what's wrong. My code activates an alarm and starts looping a signal from a distance sensor, which is then deactivated when a user enters a password (keypad to be included in the future, for now I'm just using my computer keyboard). Once deactivated, my Arduino waits for the user to reactivate the alarm by entering the password again.

The code I'm attaching is the bit I'm having trouble with, even though it is not the entire code, the bit you'll read is functional (with the problem I'm getting though).

The problem is in the 'if' statements. Basically, I'm able to deactivate the alarm but then when the program reads 'waitToTurnOn()' for some reason the program goes to Serial.println("WRONG PASS") which it shouldn't. It should wait for the user to enter the password, it can't print WRONG PASS without having entering anything. I guess the issue has to do with Serial.available and Serial.read() ? I can't get it to work the way I need, any help/suggestions will be appreciated.

boolean onState = true;

void setup() 
{
  Serial.begin(9600); 
  Serial.println("Alarm turned ON");
  pinMode(13,OUTPUT);  
}

void loop() 
{
  if(onState == true){
    
    //Code for distance sensor...
    //.
    //.
    //.
    waitToTurnOff();
  }
  else {
    waitToTurnOn();  
  }  
}

void waitToTurnOff()
{ 
  if( Serial.available() ){  
      char passToTurnOff = Serial.read();
    
      if(passToTurnOff== '1'){                    
        Serial.println("Turned OFF!");
        onState = false;
      }else{
         Serial.println("WRONG PASSSSSSSSS");
      }
    }
}

void waitToTurnOn(){
  if(Serial.available()){
    char passToTurnOn = Serial.read();

    if(passToTurnOn == '2'){
        Serial.println("Turned ON!");
        onState = true;
    }else{
       Serial.println("WRONG PASS");
    }
  }  
}

For debugging purposes, why not echo what you read in, just to make sure you're reading what you think you're reading?
Is it possible your terminal emulator is sending a '\r' or '\n' that is confusing things?

I would try 2 things. First, use an int with values 1,0 instead of a boolean for onState.
Secondly, change the char passToTurnOff,On "declarations" to int, and move out
of the if..then constructs.

For debugging purposes, why not echo what you read in, just to make sure you're reading what you think you're reading?
Is it possible your terminal emulator is sending a '\r' or '\n' that is confusing things?

Hello Gardner, thanks for your reply. Yes I echoed what I read in and I actually get what I was expecting.Why do you think my terminal emulator is sending a '\r' or '\n' ? why can that happen?

I would try 2 things. First, use an int with values 1,0 instead of a boolean for onState.
Secondly, change the char passToTurnOff,On "declarations" to int, and move out
of the if..then constructs.

Thanks Oric_dan, I'll try your suggestions when I get home. I have a question though, why would 1,0 yield a different result from my boolean variable? why do you think that can influence the result? I thought they were (pretty much) the same.

Why do you think my terminal emulator is sending a '\r' or '\n' ? why can that happen?

Because that is the normal behaviour of a terminal emulator.
"carriage-return" and "line-feed" are the end of line markers from the days of teletypes.

krow:
I echoed what I read in and I actually get what I was expecting.

I don't believe you.

You have already told us that you are getting a spurious input which fails your 'password' check. The debug should have told you what the spurious input was. If it only shows what you expected then the problem you described cannot occur.

Are you using the ide-provided terminal emulator ? Try various end-of-line options.
Also, print what you Serial.read() with println(ch, HEX) otherwise \r and \n characters will go unnoticed.

void setup() {
    Serial.begin(115200);

}

unsigned int cnt = 0;

void loop() {
    char ch;
    
    if (Serial.available() > 0) {
        cnt++;
        ch = Serial.read();
        Serial.print(cnt);
        Serial.print(": ");
        Serial.println(ch, HEX);
    }
}

Here's what I get if I send 1 when "both cr and nl" option is enabled:

1: 31
2: D
3: A

Im guessing your trying to read in "1234" and get out "1234" correct? If so that is actually easy. What you need to do is read the characters in and store them in an array, then use "Blah_Blah = atoi(Data);" this convert the array data to an integer.

example:

char Data[8]; // however long it needs to be, GLOBAL VARIABLE
int currentCommand = 0; //GLOBAL VARIABLE

void setup() {...........}

void loop{
if (Serial.available() > 0) {
char ch = Serial.read();
if (ch != '\c' || ch != '\r' || ch != '\n') // It's looking for just the numbers, 
  {                                         // and if it see one of these, it will print out the numbers
    Data[currentCommand++] = ch;
   //Serial.print(Data[currentCommand]);
  }
else {
    int MyData = atoi(Data); // converts the chars into ints
    Serial.println(MyData); // shows you what you put in
    while(currentCommand !=0){   // This can be used for any array size, LEAVE THIS IN
    Data[currentCommand--] = 0; } //clear for new data   LEAVE THIS IN
    MyData = 0; // clears it after use
    }
  }
}

Not compiled! it's really just to give you an idea.
Keep in mind it might have bracket " { } " errors or some other kind of errors i've overlooked. So you may need to tweak it a bit.

For when you incorporate the keypad, look at this http://arduino.cc/forum/index.php/topic,137352.0.html

Guys, thank you all for your help, I found the problem.

Based on what Garner said about the escape characters, I decided to view the output with Putty instead of the Arduino IDE serial monitor to see if I still had the same result, it turns out that in Putty my program works fine.

As opposed to the serial monitor in the Arduino IDE, when I use Putty and I enter # 1 to deactivate the alarm (I chose 1 for the sake of simplicity), there's no need to hit 'Enter' to send the actual key, the alarm is deactivated as soon as I hit 1. Because in the serial monitor of the Arduino IDE I hit two keys (1 and then Enter) my program reads the two keys one after the other, that's why every time I send a 1 and it goes to the next function I get the WRONG PASS message, basically what the program is reading is the Enter key which is the second key I press.

Hopefully this will help someone else in the future, I hope it was clear! cheers.

Guys, thank you all for your help, I found the problem.

Based on what Garner said about the escape characters, I decided to view the output with Putty instead of the Arduino IDE serial monitor to see if I still had the same result, it turns out that in Putty my program works fine.

As opposed to the serial monitor in the Arduino IDE, when I use Putty and I enter # 1 to deactivate the alarm (I chose 1 for the sake of simplicity), there's no need to hit 'Enter' to send the actual key, the alarm is deactivated as soon as I hit 1. Because in the serial monitor of the Arduino IDE I hit two keys (1 and then Enter) my program reads the two keys one after the other, that's why every time I send a 1 and it goes to the next function I get the  WRONG PASS message, basically what the program is reading is the Enter key which is the second key I press.

Hopefully this will help someone else in the future, I hope it was clear! cheers.

I guess the way to avoid this issue with the Arduion IDE serial monitor is by writing a program that ignores the Enter key after entering my password? it's still more comfortable for me to use that monitor than Putty.

Have you seen the listbox at the bottom of Arduino serial monitor ? It says "no line ending, etc.". Try that option, it'll work as in Putty.

Have you seen the listbox at the bottom of Arduino serial monitor ? It says "no line ending, etc.". Try that option, it'll work as in Putty.

Great! something new I learned today, thanks.

Funny thing is, after all there was nothing wrong in my code :stuck_out_tongue:

krow:
Funny thing is, after all there was nothing wrong in my code :stuck_out_tongue:

Indeed, but I wouldn't call a single char a "password" :stuck_out_tongue: