LCD print trouble

Hello,

When in the "ALARM_ON" state, for some reason. The text from the "SAFE" state is printed straight afterwards. I have been unable to find a solution, any help would be greatly appreciated.

Many Thanks.

#include <Keypad.h>
#include <Password.h>
#include <LiquidCrystal.h>

enum { 
  ARMED,
  SAFE,
  ALARM_ON,
}
state;

//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;

int alarmTime = 10;

byte ledPin = 12;
int spkrPin = 11;
int reedPin = 13;
int pirPin = 10;

//Create an instance of lcd class
//                (RS,Enable,D4,D5,D6,D7)
LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

Password password = Password("1111");



const byte ROWS = 4; //four rows
const byte COLS = 3;//four columns
char keyMap[ROWS][COLS] = { 

  {
    '1','2','3'  }
  ,
  {
    '4','5','6'  }
  , 
  {
    '7','8','9'  }
  ,
  {
    '*','0','#'  }
}; 
//               ROW  1,2,3,4
byte rowPins[ROWS] = {
  2,3,4,5}; //connect to the row pinouts of the keypad
//               COL  1,2,3
byte colPins[COLS] = {
  6,7,8}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);


boolean switchState;
boolean lockLow = true;
boolean takeLowTime;



void setup() 
{
  state=SAFE;
  Serial.begin(9600);
  lcd.begin(16,2);
  pinMode(ledPin, OUTPUT);// set up serial port
  pinMode(spkrPin,OUTPUT);
  pinMode(reedPin,INPUT);
  pinMode(pirPin,INPUT);
  digitalWrite(ledPin, LOW);
  digitalWrite(pirPin,HIGH);
  Serial.print("calibrating sensor ");
  lcd.print("Calibrating");
  lcd.setCursor (0,1);
  for(int i = 0; i < calibrationTime; i++){
    Serial.print(".");
    lcd.print(".");
    delay(1000);
  }
  Serial.println(" done");
  Serial.println("SENSOR ACTIVE");
  lcd.clear();
  delay(50);


}

void loop() 
{ 
  char keyPressed = keypad.getKey();
  if (keyPressed != NO_KEY){ // if key has been pressed

    digitalWrite(ledPin,HIGH);
    digitalWrite(spkrPin,HIGH);
    delay (50);
    digitalWrite(ledPin,LOW);
    digitalWrite(spkrPin,LOW);
    delay (50);
    Serial.print (keyPressed);
    
    

  }
  switch (state) {
  case ARMED: 
    {
      if(digitalRead(pirPin) == HIGH){
        lcd.clear();
        lcd.setCursor(0,0);
      lcd.print("Alarm Activated");
      state = ALARM_ON;
        digitalWrite(ledPin, HIGH); 
        digitalWrite(spkrPin,HIGH); //the led visualizes the sensors output pin state
        if(lockLow){ 
          //makes sure we wait for a transition to LOW before any further output is made:
          lockLow = false; 
          Serial.println("---");
          Serial.print("motion detected at ");
          Serial.print(millis()/1000);
          Serial.println(" sec"); 
          delay(50);
        } 
        takeLowTime = true;
      }

      if(digitalRead(pirPin) == LOW){ 
        digitalWrite(ledPin, LOW); //the led visualizes the sensors output pin state
        digitalWrite(spkrPin,LOW);

        if(takeLowTime){
          lowIn = millis(); //save the time of the transition from high to LOW
          takeLowTime = false; //make sure this is only done at the start of a LOW phase
        }
        //if the sensor is low for more than the given pause, 
        //we assume that no more motion is going to happen
        if(!lockLow && millis() - lowIn > pause){ 
          //makes sure this block of code is only executed again after 
          //a new motion sequence has been detected
          lockLow = true; 
          Serial.print("motion ended at "); //output
          Serial.print((millis() - pause)/1000);
          Serial.println(" sec");
          delay(50);
        }
        switchState = digitalRead(reedPin);

        if (switchState) {
          digitalWrite(ledPin,HIGH);
          digitalWrite(spkrPin,HIGH);
          
        }
        else {
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,LOW);
        }
        break;
      }
    case SAFE: 
      {
        Serial.println("safe");
        digitalWrite(ledPin,LOW);
        digitalWrite(spkrPin,LOW);
        lcd.setCursor(0,0);
        lcd.print("* To Turn On");
        lcd.setCursor(0,1);
        lcd.print("Alarm");
        if (keyPressed == '*') {
          lcd.clear();
          lcd.setCursor(0,0);
          for(int i = 0; i < calibrationTime; i++){
          Serial.print(".");
          lcd.print(".");
          delay(1000);
        }
          Serial.print("Alarm Armed");
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Alarm Armed");
          state = ARMED;
        }
        break;
      }

    }

  


  case ALARM_ON: 
    {
      Serial.println("alarm is on");
      if (keyPressed == '*') {
        if(password.evaluate()) {
          state = SAFE;
          digitalWrite(ledPin,HIGH);
          lcd.setCursor (0,0);
          lcd.print("Enter Password");
          lcd.setCursor (0,1);
          lcd.print("Correct");

          delay(2000);
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,LOW);
          password.reset();
        }

        else {
          // password wrong
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,HIGH);
          lcd.setCursor (0,0);
          lcd.print("Enter Password");
          lcd.setCursor (0,1);
          lcd.print("Incorrect, Try again!");
        }
      }
      else {
        password.append (keyPressed);
      }
      break;
    }

  }
}

