Problem with switch case

Hi,

I have only started playing around with switch case statements. I am trying to make a keypad for a shutter door.

I am using the keypad example from the password library.

I want * to open the stutter and # to close it. The shutter should only move when either button is being pressed.

I get a correct or incorrect response from the password bit, but holding the buttons down does nothing. It has something to do with case HOLD:, but I don't know what.

Can you have a switch within a switch?

#include <Password.h> //http://www.arduino.cc/playground/uploads/Code/Password.zip
#include <Keypad.h> //http://www.arduino.cc/playground/uploads/Code/Keypad.zip

Password password = Password( "1234" );

int relayOne = 8;
int relayTwo = 9;

const byte ROWS = 4; // Four rows
const byte COLS = 3; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};

byte rowPins[ROWS] = { A0, A1, A2, A3 };// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte colPins[COLS] = { 4, 3, 2 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins.


// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  pinMode(relayOne, OUTPUT);
  pinMode(relayTwo, OUTPUT);
  digitalWrite(relayOne, HIGH);
  digitalWrite(relayTwo, HIGH);
}

void loop(){
  keypad.getKey();
}

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
  Serial.print("Pressed: ");
  Serial.println(eKey);
  switch (eKey){
    case '*': 
      if (password.evaluate()){
        Serial.println("Success");
        switch (keypad.getState()){
        case HOLD:
          digitalWrite(relayOne, LOW);
          break;

        case RELEASED:
          digitalWrite(relayTwo, HIGH);
          break;
        }
      }
      else{
        Serial.println("Wrong");
        //add code to run if it did not work
      }
      password.reset();
      break;
      
    case '#':  
      if (password.evaluate()){
        Serial.println("Success");
        switch (keypad.getState()){
        case HOLD:
          digitalWrite(relayTwo, LOW);
          break;

        case RELEASED:
          digitalWrite(relayTwo, HIGH);
          break;
        }
      }
      else{
        Serial.println("Wrong");
        //add code to run if it did not work
      }
      password.reset();
      break;
    default: password.append(eKey);
     }
  }
}

Cheers,

Damien

Can you have a switch within a switch?

Yes definitely but say keypad.getState() returned PRESSED - why do you think your second call to keypad.getState() will change just microseconds after to HOLD or RELEASED? I would assume it will just return the same state, i.e. PRESSED

"Can you have a switch within a switch?"
You can always prove things out yourself by trying. :wink:

J-M-L:
Yes definitely but say keypad.getState() returned PRESSED - why do you think your second call to keypad.getState() will change just microseconds after to HOLD or RELEASED? I would assume it will just return the same state, i.e. PRESSED

So how do I get it to recognise the button is held?

Cheers

larryd:
"Can you have a switch within a switch?"
You can always prove things out yourself by trying. :wink:

I've tried with the case HOLD:, but couldn't get it to work.

larryd:
"Can you have a switch within a switch?"
You can always prove things out yourself by trying. :wink:

I've been trying but I'm going round in circles.

If I change the case PRESSED: to case HOLD:, it kinda works, but every digit of the password has to be held for a second for it to register. I'm lose.

Is the sketch in the first post your current sketch?

Yes. It just gives me Success or Wrong to password query. I cant get the relays to then operate when buttons held.

Cheers.

Here is a sketch that demonstrates turning ON a LED while a keypad button is held i.e. 'HOLD' and turning the LED OFF when the button is let go i.e. 'RELEASED'.

You will have to change the hardware pin numbers as needed.

Needs two LEDs one each on pin 9 and 8 with 220R series resistors going to GND.
const byte ledPinWhite = 9; // +5V-----LED anode/cathode-----220R-----pin 9
const byte ledPinRed = 8; // +5V-----LED anode/cathode-----220R-----pin 8

You should be able to incorporate the idea into your code.

//A sketch that demonstrates turning ON a LED while a keypad button is held i.e. 'HOLD'
//and turning the LED OFF when the button is let go i.e. 'RELEASED'.
//Enter password then * or #
//LarryD
//17/04/03 ver 1.00
//17/07/29 ver 1.01  Added password

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};
//                Row 0  1  2  3
byte rowPins[ROWS] = {4, 5, 6, 7}; //connect to the row pinouts of the keypad
//            Column  0  1  2
byte colPins[COLS] = {29, 28, 27}; //connect to the column pinouts of the keypad

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

//LOW on pin turns on LEDs
const byte ledPinWhite = 9; // +5V-----LED anode/cathode-----220R-----pin 9
const byte ledPinRed  = 8; // +5V-----LED anode/cathode-----220R-----pin 8

//Target password
unsigned int PassWord = 1234;

//Password number entered
unsigned int PW;

bool PWokay = false;

