Macro for GPIO pin not releasing

I have an odd issue that I can’t seem to resolve. I have a really simple macro:

[gcode_button BUTTON_GPIO6]
pin: !pi:gpio6
press_gcode: 
    G4 P1000
    G0 X50 Y50 F60000
    G4 P50

and I have pulled GPIO6 up:

raspi-gpio get 6
GPIO 6: level=1 fsel=0 func=INPUT pull=UP

It’s a simple button, shorted to ground. Everything works fine if I press the button once. If I press it again, it doesn’t work. If I run QUERY_BUTTON button=BUTTON_GPIO6, it gets stuck in a state of PRESSED after the first press until it is pressed again.

Is this a bug or am I doing something wrong?
Oddly, if the gcode contains no substantial commands, if it is simply:

[gcode_button BUTTON_GPIO6]
pin: !pi:gpio6
press_gcode: 
  { action_respond_info("GPIO 6 was pressed") }

Everything works fine. No sticky button state. Is some callback not firing if the command takes time to complete somewhere? gcode_button.py, hasn’t changed much recently, so I suspect I’m doing something wrong.

Any ideas?

P.s tried it without dwell commands (G4), problem remains.

After a lot of digging. I am now convinced this is a Klipper bug. I’ll raised it.

Before opening a Github issue, wait until the topic has been verified here. Before that nobody will look into such a Github issue.

Edit: Except you analyzed the issue in such depth that you can point to faulty code or propose a solution.

Apologies if I jumped the gun, I have opened the issue - I have actually done some source-code debugging on this and can point to the problem in gcode_buttons.py and talk the issue, but unfortunately I’m not knowledgeable enough about the whole solution to fix it.

Am hoping someone who knows more can help, or I would have fixed it myself already. But I appreciate that you guys are swamped with issues. Even if someone can point me in the right direction I might be able to submit the PR.

It sounds like you need to specify a pullup in the pin configuration (eg, ^!pi:gpio6). Note that some versions of the rpi Linux gpio implementation will not be able to set the pullup and it’s difficult to tell which versions have that issue.

-Kevin

Hi, I’m still stuck with this issue. I’ve explicitly pulled that pin high. Trying both ^ (which didn’t seem to work), and doing it through raspi-gpio (which does work, and then klipper claims the pin correctly). But that still has the above issue.

I wouldn’t think this were a bug if it were not for the working scenario when the macro is short. One of the things I mentioned in the linked bug is that it works fine if you happen to release the button after the macro completes. Which is where I now think the bug resides.

If I hold my finger down on the button until after the macro completes, everything works fine. So somewhere, the release event from the pi mcu is being lost because the printer is busy running the macro and not listening for the release.

Any idea how that could be?

Zeonia did you find solution for the problem? I can confirm this issue, the gcode button stays in pressed condition if released while executing macro or gcode. If released after execution or moves, or button is pressed again(pressing gets ignored, of course), the release works again.

QUERY_BUTTON button=OFFSET_CAL_SENSE command confirms this, the reply says “PRESSED” even the pin is high for sure. I have fysically measured and made sure that the pin is pulled back up by the MCU (Pull down/to ground switch is used)

So, pin is pulled up, inverted, and it works as expected when testing the switch manually when its not executing anything.

[gcode_button OFFSET_CAL_SENSE]
pin: ^!PE4
press_gcode:MEASURE_STOP
#release_gcode:

I´m trying to use the gcode button for measuring offsets for multiple extruder nozzles (with tool change) but at the moment its impossible to get it working, because so much code is executing and the release of the “button” is ignored and it stays “PRESSED” condition, ones it’s pressed. (it’s really a touch sensing of the nozzle to a metal calibration cube… but basically functions as a switch).
That MEASURE_STOP is a macro that stops a movement (moves with delayed cgode → value to 0), records position, and starts next iteration of measurements.

Edit. Before anyone suggests that the delayd gcode is the problem, I say, I don’t thing so, the release is done later, when the dalayed gcode is no longer active.

I have tried G4 dwell and even keep the “BUTTON” pressed over the macro, and move the nozzle off in next macro.

It seems like if the macro, or other gcode executed, it self is making the pin change state, the rising edge is lost. I mean the actions are so close each other, the problem gets worse. I could imagine the problem may exist in other applications too, but only by coincidence.
In my case, macro commands G1 to move off the caribration cube, → contact is lost allmost at the same time → rising edge in the pin lost = “button” stays pressed and next measurement is not qoing to work.

I’m using ramps 1.4 as a MCU

Any help is appreciated.

Just to simplify, I tested following:

[gcode_button OFFSET_CAL_SENSE]
pin: ^!PE4
press_gcode =
		G91
		G1 Z5
		G90
		G1 X200 Y200 F1000

I had nothing else is running. If you just briefly press the “button”, just to start the code and release right away, the button stays pressed.

Send: QUERY_BUTTON button=OFFSET_CAL_SENSE
Recv: // OFFSET_CAL_SENSE: PRESSED

After a second time button pressed and released:
or
Button held pressed until the gcode is finished:

Send: QUERY_BUTTON button=OFFSET_CAL_SENSE
Recv: // OFFSET_CAL_SENSE: RELEASED

This is an obvious bug.

Could someone confirm this behavior? Not much setup needed.

If you have a question or think you’ve found an issue, you should create a new topic. Appending content to an old topic like this is unlikely to gather any responses.

Upon creating a new topic, be sure to include all the information requested (in particular the klipper log file).

Finally, to your question, buttons work fine for me.

-Kevin

I also stumbled over this with Klipper v0.11.0-299-gb1f597c5. I also noticed that the release script sometimes is run multiple times. Basically:

  • Firmware reboot
  • Press button
    → Gcode triggered as expected
  • QUERY_BUTTON button=unload_button → PRESSED
  • Press button
    → Gcode is not triggered
  • QUERY_BUTTON button=unload_button → RELEASED
  • Press button
    → Gcode triggered as expected
  • loop from here on

This is my config:

## Filament Sensor 1
[filament_switch_sensor runout_sensor]
switch_pin: gpio16
pause_on_runout: True

[gcode_button unload_button]
pin: ^gpio29 # remove the negation "!" for sensor v1 - use just PA10 as example
press_gcode:
  RESPOND PREFIX="Eject button pressed!"
  {% if (printer.print_stats.state != "printing")%} # requires [virtual_sdcard]   
    {% if (printer["filament_switch_sensor runout_sensor"].filament_detected == True)%}
       RESPOND PREFIX="Filament detected, unloading!"
       UNLOAD_FILAMENT     
    {% else %}]
       RESPOND PREFIX="No filament detected, loading!"
       LOAD_FILAMENT
    {% endif %}
  {% else %}
     RESPOND PREFIX="M117 Printing! Can't unload filament right now!"
  {% endif %}
  RESPOND PREFIX="Eject button completed"