ESP32 button interrupt executes on button release

Hello. I am developing an ESP32 project and I have set up an interrupt on a button press. When the button is pressed for 3 seconds, the ESP switches off. Here is the code I am using:

#include <arduino-timer.h>

auto timer{timer_create_default()};

void powerOffDevice(void)
{
    digitalWrite(MCU_POWER_LED, HIGH);
    digitalWrite(MCU_DATA_LED, HIGH);
    digitalWrite(MCU_POWER_HOLD, LOW);
}

void IRAM_ATTR togglePower(void)
{
    timer.in(3000UL, [](void *) -> bool
             {
    if (digitalRead(MCU_BUTTON_PRESS) == LOW)
        powerOffDevice();
                        
    return false; });
}

void setup()
{
    pinMode(MCU_BUTTON_PRESS, INPUT_PULLUP);
    pinMode(MCU_POWER_LED, OUTPUT);
    pinMode(MCU_DATA_LED, OUTPUT);
    pinMode(MCU_POWER_HOLD, OUTPUT);
    attachInterrupt(digitalPinToInterrupt(MCU_BUTTON_PRESS), togglePower, FALLING);
}

void loop()
{
    timer.tick();
}

The problem is that powerOffDevice() is actually called when I release the button, after having pressed it for 3 seconds. Is there a way to call powerOffDevice() simply after 3 seconds of pressing the button?

Thanks in advance!

Using pinMode INPUT_PULLUP I assume the button is wired between the input pin and GND.
The interrupt routine is set to interrupt when the button is activated duw to "FALLING", when pressed down and directly going asleep.
I can't tell if entering sleep inside an interrupt routine is good.

The return false looks strange. To where is that flase returned?

Yeah, @Railroader sees that, so should the compiler

warning: 'return' with a value in function returning void

Go to the IDE and turn on compiler warnings, then heed the red ink.

Besides being an error, it is wrong as @Railroader points out - even if it was correctly returning a value, where woukd it go?

a7

1 Like

Where are the pin numbers defined?
Code does compile!

Please post the code you are actually using.

1 Like

It does not enter sleep, it switches off. MCU_POWER_HOLD acts as a power switch. I have tried a non-interrupt approach, using millis() inside loop, with the same results.

@alto777
This is required by the arduino-timer.h library. It tells the timer that the task will not repeat (I have also tried returning true and nothing at all, which throws a warning). The library code for the timer function is the following:

inline
    struct task *
    add_task(unsigned long start, unsigned long expires,
             handler_t h, T opaque, bool repeat = 0)
    {
        struct task * const slot = next_task_slot();

        if (!slot) return NULL;

        slot->handler = h;
        slot->opaque = opaque;
        slot->start = start;
        slot->expires = expires;
        slot->repeat = repeat;

        return slot;
    }

 Task
    in(unsigned long delay, handler_t h, T opaque = T())
    {
        return add_task(time_func(), delay, h, opaque);
    }

Here are the pin definitions:

#define MCU_POWER_LED 26
#define MCU_DATA_LED 25
#define MCU_BUTTON_PRESS 14
#define MCU_POWER_HOLD 12

Please Post the code you are actually using

Then why do you declare it as returning void?

void IRAM_ATTR togglePower(void)

That's an error on anything from an Arduino UNO to a MacOS desktop machine. A language error.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.