//******************************************************
void setup()
{
  Serial.begin(9600);
  pinMode(ledPinWhite, OUTPUT);
  pinMode(ledPinRed,  OUTPUT);
  digitalWrite(ledPinWhite, HIGH);      //Turn the LED OFF
  digitalWrite(ledPinRed,  HIGH);      //Turn the LED OFF
  keypad.addEventListener(keypadEvent); //Add an event listener for this keypad
  Serial.println("Enter a new password");

} //END of            s e t u p ( )

//******************************************************
void loop()
{
  char key = keypad.getKey();
  if (key)
  {
    Serial.print(key);

    //check for a valid password
    if ((key == '*' || key == '#') && PWokay == false)
    {
      if (PW == PassWord)
      {
        PWokay = true;
        Serial.println("");
        Serial.println("Password is okay.");
        Serial.println("You can use * or # to control the LEDs, hold 0 to reset.");
      }

      else
      {
        PWokay = false;
        PW = 0;
        Serial.println("");
        Serial.println("Password is bad.");
        Serial.println("Enter a new password");
      }
    }

    //assemble the password number
    if (PWokay == false && key >= '0' && key <= '9')
    {
      //if (PW == 0)  // not needed
      //{
      //  PW = key - '0';
      //}

      //else
      //{

        PW = PW * 10 + (key - '0');

      //}
    }
  }

} //END of            l o o p ( )


//******************************************************
void keypadEvent(KeypadEvent key)
{
  switch (keypad.getState())
  {
    //*********************
    //case PRESSED:
    //  {
    //  }
    //  break; //END of PRESSED

    //*********************
    case RELEASED:
      {
        switch (key)
        {
          //***************
          //only if there is a valid password
          case '*':
            if (PWokay == true)
            {
              {
                //LED OFF
                digitalWrite(ledPinWhite, HIGH);
              }
            }
            break;

          //***************
          //only if there is a valid password
          case '#':
            if (PWokay == true)
            {
              {
                //LED OFF
                digitalWrite(ledPinRed, HIGH);
              }
            }
            break;

        } //END of switch (key)
      }
      break; //END of RELEASED

    //*********************
    case HOLD:
      {
        switch (key)
        {
          //***************
          //only if there is a valid password
          case '*':
            if (PWokay == true)
            {
              {
                //LED ON
                digitalWrite(ledPinWhite, LOW);
              }
            }
            break;

          //***************
          //only if there is a valid password
          case '#':
            if (PWokay == true)
            {
              {
                //LED ON
                digitalWrite(ledPinRed, LOW);
              }
            }
            break;

          //***************
          //reset the lock
          case '0':
            {
              PWokay = false;
              PW = 0;
              Serial.println("");
              Serial.println("Enter a new password");
            }
            break;

        } //END of switch (key)
      }
      break; //END of HOLD

  } //END of switch (keypad.getState())

} //END of    k e y p a d E v e n  t ( )

//******************************************************

Edit:
Updated code

Thank you. I'll try that out in the morning.

Cheers

Updated code in post #7

@larry - what if I'm James Bond and my password is 007? :wink:

J-M-L:
@larry - what if I'm James Bond and my password is 007? :wink:

Still works:

Enter a new password
007*
Password is okay.
You can use * or # to control the LEDs, hold 0 to reset.

You might be thinking a zero cannot be in the password since it is used as reset but it can.
The HOLD case is looking for 'a period of time' therefore 'a short press' on the number 0 still works as expected.
007 = 7 on this side of the pond.

I thought James was being replaced by a woman.

.

So 7, 07, 007 or 0007 is the same? not according to MI6 :slight_smile:

(well and popular movie beliefs - cf WIkipedia - the 00 Section of MI6 is considered the secret service's elite. A 00 (typically read "Double O" and denoted in Fleming's novels by the letters "OO" rather than the digits "00") is a field agent that holds a licence to kill in the field, at his or her discretion, to complete any mission.

But that is ok, it was not the purpose of the exercise! The OP can use a char buffer instead of Math to hold the passcode

larryd:
Updated code in post #7

Thank you so much. I added the reset password code to the case RELEASED, and it works brilliant. Thank you so much. You are a legend :slight_smile:

Damien.

J-M-L:
So 7, 07, 007 or 0007 is the same? not according to MI6 :slight_smile:

(well and popular movie beliefs - cf WIkipedia - the 00 Section of MI6 is considered the secret service's elite. A 00 (typically read "Double O" and denoted in Fleming's novels by the letters "OO" rather than the digits "00") is a field agent that holds a licence to kill in the field, at his or her discretion, to complete any mission.

But that is ok, it was not the purpose of the exercise! The OP can use a char buffer instead of Math to hold the passcode

Everyone knows if James was going to use a password he would use 700.
This way he would fool the villains of SPECTRE. :wink:

Now if this keyboard was alpha numeric then, yes, a character array would be the way to go.

Seedler:
Thank you so much. I added the reset password code to the case RELEASED, and it works brilliant.
Damien.

