Feature Request - Filament Runout Trigger 'PAUSE' After 700mm extruded (distance_delay?)

Would like the ability to set the filament runout trigger to be a set extruded distance (distance_delay?)

when filament sensor triggers. Wait 700mm before triggering PAUSE


I second this request, I’ve wanted this feature for a while now. I have a direct drive extruder on my hotend, but bowden tube to route the filament to it. The filament sensor lives on the upstream side of the bowden tube because that makes mounting and wiring so much easier, but now I have this long length of filament in queue that just gets thrown out when the sensor trips.

1 Like

I was looking for the same thing to no avail so I had a crack at making it work with the existing macro functionality.

Usage: PAUSE_AFTER_D D={distance_in_mm}

PAUSE_AFTER_D gets the current extruded distance, adds the D parameter to it, then triggers a delayed_gcode that checks every second if the extruded distance has reached the endpoint yet.

I’ve only tested this so far as it pauses after D more mm have been extruded, resumes correctly and then will pause in the same manner after resuming.

Let me know how you go!

[gcode_macro PAUSE_AFTER_D]
description: Trigger to pause the print after a further 'd' mm has been extruded
variable_end_d: 0 #create variable "END_D" which is associated with the PAUSE_AFTER_D gcode macro
  {% set d_start = printer.print_stats.filament_used|float %} #starting point is whatever the filament used is when PAUSE_AFTER_D is called
  {% set d_end = (d_start + params.D|float)|float %} #end point is start + D parameter
  SET_GCODE_VARIABLE MACRO=PAUSE_AFTER_D VARIABLE=end_d VALUE={d_end} #write the end value to the END_D gcode variable to access later
  M117 Pause at {printer["gcode_macro PAUSE_AFTER_D"].end_d|round(2)}
  UPDATE_DELAYED_GCODE ID=PAUSE_AT_D DURATION=1 #trigger the delayed gcode below after 1 second

[delayed_gcode PAUSE_AT_D]
initial_duration: 0 #if initial_duration is zero, the delayed gcode won't start by default
  {% set d_current = printer.print_stats.filament_used|float %} #get the current filament used
  {% if d_current < printer["gcode_macro PAUSE_AFTER_D"].end_d %} #if we aren't at the stopping point
    M117 Stopping {d_current|round(2)} {printer["gcode_macro PAUSE_AFTER_D"].end_d|round(2)}
    UPDATE_DELAYED_GCODE ID=PAUSE_AT_D DURATION=1 #restart the timer on the delayed gcode
  {% else %}
    UPDATE_DELAYED_GCODE ID=PAUSE_AT_D DURATION=0 #set the delayed gcode duration back to zero so it doesn't keep triggering
  {% endif %}

To make this work with a filament runout sensor, use the following:

[filament_switch_sensor runout_sensor]
pause_on_runout: False #we dont want it to pause immediately
  #positions here are in printer coordinates eg if you have a 300mm bed and your sensor is 7cm past the 
  #max y position then y_offset should be 370
  {% set x_offset = 150 %}  #approximate x location of the runout sensor
  {% set y_offset = 370 %}    #approximate y location of the runout sensor
  #z location not used but this can be easily extended to include a z offset if needed

  {% set current_x = printer.toolhead.position.x %}
  {% set current_y = printer.toolhead.position.y %}

  {% set distance = ((x_offset - current_x)**2 + (y_offset - current_y)**2)**(1/2) %}
  PAUSE_AFTER_D D={distance}

switch_pin: !PC1 #change this to the pin your runout switch is hooked up to

The stuff before the PAUSE_AFTER_D command in the runout_gcode is optional and should be commented out/deleted if not used. If you do this you’ll need to hardcode the distance in the call to PAUSE_AFTER_D. Don’t touch variable_end_d in the PAUSE_AFTER_D definition in the previous post. That’s used by the macro to set the end point relative to the current total filament extruded when PAUSE_AFTER_D is called.

Would you mind helping me out with this? I have a bed slinger that has a 300x300 bed and a max z of 380 (compensating for the z offset of my BLTouch). How would I add the z offset as my sensor is located on top of my enclosure (approximately 7cm higher than max z)?

{% set x_offset = 0 %}  #approximate x location of the runout sensor
{% set y_offset = 0 %}    #approximate y location of the runout sensor
{% set z_offset = 450 %}    #approximate z location of the runout sensor

{% set current_z = printer.toolhead.position.z %}

{% set distance = ((x_offset - current_x)**2 + (y_offset - current_y)**2 + (z_offset - current_z)**2)**(1/2) %}

Does that look correct? I want it to be dynamic and not a set extrusion distance.
Thank you in advance for the help.

Yep I think you have the right idea here, though I don’t think the BLTouch offset is relevant as that offset will already be handled by the homing routine. I assume your actual max z is 400? If so you’d want to set z_offset to 470. If the sensor is on the far left hand side of the printer then you’ll be fine with x_offset = 0, otherwise you’ll want to update that with the x location of the sensor. The y component of the distance doesn’t need to be dynamically calculated as on a bedslinger the y distance between the toolhead and the sensor should be fixed. Set y_offset to this distance and then change the y component of the distance calculation to just y_offset**2

Thank you I got it working perfectly! Took me a while because my smart filament sensor died and I had to make a new runout sensor from an end-stop I had laying around.