Mimic Key press and Release Else If Statement

Hey guys, I'm hoping someone can help me.

I'm trying to make a little device that has four buttons on it which mimick keys on another device, these will require a key press and release command to be sent, originally I made this work using an IF statement however because the void loop continued the LED/output flickered so I changed it for an Else If statement however I can't work out how to add a key release command aswell, is this possible and if so how can I do this?

I'm using the LCD print command iso that I can see its working, Ideally when the keys are released I want it to flash

lcd.setCursor(0, 1); 
lcd.print("   Release 1   ");

This is the code I'm trying:

// read the state of the buttons:
  button1State = digitalRead(button1Pin);
  button2State = digitalRead(button2Pin);
  button3State = digitalRead(button3Pin);
  button4State = digitalRead(button4Pin);
  
  if (button1State == HIGH) 
  {
    digitalWrite(ledPin, HIGH);
    lcd.setCursor(0, 1); 
    lcd.print("    Button 1    ");
  }
  else if (button2State == HIGH) 
  {
    digitalWrite(ledPin, HIGH);
    lcd.setCursor(0, 1); 
    lcd.print("    Button 2    ");
  }
  else if (button3State == HIGH) 
  {
    digitalWrite(ledPin, HIGH);
    lcd.setCursor(0, 1); 
    lcd.print("    Button 3    ");
  }  
  else if (button4State == HIGH) 
  {
    digitalWrite(ledPin, HIGH);
    lcd.setCursor(0, 1); 
    lcd.print("    Button 4    ");
  }    
  else 
  {
    digitalWrite(ledPin, LOW);  
    lcd.setCursor(0, 1);
    lcd.print("     Ready!     "); 
  }

I can make this work using one button but its the four that is troubling me.

I think you should have an if / else for each key. If the screen flickers it's because you're writing to it over and over as long as the button is held down so fast it makes it flicker. Do you want to send the key press over and over and over as fast as you can while the key is held down or do you want to send it once only when the key first becomes pressed?

Hey! Its not flickering now that I’m using the code shown however I can’t send the release command.

I want to send it once,

Basically when a button is pressed I want a command sent and when it is released I want a different command sent like a keystroke but I’m not sure how to achieve this

Then you're going to have to go back to an if / else for each button instead of the else-if way you have it now. IF you'd answer the last question in my post I'd get you closer.

You need to think in terms of state changes. You want to send a release when the key was pressed last time you read it but isn't this time. Look at the "State Change Example" that comes with the IDE for some inspiration. Whether or not you also need to do the same thing for the presses depends on the answer to that last question in my last post.

its easier to do this in 2 parts.

read the keys then deal with the results

example:

  // add    byte prevbutton = 0; to global
  byte button1State = digitalRead(button1Pin);
  byte button2State = digitalRead(button2Pin);
  byte button3State = digitalRead(button3Pin);
  byte button4State = digitalRead(button4Pin);

  byte button = 0;//last line wins so if no buttons pressed
  // then button will remain at 0

  if (button1State == HIGH) {
    button = 1;
  }
  else if (button2State == HIGH) {
    button = 2;
  }
  else if (button3State == HIGH) {
    button = 3;
  }
  else if (button4State == HIGH) {
    button = 4;
  }

  if (button != prevbutton) {//if button has not changed
    // since last time this ran (thats a bit like do this once)

    lcd.setCursor(0, 1);//set cursor once

    switch (button) {//button number = case number at this point
      case 0:
        digitalWrite(ledPin, LOW);
        lcd.print("     Ready!     ");
        break;
      case 1:
        digitalWrite(ledPin, HIGH);
        lcd.print("    Button 1    ");
        break;
      case 2:
        digitalWrite(ledPin, HIGH);
        lcd.print("    Button 2    ");
        break;
      case 3:
        digitalWrite(ledPin, HIGH);
        lcd.print("    Button 3    ");
        break;
      case 4:
        digitalWrite(ledPin, HIGH);
        lcd.print("    Button 4    ");
        break;
    }
  }
  prevbutton = button;//now they are equal so
  // if (button != prevbutton) will be false unless different button pressed
}

the only down side to this type of code is only one key can be pressed at any time but as you are printing to the same area of the lcd im presuming that you only want one key to be used at a time (extra code could be added to ensure only one key is pressed as the key furthest down the program will be the one that is used otherwise)

Hey guys, thanks for the replies, although it's not the quiet what I need.

Im confused Detla-G, what questions didn't i answer?

I want the command to be sent once on each keypress and a different command to be sent when each key is released and nothing to be sent the rest of the time.

I don't think I'm explaining myself well, what I need is this:

When key 1 is pressed:
print.LCD("key1 pressed");
delay(50);
Break;

When key 1 is released:
print.LCD("key 1 released");
delay(50);
Break;

