Manual stepper: How to stop/interrupt ongoing/future motion?

Basic Information:

Printer Model:
MCU / Printerboard: Manta M8P
Host / SBC: Mainsail
klippy.log

Fill out above information and in all cases attach your klippy.log file (use zip to compress it, if too big). Pasting your printer.cfg is not needed
Be sure to check our “Knowledge Base” Category first. Most relevant items, e.g. error messages, are covered there

Describe your issue:

Hi everyone,
I am new to klipper and developing a custom printer. I have successfully integrated all the kinematics and a manual stepper. I am now able to run the manual stepper in an asynchronous mode (which is what I needed in the first place).

I am looking for ways to control my manual stepper in between its motion, for example,

Consider a scenario,

I have a following command in my GCode:

MANUAL_STEPPER STEPPER=MY_STEPPER MOVE=100 SPEED=1 SYNC=0

When this command is executed in the middle of my GCode, the manual stepper starts rotating. Based on my application, I want to create a custom GCode such as “STOP_MANUAL_STEPPER” which once called will stop the rotation of the manual stepper irrespective of its position etc.

I want to add this custom GCode within a conditional loop to interrupt the motion of my manual stepper.

I would really appreciate some tips and tricks on how to achieve this motion control.

Thanks!

If I understood your requirement correctly, then this is not possible. Once a movement is queued, it is executed once it is time and cannot be prematurely interrupted.

1 Like

Thanks for your reply.

If the motion is executed, then there has to be a way to interrupt that motion in between. I mean mcu is sending pulses for a given time period at a given frequency, so there has to be a way to stop that pulses at any given time.

I do agree that it is not straightforward, but I do not agree that it is impossible.

I think what your looking for is something similar to a macro i wrote for homing filament using a runout sensor.
This is possible through the use of delated gcode macros.
Take for example this, the call to load_filament, triggers a delayed gcode by setting its duration

[gcode_macro LOAD_FILAMENT]
gcode:
   {% if not printer["filament_switch_sensor CP_Head_Sensor"].filament_detected %}
  {action_respond_info("AutoLoad Start")}
   UPDATE_DELAYED_GCODE ID=auto_load DURATION=0.8
   UPDATE_DELAYED_GCODE ID=auto_load_timeout DURATION=120
  {% else %}
  RESPOND TYPE=error MSG='Head sensor blocked, remove and try again'
  {% endif %}

The delayed gcode, repeats itself feeding the extruder untill the condition is met

[delayed_gcode auto_load]
gcode:
   {% if not printer["filament_switch_sensor CP_Head_Sensor"].filament_detected %}
   UPDATE_DELAYED_GCODE ID=auto_load DURATION=0.8
    G91
    G92 E0
    G1 E25 F2500 # fast-load
  {% else %}
   UPDATE_DELAYED_GCODE ID=auto_load DURATION=0
  {action_respond_info("AutoLoad Detected")}
  {% endif %}

This can also be interrupted by another macro such as adding a timeout that sets the delayed gcode duration back to 0, stopping it

[delayed_gcode auto_load_timeout]
gcode:
  RESPOND TYPE=error MSG='AutoLoad Failed – Check filament and try again'
  UPDATE_DELAYED_GCODE ID=auto_load DURATION=0

2 Likes

Hello @mjfsch !

Please use Preformatted Text for posting code instead of Blockquote.

  • It’s better to read
  • Leading spaces are not clipped off.

Format

2 Likes

In order to maintain synchronized moves of multiple steppers, once a move is initiated Klipper has no method for canceling the move.

You could, however, break your move into small pieces and send multiple small moves out of your conditional loop.

1 Like

I did not state that it is impossible. I stated that it is (currently) not possible.

Nice solution. The applicability to the OPs request depends on a few factors:

  • The filament loading is an “isolated” process and not dependent on synchronized movements
  • Depending on the needed precision and continuity of the movement, the “staggered” moves may or may not be suitable
1 Like

Thanks for your insights! Could you describe the logical sequence of the macros along with the objective?

The manual stepper I am using is isolated from the kinematics and its movements are asynchronous to other steppers. The primary function of this stepper is to apply high level of axial force (600 N), so I want to start the stepper once my printing begins. I want this stepper to rotate at fixed speed for some distance (a distance value for the given speed, resulting travel time way higher than total print time).

Aim is to finish the printing before this stepper completes its travel and interrupt the motion once the last line in the GCode is exceuted.

This is actually my last resort. But I want to believe that there might be a brute force way to interrupt single motion command :smile:

The macro example i posted, is a homing routine for a multi filament system, its triggered by filament been fed into a sensor and feeds till it triggers a second sensor.

I limited the example shown to the course feeding as it seemed more applicable the actual macro i us then removes filament using a much finer resolution movement to get a more precise position before putting it in a parking position.

Its worth noting that due to the timing and queuing of commands, this is not the most accurate, (especially during the course feeding) and is not a smooth movement.

Given the use case you have added above, im not sure if its the right fit, and im not too sure there is a method within klipper to do what you want.
You may be better off using an external controller e.g. Arduino or ESP32 that is triggered by a GPIO output from klipper driven high at print start and low at print end.

Emergency stops resets the MCU and stops everything. Leaves the printer in an error state though.

“Brute force” was authorized :grimacing:

You could also put a power controller on your machine and turn the whole thing off when the g-code completes

This seems a more elegant solution.

Not sure if this helps:
if you have a [manual_stepper] defined, you can define an endstop pin.

This endstop-Pin can physically be a button, a externaly driven relay, maybe simply a FET.
if the endstop pin is triggered, the manual_stepper stopps immediately and gcode gets resumed

idk your physical setup or what you are actually trying to achieve, but maybe this can help you…

  • cad435

Edit: Just read your post what you try to achieve with the 600N output - my guess is you can simpy hook up a digital pin from klipper which you set as output to another digital pin from the same MCU which then gets used as “endstop”

therefore if the last line of your gcode is to set the output pin to “high” the manual_stepper sees its “endstop” triggerd and should also halt.

Edit 2: just out of couriostiy: Are you using a stepper to “hold” some kind of power switch untill your print ends and if so, this switch gets released and the printer kills itself? :sweat_smile:

Could the endstop pin be a virtual pin?

Oh that I don’t know…

Unfortunately, virtual pins do nothing when commanded to home.