Detect a Button Press from Running Function


I am trying to detect a button press from inside a function (not the event handler itself).

I currently have 2 buttons, one to start the function running and one to interrupt the function. After pressing the Start button, it should disappear and the Cancel button should be visible and have the ability to cancel or stop the running function.

The Start button works fine, but i can either get the Cancel button to show or run the function() but not both.

What MCU/Processor/Board and compiler are you using?

M5Stack Core2 and Arduino IDE 2

What LVGL version are you using?

Latest version 8

What do you want to achieve?

If I was using Arduino, I would do something like -

void someFunction() {
  if (LOW == digitalRead(buttonA_GPIO) {
    do something;
  } else {
    do something else;

What have you tried so far?

if (lv_btn_get_state(btn) == 0) 


Hi @Damien_Norris ,

The function lv_btn_get_state() is an LVGL version 7 function, which is no longer available in LVGL version 8.

In version 8 there are generic states for objects which you can query instead using the lv_obj_has_state() function. See the documentation here & here for the details. :slight_smile:

lv_obj_has_state(btn, LV_STATE_PRESSED);

Kind Regards,


Hi Pete,

Thank you for getting back to me and please accept my most sincere apologies for not replying sooner (had to go do some work :frowning: ).

Although it works, to an extent, as I can either put an instruction directly into the button clicked event or a function and trigger button event using the lv_obj_has_state().

However, this is not really what I am trying to achieve. I currently have an app developed using LovyaGFX (sorry), and would like to transfer it over to LVGL, most of it is working fine with the exception of the buttons. The following snippet may demonstrate what I mean better than I can describe it.

void showStartScreen() {

  bool standby_mode = false;

  if (STATE_READY == currentState) {
    // RESET button
    if (LOW == digitalRead(buttonA_GPIO) || standby_mode) {
      // Debounced wait for release of RESET button
      if (!test_loop_mode) {
        while (LOW == digitalRead(buttonA_GPIO)) {

      size_t bytes_written;
      // Gate Rise
      i2s_write(SPEAKER_I2S_NUMBER, wavList[5], wavSize[5], &bytes_written, portMAX_DELAY);

      // Set Mic Mode

      currentState = STATE_ARMED;
	  // display START button

      // Remember this time to allow timeout
      timing_start_ms = millis();
if (LOW == digitalRead(buttonA_GPIO))

Is what I am trying to replicate, if it is possible, maybe I am misunderstanding something or just plain missing something.

Kind Regards


Hi @Damien_Norris ,

No need to apologise, we are all busy people no worries :slight_smile:

Are you trying to map the input of a hardware button to a button in the GUI? The code snippet suggests you may be polling a hardware button maybe?

Sorry I’m just trying to understand the context of what you are trying to achieve…

Kind Regards,


Hi Pete,

A funny thing happened on the way to answering your last question - it appears I had a heart attack and have spent just over a week in hospital. Soooo, as far as excuses go for not getting back sooner, I think that one is just about ok :rofl:

Not mapping an external hardware button, but attempting to use the M5Stack Core2 touch screen as a momentary switch and yes, there is a polling/interrupt - which I seem to remember reading somewhere isn’t easy/possible.

The buttonA_GPIO above is a way of making the whole M5Stack Core2 touch screen act as buttonA.

Hope that makes sense



Hi @Damien_Norris ,

I have sent you a private forum message. :slight_smile:

Kind Regards,