Jeff
Your code is a bit long for me to guess what it is supposed to do. Can you elaborate on its functions and hardware you are using? That will get you more help:)

Hey,

It is this part of the code I am having trouble with.

For some reason as the state changes to ALARM_ON, the text from SAFE immediately over writes it.

Many Thanks.

switch (state) {
  case ARMED: 
    {
      if(digitalRead(pirPin) == HIGH){
        lcd.clear();
        lcd.setCursor(0,0);
      lcd.print("Alarm Activated");
      state = ALARM_ON;
        digitalWrite(ledPin, HIGH); 
        digitalWrite(spkrPin,HIGH); //the led visualizes the sensors output pin state
        if(lockLow){ 
          //makes sure we wait for a transition to LOW before any further output is made:
          lockLow = false; 
          Serial.println("---");
          Serial.print("motion detected at ");
          Serial.print(millis()/1000);
          Serial.println(" sec"); 
          delay(50);
        } 
        takeLowTime = true;
      }

      if(digitalRead(pirPin) == LOW){ 
        digitalWrite(ledPin, LOW); //the led visualizes the sensors output pin state
        digitalWrite(spkrPin,LOW);

       if(takeLowTime){
          lowIn = millis(); //save the time of the transition from high to LOW
          takeLowTime = false; //make sure this is only done at the start of a LOW phase
        }
        //if the sensor is low for more than the given pause, 
        //we assume that no more motion is going to happen
        if(!lockLow && millis() - lowIn > pause){ 
          //makes sure this block of code is only executed again after 
          //a new motion sequence has been detected
          lockLow = true; 
          Serial.print("motion ended at "); //output
          Serial.print((millis() - pause)/1000);
          Serial.println(" sec");
          delay(50);
        }
        switchState = digitalRead(reedPin);

        /*if (switchState) {
          digitalWrite(ledPin,HIGH);
          digitalWrite(spkrPin,HIGH);
          Serial.print("On");
          state = ALARM_ON;
          
        }
        else {
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,LOW);
          Serial.print("Off");
          state = ALARM_ON;
        }*/
        break;
      }
    }
    case SAFE: 
      {
        Serial.println("safe");
        digitalWrite(ledPin,LOW);
        digitalWrite(spkrPin,LOW);
        lcd.setCursor(0,0);
        lcd.print("* To Turn On");
        lcd.setCursor(0,1);
        lcd.print("Alarm");
        if (keyPressed == '*') {
          lcd.clear();
          lcd.setCursor(0,0);
          for(int i = 0; i < calibrationTime; i++){
          Serial.print(".");
          lcd.print(".");
          delay(1000);
        }
          Serial.print("Alarm Armed");
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("Alarm Armed");
          state = ARMED;
        }
        break;
      }

    

  


  case ALARM_ON: 
    {
      Serial.println("alarm is on");
      digitalWrite(spkrPin,HIGH);
      digitalWrite(ledPin,HIGH);
      /*if (keyPressed == '*') {
        if(password.evaluate()) {
          state = SAFE;
          digitalWrite(ledPin,HIGH);
          lcd.setCursor (0,0);
          lcd.print("Enter Password");
          lcd.setCursor (0,1);
          lcd.print("Correct");

          delay(2000);
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,LOW);
          password.reset();
        }

        else {
          // password wrong
          digitalWrite(ledPin,LOW);
          digitalWrite(spkrPin,HIGH);
          lcd.setCursor (0,0);
          lcd.print("Enter Password");
          lcd.setCursor (0,1);
          lcd.print("Incorrect, Try again!");
        }
      }
      else {
        password.append (keyPressed);
      }*/
      break;
    }

  }