When key 2 is pressed:
print.LCD("key 2 pressed");
delay(50);
Break;

When key 2 is released:
print.LCD("key 2 released");
delay(50);
Break;

Etc

The key could be pressed for two mins or .5 of a second the LCD should only do anything when it is pressed or released. Just like a key on a keyboard.

Basically this is to turn a light on and off using another price of hardware but it needs a keypress and a key release command to work.

I don't think I'm explaining myself well, what I need is this:

You still aren't. When is NOT a C++ statement.

You can perform actions if a switch is pressed, while a switch is pressed, or if a switch has become pressed. When is a meaningless term.

hey jifop :slight_smile:

i think i basically understand what you want to do:

if a button is pressedDown
do something
if a button is releasedUp
do something

so you want to react on the event of pressing down or releasing up.

in the basics a micro controller does not know about events - it only knows about a state.
an event occurs if the state changes - i think the easiest way is to handle something like this with a state-machine:

(code is untested)

// possible states
const uint8_t BUTTON_STATE_IDLE = 0;
const uint8_t BUTTON_STATE_PRESSED = 1;

uint8_t button1_state = BUTTON_STATE_IDLE;

void loop() {
    // get current button state:
    button1_raw = digitalRead(button1_pin);

    // with this if you can change the behaivior -
    // (is your button active when you read 0 or active when you read 1?)
    // that is explained in https://www.arduino.cc/en/Tutorial/Button
    uint8_t button1_state_current = BUTTON_STATE_IDLE;
    if (button1_raw == true) {
        button1_state_current = BUTTON_STATE_PRESSED;
    } else {
        button1_state_current = BUTTON_STATE_IDLE;
    }

    // button1
    // check for event (= change in button state)
    if (button1_state_current != button1_state) {
        // check if button is released
        switch (button1_state) {
            case BUTTON_STATE_PRESSED: {
                // button was pressed and now is released
                button1_state = BUTTON_STATE_IDLE;
                // here you can add your print or other things..
            } break;
            case BUTTON_STATE_IDLE: {
                // button was released and now is pressed
                button1_state = BUTTON_STATE_PRESSED;
                // here you can add your print or other things..
            } break;
        }
    }

    // button2
    // ...
}

if you now getting multiple release and press events than your hardware button is bouncing.
there is a nice example for debouncing
and you can include this in the state-machine:

// possible states
const uint8_t BUTTON_STATE_IDLE = 0;
const uint8_t BUTTON_STATE_WAITFORBOUNCE = 1;
const uint8_t BUTTON_STATE_ACTIVE = 2;

uint32_t button_debouncetime = 20;  // ms


uint32_t button1_starttime = 0;
uint8_t button1_state = BUTTON_STATE_IDLE;

void loop() {
    // get current button state:
    button1_raw = digitalRead(button1_pin);

    // with this if you can change the behaivior -
    // (is your button active when you read 0 or active when you read 1?)
    // that is explained in https://www.arduino.cc/en/Tutorial/Button
    uint8_t button1_state_current = BUTTON_STATE_IDLE;
    if (button1_raw == true) {
        button1_state_current = BUTTON_STATE_ACTIVE;
    } else {
        button1_state_current = BUTTON_STATE_IDLE;
    }

    // button1
    // check for event (= change in button state)
    switch (button1_state) {
        case BUTTON_STATE_IDLE: {
            if (button1_state_current == BUTTON_STATE_ACTIVE) {
                // button was released and now is pressed
                button1_state = BUTTON_STATE_WAITFORBOUNCE;
                button1_starttime = millis();
            }
        } break;
        case BUTTON_STATE_WAITFORBOUNCE: {
            // wait untill debounce time is over
            uint32_t duration = millis() - button1_starttime;
            if (duration > button_debouncetime) {
                button1_state = BUTTON_STATE_ACTIVE;
                // event Button DOWN
                // here you can add your print or other things..
            }
        } break;
        case BUTTON_STATE_ACTIVE: {
            if (button1_state_current == BUTTON_STATE_IDLE) {
                // button was pressed and now is released
                button1_state = BUTTON_STATE_IDLE;
                // here you can add your print or other things..
                // event Button UP
            }
        } break;
    }

    // button2
    // ...
}

there are some libraries that handle all this nicely...
for example you can check my own implementation:
slight_ButtonInput :wink:

hope that helps you a bit

sunny greetings
stefan

the code in post 4 will print when key is pressed. Add a flag at the same time to monitor for the key being released then have the flag one time print that the key is released and remove the flag.

can be something as simple as adding flag=1; to the button one switch/case

then add

if (on1State == LOW && flag==1){
// print button one released
flag=0;
}

do you have pull down resistors on the buttons pins. If not you should look at INPUT_PULLUP as a option. Also look at adding de-bounce to the buttons