简体   繁体   中英

Button press and hold detection in microcontroller

I'm trying to implement a logic to detect a keypress and hold from a RF remote. Currently I'm able to detect the button press in my controller RF receiver. I'm getting the interrupt callback for every press. Now how do I detect a press and hold for 5 sec in the code?

I checked in the oscilloscope that when I press and hold a key in remote, I get the RF data in my receiver every 34ms.

All I can think of is to count the number of sequential interrupts with the same data in 5 secs and validate it but I'm not sure its the right way.

Any suggestions how to implement it. I will try it.

Thanks

First of all, depending on what RF technology you are using, you may not be getting the response in real-time. Some RF technologies have relatively long latency/propagation delay and many can't guarantee real-time at all. You may want to take this in account by measuring with a scope the time between the physical key press in the transmitter until the time when that key press is detected in the receiver.

Also we have to assume that the button is properly debounced on the transmitter side, or you'll be getting lots of garbage sent through the air.

Possible method 1:

  • Use a cyclic timer interrupt which reads the state of the button once every 50ms or so. You can use a counter variable which is increased by 1 if the button is pressed or set to zero if the button is released.

Possible method 2:

  • Upon getting the first keyboard interrupt, assuming it fires on rising edge, change that interrupt to now trigger on falling edge. Then start a timer and ensure that no interrupts fire during the time that timer was running.

    Some MCU timer peripherals support input capture on both edges, so you could implement various alternative methods to the above based on that.

Possible method 3:

  • If using some simple OOK stuff and the transmitter remains asleep until a button is pressed, you may be able to simply record RSSI over time by using whatever provided RSSI feature the RFIC got. But this way you need some means to detect that it was actually your transmitter that caused the RSSI to go up.

A good idea with any button, direct, or as in this case remote, is to detect both press and release. Then apply the press and hold timing on top of that. In that way physical and remote buttons can be handled in the same manner.

In this case you could detect release by setting a 50ms timer that is restarted in every 35ms button interrupt. Then if the 50ms timer expires, the button has been released (or gone out of range).

Then for the 5 second hold, you could have 5 second timer that can be started in button down, and cancelled on button release. Similarly, if that timer expires you trigger the hold event.

The timers could be implemented in software or hardware, although it might be a poor use of resources to dedicate two hardware timers to one button.

See also Pressing button for 3 seconds and how to measure its time with Atmega8 1MHz? . Given press/release detection as described above, you could apply the higher level hold timing as in the accepted answer to that question.

Thank you all so much for the suggestions. I implemented the logic based on the suggestion given by users "the busybee, Clifford and Lundin" and it is working now. Please have a look.

void ISR_callback(uint32_t value) //Button press ISR
{
   button_data = (uint8_t)((value>>8) & 0xF);
   
   if(button_data == 0xB) //required button pressed
   {
      button_pressed = 1;
      button_timer_50ms = 0; //reset the independent 50ms counter, if button pressed
   }
 }

void main(void)
{
    while(1)
    {
        if (one_ms_time_expired()) //1ms timer loop
        {
          if(button_pressed) //is set in ISR, if button is pressed
          {
              timer_5sec++; //Counter to check if key is pressed for 5 sec
              button_timer_50ms++; //Independent counter to reset status if button is released

              if(button_timer_50ms==50) //if no key pressed for 50ms, reset all status
              {
                    button_timer_50ms = 0;
                    button_pressed = 0;
                    timer_5sec = 0;
                    button_data = 0;
              }
              if(timer_5sec == 5000) //5sec done
              {
                    timer_5sec = 0;
                    button_data = 0;
                    button_pressed = 0;
                    button_timer_50ms = 0;
                    //Buzzer_ON
              }
           }
        }
     }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM