rwmingis / InterruptButton

This is an interrupt based button event library for the ESP32. It enables binding user defined actions to button events including 'Key Down', Key Up' , 'Key Press', 'Long Key Press' 'AutoRepeat Press' and 'Double-Click'. The actions associated it these events may be executed Asynchronously, Synchronously, or a Hybrid between the two.
MIT License
30 stars 8 forks source link

Cant disable AutoRepeatPress #17

Closed steiraa closed 10 months ago

steiraa commented 11 months ago

Hello, I have the following code:

prevButton.disableEvent(Event_AutoRepeatPress);
prevButton.disableEvent(Event_DoubleClick);
prevButton.disableEvent(Event_KeyDown);
prevButton.disableEvent(Event_KeyUp);

prevButton.bind(Event_KeyPress, 0, &prevEventHandler);
prevButton.bind(Event_LongKeyPress, 0, &longPrevEventHandler);

void prevEventHandler(void)
{

  Serial.println("prev pressed");
}

void longPrevEventHandler(void)
{

  Serial.println("long prev pressed");
}

But whenever I longpress a button, the Autorepeatpress also triggers(When i set the Autorepeatpress Interval to a high value, it "works")

This is the response from my ESP32, when i only press and hold the button for a few seconds:

long prev pressed
prev pressed
prev pressed
prev pressed
prev pressed
prev pressed
prev pressed
rwmingis commented 11 months ago

Hi steiraa,

I'm at work atm and not able to go through the code at the moment, but the following should sort it out in the near term.

// Try one or both of the below 2 lines
prevButton.disableEvent(Event_All);                                // This disable all events associated with that button
prevButton.bind(Event_AutoRepeatPress, nullptr);         //  Inside the library, if the function is undefined, then it doesn't even try to call it

// Then carry on as before.
prevButton.bind(Event_KeyPress, 0, &prevEventHandler);                 // Event automatically enabled when binding an action
prevButton.bind(Event_LongKeyPress, 0, &longPrevEventHandler);  // Event automatically enabled when binding an action

Worth trying this and letting me know how you go. If the event is 'undefined' by binding a nullptr instead of a function pointer, then the library should never call it. If it continues, then something else is probably happening elsewhere in the main code?

Cheers.

rwmingis commented 11 months ago

Actually, can you send me the minimal code to reproduce the issue? I just had another look, and the bit I suggested about disableEvent(Event_All) doesn't flush the mask like my memory said it did so that won't fix it.

Also, if the Event_AutoRepeatPress event is enabled, but you don't bind a function to the AutoRepeatPress event, it just uses the function alreayd bound to Event_KeyPress event as default.

steiraa commented 11 months ago

Hello, thanks for the quick replay!

Sadly all of your fixes didnt work for me. I attached the full code to reproduce the issue and a video showcasing it.

The prevButton.disableEvent(Event_All); command disables any event with the Button, I dont even get normal Event_KeyPress anymore.

#include "InterruptButton.h"
#include <Arduino.h>
#define PREV_PIN 2

InterruptButton prevButton(PREV_PIN, LOW);

void prevEventHandler(void);
void longPrevEventHandler(void);

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

  InterruptButton::setMode(Mode_Asynchronous);

  // prevButton.disableEvent(Event_All);
  prevButton.disableEvent(Event_DoubleClick);
  prevButton.disableEvent(Event_KeyDown);
  prevButton.disableEvent(Event_KeyUp);
  prevButton.disableEvent(Event_KeyPress);
  prevButton.disableEvent(Event_LongKeyPress);
  prevButton.disableEvent(Event_AutoRepeatPress);

  prevButton.bind(Event_KeyPress, 0, &prevEventHandler);
  prevButton.bind(Event_LongKeyPress, 0, &longPrevEventHandler);
  prevButton.bind(Event_AutoRepeatPress, nullptr);
};

void loop()
{
}

void prevEventHandler(void)
{

  Serial.println("prev pressed");
}

void longPrevEventHandler(void)
{

  Serial.println("long prev pressed");
}

https://github.com/rwmingis/InterruptButton/assets/114651979/cc3492a0-d540-4870-bf38-87b70a8c8510

I am using Platformio and an AZ-Delivery ESP-32 Dev Kit C V4

rwmingis commented 11 months ago

Yes, it would appear something is amiss in the library. I think it relates to how the logic works around interpreting long presses and then the autorepeat. Has been a little while since I had to go in there. Will have a look on the weekend and let you know. 👍

On Wed, 22 Nov 2023, 2:56 am steiraa, @.***> wrote:

Hello, thanks for the quick replay!

Sadly all of your fixes didnt work for me. I attached the full code to reproduce the issue and a video showcasing it.

The prevButton.disableEvent(Event_All); command disables any event with the Button, I dont even get normal Event_KeyPress anymore.

include "InterruptButton.h"

include

define PREV_PIN 2

InterruptButton prevButton(PREV_PIN, LOW);

void prevEventHandler(void); void longPrevEventHandler(void);

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

InterruptButton::setMode(Mode_Asynchronous);

// prevButton.disableEvent(Event_All); prevButton.disableEvent(Event_DoubleClick); prevButton.disableEvent(Event_KeyDown); prevButton.disableEvent(Event_KeyUp); prevButton.disableEvent(Event_KeyPress); prevButton.disableEvent(Event_LongKeyPress); prevButton.disableEvent(Event_AutoRepeatPress);

prevButton.bind(Event_KeyPress, 0, &prevEventHandler); prevButton.bind(Event_LongKeyPress, 0, &longPrevEventHandler); prevButton.bind(Event_AutoRepeatPress, nullptr); };

void loop() { }

void prevEventHandler(void) {

Serial.println("prev pressed"); }

void longPrevEventHandler(void) {

Serial.println("long prev pressed"); }

https://github.com/rwmingis/InterruptButton/assets/114651979/cc3492a0-d540-4870-bf38-87b70a8c8510

I am using Platformio and an AZ-Delivery ESP-32 Dev Kit C V4 https://www.az-delivery.de/en/products/esp-32-dev-kit-c-v4

— Reply to this email directly, view it on GitHub https://github.com/rwmingis/InterruptButton/issues/17#issuecomment-1821197625, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALW24E2OJGFD3HZN46IVL2DYFTFKVAVCNFSM6AAAAAA7TQ3SOCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRRGE4TONRSGU . You are receiving this because you commented.Message ID: @.***>

rwmingis commented 11 months ago

OK, I sat down tonight and figured it out.

I originally thought it must have been a bug in the library, but I think the library is sound. It's just the implementation. Almost an undocumented feature. 😁

Soooooo, when you bind an action (a function) to an event (a key press, double click, etc.) that is associated with a button, the library thinks you want to of course enable that event/action by default, so it enables it. If you want to disable it, then you need to disable it AFTER you bind the actiont to the button's specific event.

So, I modified your code accordingly below. Let me know if this solves your issue and I will close out the issue.

Cheers!

#include <Arduino.h>
#include "InterruptButton.h"

#define PREV_PIN 2

InterruptButton prevButton(PREV_PIN, LOW);

void prevEventHandler(void);
void longPrevEventHandler(void);

//== MAIN SETUP FUNCTION ===========================================================================
//==================================================================================================

void setup() {
  Serial.begin(115200);                           // Remember to match platformio.ini setting here
  while(!Serial);                                 // Wait for serial port to start up

  InterruptButton::setMode(Mode_Asynchronous);

  prevButton.bind(Event_KeyPress, 0, &prevEventHandler);
  prevButton.bind(Event_LongKeyPress, 0, &longPrevEventHandler);
  prevButton.bind(Event_AutoRepeatPress, nullptr);    // This does clear the auto repeat press binding, but still enables the feature. 
                                                      // Because it has been enabled, but no special autoRepeat press function is bound to it,
                                                      // it defaults to using the action for regular keyPress because the function is similar.
                                                      // YOu can just delete this line unless you want to bind an autoREpeatePress action specific
                                                      // function that is different from a regular keypress.

  prevButton.disableEvent(Event_AutoRepeatPress);     // So you need to disable the autoRepeatPress event AFTER you define it if
                                                      // that is your intention to prevent it
}

//== MAIN LOOP FUNCTION =====================================================================================
//===========================================================================================================

void loop() { 
  if(InterruptButton::getMode() != Mode_Asynchronous) InterruptButton::processSyncEvents();

  // Normally main program will run here and cause various inconsistant loop timing in syncronous events.

  delay(2000);
}

void prevEventHandler(void)
{

  Serial.println("prev pressed");
}

void longPrevEventHandler(void)
{

  Serial.println("long prev pressed");
}
steiraa commented 11 months ago

Hey, sadly this code doesnt solve my issue. It behaves the same as before :(

I circumvented the problem by binding an empty function to Event_AutoRepeatPress at the moment

rwmingis commented 11 months ago

Did you copy and paste the code exactly from my last post? Because when I tried it, it did what you were saying (which is planned behaviour) until I called

prevButton.disableEvent(Event_AutoRepeatPress)

Immediately after binding the Event_AutoRepeatPress. Even binding a nullptr instead of a function will turn it back on. Because it's a nullptr, it just defaults to actioning whatever you bound to the regular keypress. Ie rapidfire of the regular keypress after a brief pause.

So there is no benefit to the line below unless clearing out a special rapidfire so you can go back to regular keypress rapid fire.

prevButton.bind(Event_AutoRepeatPress, nullptr)

If you haven't copied the code in my previous post exactly, then try that, upload it, and see if it still happens.

Cheers

rwmingis commented 11 months ago

Did you have any success with the code above?

steiraa commented 11 months ago

Hello, I will try it tomorrow, I'm on holiday right now

-------- Ursprüngliche Nachricht -------- Von: rwmingis @.> Datum: 25.11.23 04:51 (GMT+01:00) An: rwmingis/InterruptButton @.> Cc: steiraa @.>, Author @.> Betreff: Re: [rwmingis/InterruptButton] Cant disable AutoRepeatPress (Issue #17)

Did you have any success with the code above?

— Reply to this email directly, view it on GitHubhttps://github.com/rwmingis/InterruptButton/issues/17#issuecomment-1826205444, or unsubscribehttps://github.com/notifications/unsubscribe-auth/A3KXGS5S4HZOHT3QZGPWWOTYGFTNFAVCNFSM6AAAAAA7TQ3SOCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRWGIYDKNBUGQ. You are receiving this because you authored the thread.Message ID: @.***>

steiraa commented 10 months ago

Hey, yes i copied the code exactly from your post, the issue still exixts.

rwmingis commented 10 months ago

Wow, this has me a bit confused. Same code, two different bits of hardware, different behaviour.

Before I dive deeper, can you update the .h and .cpp files from the repository and see if its just an old source/header file? I have just looked through the current code and can't see how the flow can spill through in the current version if the Event_AutoRepeatPress is not enabled. The timers shouldn't even start, and if they did, it should get blocked by the private action() method.

After that, if it still happens, the next check would be to bind an empty dummy function to the Event_AutoRepeatPress event so this is used instead of the default keypress action for the Event_AutoRepeatPress event like below:

prevButton.bind(Event_AutoRepeatPress, 0, [](){ });

Yes, the autorepeatpress may still happen in your instance but it will do nothing which is a temporary workaround.

Thanks.

On Mon, 27 Nov 2023, 6:35 am steiraa, @.***> wrote:

Hey, yes i copied the code exactly from your post https://github.com/rwmingis/InterruptButton/issues/17#issuecomment-1823969228, the issue still exixts.

— Reply to this email directly, view it on GitHub https://github.com/rwmingis/InterruptButton/issues/17#issuecomment-1826877012, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALW24E7FCVTROKCPO565C5LYGOKWZAVCNFSM6AAAAAA7TQ3SOCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRWHA3TOMBRGI . You are receiving this because you commented.Message ID: @.***>

steiraa commented 10 months ago

Hey, it works now! The new file from ur repo fixed it! The difference maker was this change, I tested it.

Thanks for your fast and compentent help, kinda saved my project or at least helped a lot!

rwmingis commented 10 months ago

Ah, good, glad to see it's fixed. Was eating at me abit. That change that you mentioned was something I added out of Issue 18, not 100% that's it. Feel like it's more like where I forgot to put a mask in to check if the autoRepeatPress event was enabled before calling it. which i added in July of 2022. When did you download the original code? Bet that was it.

https://github.com/rwmingis/InterruptButton/blob/facd8a2203e848af6b0d26bcabdf29fb4d324b5a/InterruptButton.cpp#L219

https://github.com/rwmingis/InterruptButton/blob/facd8a2203e848af6b0d26bcabdf29fb4d324b5a/InterruptButton.cpp#L235

steiraa commented 10 months ago

I downloaded this release on the 20th Nov

rwmingis commented 10 months ago

Ok, I can see that bug fix didn't make it into that release apparenty if only by a day. Will do a new release today to save others strife. Thanks for your feedback! 👍