If you make changes, let the community see what you are doing.

.

:slight_smile:

Note that there is no need to test PW for being 0 or not, the math formula PW = PW * 10 + (key - '0'); will work all the time as 0*10 is 0

Good one.
Someone ate their Wheaties today.

Ok I have added a change password function that is saved to eeprom. Problem is that I am using holding down zero to start it, which means I can't have zero in the password. Is there any way around this?

This is the updated code:

#include <Keypad.h>
#include <EEPROMex.h>

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {A0, A1, A2, A3}; //connect to the row pinouts of the keypad

byte colPins[COLS] = {4, 3, 2}; //connect to the column pinouts of the keypad

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

const byte relayOne = 8;
const byte relayTwo  = 9;

//Target password
unsigned int PassWord = 1234;
unsigned int newPassWord;

int address;

//Password number entered
unsigned int PW;

bool PWokay = false;

void setup()
{
  Serial.begin(9600);
  pinMode(relayOne, OUTPUT);
  pinMode(relayTwo,  OUTPUT);
  digitalWrite(relayOne, HIGH);      
  digitalWrite(relayTwo,  HIGH);    
  keypad.addEventListener(keypadEvent); //Add an event listener for this keypad
  newPassWord = EEPROM.readInt(address);
  Serial.println(newPassWord);
  if(newPassWord > 0){
    PassWord = newPassWord;
  }
  Serial.println("Enter password");
}

void loop()
{
  char key = keypad.getKey();
  if (key)
  {
    Serial.print(key);

    //check for a valid password
    if ((key == '*' || key == '#' || key == '0') && PWokay == false)
    {
      if (PW == PassWord)
      {
        PWokay = true;
        Serial.println("");
        Serial.println("Password is okay.");
      }

      else
      {
        PWokay = false;
        PW = 0;
        Serial.println("");
        Serial.println("Password is bad.");
        Serial.println("Enter password");
      }
    }

    //assemble the password number
    if (PWokay == false && key >= '0' && key <= '9')
    {
       PW = PW * 10 + (key - '0');
    }
  }
} 

void keypadEvent(KeypadEvent key)
{
  switch (keypad.getState())
  {
    case RELEASED:
      {
        switch (key)
        {
          //only if there is a valid password
          case '*':
            if (PWokay == true)
            {
              {
                //relayOne OFF
                digitalWrite(relayOne, HIGH);
                PWokay = false;
                PW = 0;
              }
            }
            break;

          //only if there is a valid password
          case '#':
            if (PWokay == true)
            {
              {
                //relayTwo OFF
                digitalWrite(relayTwo, HIGH);
                PWokay = false;
                PW = 0;
              }
            }
            break;

           case '0':
            if (PWokay == true)
            {
              {
                PWokay = false;
                PW = 0;
              }
            }
            break;
        } //END of switch (key)
      }
      break; //END of RELEASED

    //*********************
    case HOLD:
      {
        switch (key)
        {
          //***************
          //only if there is a valid password
          case '*':
            if (PWokay == true)
            {
              {
                //relayTwo ON
                digitalWrite(relayOne, LOW);
              }
            }
            break;

          //***************
          //only if there is a valid password
          case '#':
            if (PWokay == true)
            {
              {
                //relayTwo ON
                digitalWrite(relayTwo, LOW);
              }
            }
            break;

           case '0':
            if (PWokay == true)
            {
              {
                Serial.print("Enter new password: ");
                int address;
                unsigned long passWorddelay = millis();
                while(millis() - passWorddelay < 6000)
                {
                  char key = keypad.getKey();
                  if (key)
                  {
                    Serial.print(key);

                    if (key == '*')
                    {
                      EEPROM.writeInt(address,PW);
                      newPassWord = EEPROM.readInt(address);
                      PassWord = newPassWord;
                      Serial.print("New password: ");
                      Serial.println(newPassWord);
                      Serial.print("New password confirmed as: ");
                      Serial.println(PassWord);
                    }

                    //assemble the password number
                    if (PWokay == false && key >= '0' && key <= '9')
                    {
                      PW = PW * 10 + (key - '0');
                    }
                  }
                }
                PWokay = false;
                PW = 0;
              }
            }
            break;

        } //END of switch (key)
      }
      break; //END of HOLD

  } //END of switch (keypad.getState())

} //END of    k e y p a d E v e n  t ( )

In the example I posted, HOLD was used which looks for a button press for a period of time.

Therefore a quick press was accepted and 0 could be used in a password number.

PRESSED acts immediately therefore 0 cannot be used.

Use HOLD.

.

But I need it to check password first. Pressing * or # to check password and then holding zero doesn't work.

I kinda got it working by making a master password that could be used to change password.

It kinda worked, but sometimes saved different numbers from what I entered, and sometimes got stuck in an enter new password loop

I can't paste code at the min cos my broadband is down. I'll put it up as soon as I can

Cheers