Give us an overview what you try to do. Too much details and no overview is like piecing together a puzzle.

When the PIR sensor goes HIGH, the state changes from ARMED to ALARM_ON, but when this happens, for some reason, it prints on the LCD what is in the SAFE state.

I make mine the words of liudr

liudr:
Jeff
Your code is a bit long for me to guess what it is supposed to do. Can you elaborate on its functions and hardware you are using? That will get you more help:)

and add, you should get rid of the comments in your code. Cut them out, open notepad, paste them there and continue troubleshooting with clean code. understanding what your's does with so many lines commented is a nightmare... especially when we have no idea what you pretend to accomplish.

So when we asked for you to elaborate we mean for you to narrow down further where the program is having problems, don't comment and post the same code with comments on without saying if that code does something different, what keys did you press while testing, where did you get the Password class and the serial communication log that you have running.

Then we might be able to get somewhere... until then, I don't think we can be of much help. :\

I see that you commented out the content of alarm_on case. So you're saying even with everything commented like you did, the execution still goes to safe after you trigger the PIR?

There are only two places you assigned safe to state, once in setup once in a line you commented out already. If you still keep getting safe, maybe your code keeps restarting so setup gets executed and sets state to safe. You need more description on symptoms before anyone can be real help to you.

and add, you should get rid of the comments in your code. Cut them out, open notepad, paste them there and continue troubleshooting with clean code. understanding what your's does with so many lines commented is a nightmare... especially when we have no idea what you pretend to accomplish.

This is absolutely the worst possible advice that you could give to any programmer. There are never enough comments. Ideally every block of code should be preceded by a comment telling what is to be done and then each step should be commented to tell what it's specific function is. The only possible reason for doing what you are proposing is for job security, so that no one else could possibly understand or maintain your code after you get fired.

Don

[EDIT] Perhaps you meant to recommend that he remove the blocks of code that he had 'commented out'. That's a whole lot different 'than getting rid of the comments', and I agree with that idea.

Jeff
I might be wrong here...but try me out.
It seems that all of your switch case is within the loop.

Instead of exiting the loop whenever you detect something, and check then come back, you fall all the way through.
SAFE is in setup, so it never comes back unless you reset by power or serial monitor.

If you were to increase the delay (50) at the end of each case to say 5000, i think you will see the fall through each state.

I agree with putting in comments. Add lots to help you out.
228 lines isn't large, i dumped into a sketch (it didn't like password) and checked it easily.

I found that adding serial.prints along the way helps to see where its getting lost.
Also sit down with a piece of paper and draw it in some form of flow chart, with each block (SAFE, ALARM_ON, etc) so you can visualise without the clutter can also help.

Mark

Try this, move the break; in each case to just before the next case statement

case 1:
....
break;
case 2:

Your break in within curly braces and may just break the curly braces instead of case. I wish c is more intelligent with switch-case statements but it's just as stubborn as '=' and '==' crap.

liudr
Cheers for the hint.
I avoided it by making it a different routine.

I managed to avoid C (or C++) for 20 years then got put onto Arduino.
I still keep forgetting the ; at the end

I had a better one yesterday.
one of my previously working routines had some comment lines inside /* ... */
I added another set (to save scrolling up and down the screen while I wrote)so in total had about three sets totalling 50 lines of text.

It threw up errors until I made it one big comment......strange
Mark

It threw up errors until I made it one big comment......strange

Comment blocks within comment blocks will cause a problem.

/* Start of first comment block
stuff you want to be ignored #1
    /* Start of second comment block
    stuff you want ignored #2
   */ End of second comment block
stuff you want ignored #3
*/ End of first comment block

The first /* starts the first comment block. The second /* is ignored since it is within a comment block, but it's */ actually terminates the first comment block and everything that follows (stuff you want ignored #3) is compiled. The second */ will cause one of your errors unless it is on a line following a regular comment symbol // or ;

Don

Don
Cheers

Mine were three seperate sets
/* Start of first comment block
stuff you want to be ignored #1
*/ End of first comment block

/* Start of second comment block
stuff you want ignored #2
*/ End of second comment block

/* Start of third comment blockstuff
stuff you want ignored #3
*/ End of first comment block

All the text was in grey and the next line of code was correctly colourised or recognised as keywords.

Total was baout 50 lines with blanks etc.

Making it one big comment fixed it, but had me scratching for a while.

Mark

Just a trick to keep long programs readable for me.

Lidru

Brilliant.
thanks very much

mark