# "Long press" button Macro

**URL:** <https://klipper.discourse.group/t/long-press-button-macro/14901>\
**Category:** Macros\
**Created:** [March 13, 2024, 8:36pm UTC](https://klipper.discourse.group/t/long-press-button-macro/14901 "2024-03-13T20:36:41Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gaolst](https://yyz2.discourse-cdn.com/free1/user_avatar/klipper.discourse.group/gaolst/32/10026_2.png) [@gaolst](https://klipper.discourse.group/u/gaolst)\
**Post date:** [March 13, 2024, 8:36pm UTC](https://klipper.discourse.group/t/long-press-button-macro/14901/1 "2024-03-13T20:36:41Z")

</div>

By default Kliper `gcode_button` supports only `press` and `release` actions,  
This configuration allow to extend `gcode_button` to recognize how long it was pressed and from that can derive what kind of action it should do, this way we can get multiple different actions from single button.

Provided sample have following behavior:  
if press and release of a button(trip a switch) in less than 2 sec - don’t do anything  
if we press-release took more than 2 sec but less than 4 sec - call action 1  
if we press-release took more than 4 sec but less than 10 sec - call action 2  
if we press-release took more than 10 sec - call action 3

How it works:  
When button is pressed - we are pushing current runtime of klipper to macro variable, when button will be released - we pool previously stored “press time” value from a macro variable and fetching current runtime then calculating duration and taking decision what to do.

If you will see that “release” action is called before “press” - just reverse pin configuration by removing “!”

Personally I think that existing `gcode_button` should extend it’s capabilities and should report not only `state` but also some timestamp of “last press” and “last release” so we could use it without additional workarounds.

P.S. currently this macro uses undocumented property to get runtime of a klipper, why this kind of property or usual “host time” it’s not available in `system_stats` or somewhere else I don’t know.

```auto
[gcode_button my_button_long_press]
description: sample "long press" button configuration
pin: !host:gpiochip0/gpio30
press_gcode:
  {% set current_timer = printer.toolhead.estimated_print_time %} 
  SET_GCODE_VARIABLE MACRO=my_button VARIABLE=last_press VALUE={current_timer}
  {action_respond_info("Press time: %.2f "% (current_timer))}

release_gcode:
  {% set duration = printer.toolhead.estimated_print_time - printer["gcode_macro my_button"].last_press|float %}
  {action_respond_info("duration: %.2f "% (duration))}
  {% if duration|float > 10.0 %}
      my_button_level3
  {% elif duration|float > 4.0 %}
      my_button_level2
  {% elif duration|float > 2.0 %}
      my_button
  {% else %}
      {action_respond_info("button didn't meet criteria it was too short press")}
  {% endif %}

[gcode_macro my_button]
description: This macro will be called if button pressed more than 2 sec
variable_last_press: 0.0
gcode:
  {action_respond_info("it was loong press of a button level 1")}

[gcode_macro my_button_level2]
description: This macro will be called if button pressed more than 4 sec
gcode:
  {action_respond_info("it was loong press of a button level 2")}

[gcode_macro my_button_level3]
description: This macro will be called if button pressed more than 10 sec
gcode:
  {action_respond_info("it was loong press of a button level 3")}

```

---

<div class="post-metadata">

**Author:** ![alt](https://avatars.discourse-cdn.com/v4/letter/a/e36b37/32.png) [@alt](https://klipper.discourse.group/u/alt)\
**Post date:** [March 21, 2025, 3:59pm UTC](https://klipper.discourse.group/t/long-press-button-macro/14901/2 "2025-03-21T15:59:15Z")

</div>

Inspired by your macro. Added 3 event approach with Click, Double click and Hold action

```auto
gcode_button red_button]
pin: ^!PB1
press_gcode:
  {% set current_timer = printer.toolhead.estimated_print_time %} 
  SET_GCODE_VARIABLE MACRO=red_button VARIABLE=press_start_time VALUE={current_timer}
  UPDATE_DELAYED_GCODE ID=red_button_hold DURATION=0.5
release_gcode:
  UPDATE_DELAYED_GCODE ID=red_button_hold DURATION=0
  {% set duration = printer.toolhead.estimated_print_time - printer["gcode_macro red_button"].press_start_time|float %}
# {action_respond_info("duration: %.2f "% (duration))}
  {% if duration < 0.5 %} # holdThreshold 
    {% set current_timer = printer.toolhead.estimated_print_time %} 
    {% set click_duration = current_timer - printer["gcode_macro red_button"].last_click_time|float %}
    
    {% if click_duration < 0.3 %} # doubleClickThreshold
      red_button_double_click
      
      UPDATE_DELAYED_GCODE ID=red_button_click DURATION=0
      SET_GCODE_VARIABLE MACRO=red_button VARIABLE=last_click_time VALUE=0
    {% else %}
      UPDATE_DELAYED_GCODE ID=red_button_click DURATION=0.3 # doubleClickThreshold
      SET_GCODE_VARIABLE MACRO=red_button VARIABLE=last_click_time VALUE={current_timer}
    {% endif%}
  {% endif%}

[gcode_macro red_button]
variable_press_start_time: 0.0
variable_last_click_time: 0.0
gcode:
  #do nothing just store variables
  
[delayed_gcode red_button_click]
gcode:
  {action_respond_info("Click")}
  {% if printer.idle_timeout.state in ['Idle','Ready'] and not printer.pause_resume.is_paused %}
    REPEAT_LAST_PRINT
  {% elif printer.idle_timeout.state in ['Idle','Ready'] and printer.pause_resume.is_paused %}
    RESUME
  {% elif printer.idle_timeout.state | upper == "PRINTING" %}
    PAUSE
  {% else %}
    {action_respond_info(printer.idle_timeout.state)}
  {% endif %}

[gcode_macro red_button_double_click]
gcode:
  {action_respond_info("Double click")}
	#add your Double click actions here
  
[delayed_gcode red_button_hold]
gcode:
  {action_respond_info("Hold")}
  #add your hold actions here
  

```

---

<div class="post-metadata">

**Author:** ![EmperorArthur](https://avatars.discourse-cdn.com/v4/letter/e/9fc29f/32.png) [@EmperorArthur](https://klipper.discourse.group/u/EmperorArthur)\
**Post date:** [March 23, 2025, 2:56pm UTC](https://klipper.discourse.group/t/long-press-button-macro/14901/3 "2025-03-23T14:56:48Z")

</div>

Long press was just added to master as an option to prevent false triggering, and to provide this functionality.

This works for both buttons and for run-out sensors.

The configuration option is “debounce\_delay”.

Edit: @garethky Your changes are already being useful.

---

<div class="post-metadata">

**Author:** ![hcet14](https://avatars.discourse-cdn.com/v4/letter/h/ecd19e/32.png) [@hcet14](https://klipper.discourse.group/u/hcet14)\
**Post date:** [March 23, 2025, 5:44pm UTC](https://klipper.discourse.group/t/long-press-button-macro/14901/4 "2025-03-23T17:44:41Z")

</div>

EmperorArthur is talking about [Debounce gcode\_button and filament\_switch\_sensor by garethky · Pull Request #6848 · Klipper3d/klipper · GitHub](https://github.com/Klipper3d/klipper/pull/6848).
