Load/Unload filament to sensor detection

Hi,
They assemble a multi-material filament exchanger. Everything is already functional and tested.

One of the functions I wanted to use was to load and unload the filament when changing the material to detect the end switch, which would ensure that the filament really got out of the path of another filament.

Using [gcode_maco] this is not possible in the {% for %} loop because the switch state cannot be updated.

It would be worth considering to use the “endstop_pin” option and g-code e.g.


[extruder]
...
endstop_pin: PA5
max_length: 500

MOVE_FILAMENT  EXTRUDER=<config_name> STOP_ON_ENDSTOP= [0|1]
# [ 0 -forward | 1 -back ]
  • similar to [manual_stepper]

I am willing to test a module under development for Klipper.

Thanks
-Peter

  • here are functional macros for load/unload filament without using a switch.

Just spitballing:

  • Look at how Happy Hare or similar system solved it
  • “Misuse” the filament sensor or gcode button setting to trigger follow-up macros

Hi, can you leave links here?

Are we a bit lazy? :stuck_out_tongue:

[gcode_button]
I tried, but in the {% for %} loop it is not possible to read its current state.

[filament_switch_sensor]
hmm… I have to think and try it, but I’m afraid I’ll run into the same problem as above.

I’m not sure why you would need this in a for-loop. When you have defined a gcode button Klipper will monitor it and react with the press_gcode / release_gcode.

So in theory, the press_gcode should get executed when filament enters your “splitter” and the release_gcode when a filament leaves it.

I wanted to do this idea - move the filament until the switch is activated

### load filament to activation switch  
  
        {% set  step = 15|int %}                # number of repeat
        {% set  repeat_length = 5|int %}   # in mm
       
        {% for count in range(0, step) %}              
           {% if  printer['gcode_button safety_switch'].state == 'PRESSED' %} 
             M83
             G92 E0             
             G1 E{repeat_length}   F1200   
           {% endif %}  
        {% endfor %}    
  • unfortunately for-loop cannot read current state [gcode_button]

If you separate the code to verify the filament sensor state into a separate macro, the new macro will have an updated state as soon as you run it. That’s what I did when developing the macros for the 3MS multimaterial system.

Hi, I tried that too. It used to be solved smoothly by loading / unloading the filament without the need to know the required length for sensing.

Why not solve it at the Klipper level?
It would certainly be suitable for all kinds of Multi-material changers.

The solution will be elegant, smooth and independent of the length parameter or ‘max_extrude_only_distance’.

-Petr

HI,
I tried replacing the [extruder_stepper] with the [manual_stepper ] configuration and found it to be a function that would fit except for these flaws:

  • [manual_stepper ] is not synchronous with [extruder]
  • if the defined value of MOVE or SET_POSITION is for example 300 mm, the motor will stop at end_stop, but there will be a pause before processing the next code. (the motor is probably doing the MOVE virtually, but is no longer physically spinning)

Example:


  ### load filament to end_stop pin
       MANUAL_STEPPER STEPPER=manual_0  ENABLE=1
       MANUAL_STEPPER STEPPER=manual_0  SET_POSITION=0  MOVE=300  SPEED=30  STOP_ON_ENDSTOP=-1
       MANUAL_STEPPER STEPPER=manual_0  ENABLE=0
	   
	   
  ### unload filament to end_stop pin
       MANUAL_STEPPER STEPPER=manual_0  ENABLE=1
       MANUAL_STEPPER STEPPER=manual_0  SET_POSITION=300  MOVE=0  SPEED=30  STOP_ON_ENDSTOP=1
       MANUAL_STEPPER STEPPER=manual_0  ENABLE=0

If the same principle could be applied to [extruder_stepper], everything would probably be solved

See if G-Codes - Klipper documentation helps

SYNC_EXTRUDER_MOTION is only for as extruder or extruder_stepper config section

This is true. You would need to use extruder_stepper instead of manual_stepper. Maybe I have not understood why you prefer the manual one over the dedicated extruder one, which seems a better fit.

I think you don’t understand that it was an experiment that demonstrated the load/unload filament function on the end_stop pin.

If ( SET_POSITION, MOVE, SPEED and STOP_ON_ENDSTOP ) could be used in the same way for the [extruder] configuration, then filament swapping on multi-material devices would be much smoother and safer.

This would require modifying the core Klipper code but I can’t do that,
I can only provide testing and feedback.

HI everyone,
I solved the function “Load/Unload filament to end stop switch” for configuration with setting for [manual_stepper].

         ### Define stepper 
          {% set target_material = user_vars.active.material|default(0)|int %}
          {% set man_stepper =  user_vars.switching[target_material].index %}           

         ### Example :{'park': 50, 'switch': 40, 'out':80, 'speed': 30}
         ### info picture: toolhead_4-in-1.png      
          {% set park  = init.end_stop.park|int %}      ; distance between park position and  end_stop switch
          {% set switch  = init.end_stop.switch|int %}  ; distance between end_stop switch and position when filament is outside extruder
          {% set out  = init.end_stop.out|int %}        ; distance between end of filament (nozzle, heatbreak, cutting) and position when filament is outside extruder    
          {% set speed  = init.end_stop.speed|int %}    ; load/unload speed in mm/s

         ### define max extrude steps
		  {% set act_extruder = printer.toolhead.extruder %}   
          {% set max_extrude = printer.configfile.settings[(act_extruder)].max_extrude_only_distance|int %}  
		  
#------------------------------- LOAD FILAMENT ------------------------------------------------------------------------------------   

        {% if action == 'load' %}  
          {% set step = (switch + out) // max_extrude|int %}
          {% set rest = (switch + out) % max_extrude|float %} 
          
          ### load filament to end_stop switch             
            MANUAL_STEPPER STEPPER={man_stepper}  SET_POSITION=0  MOVE={(park + 10 )}  SPEED={speed}  STOP_ON_ENDSTOP=-1
            
          ### load filament to extruder            
           MANUAL_STEPPER STEPPER={man_stepper}  SET_POSITION=0  MOVE={(switch + out) }  SPEED={speed}  SYNC=0
           
           M83
           G92 E0                
           {% for n in range(step) %}
             G1 E{max_extrude} F{speed*60} 
           {% endfor %}	
           {% if rest > 0.0 %}
              G1 E{rest } F{speed*60}
           {% endif %}  
           M400
		   
 #------------------------------- UNLOAD FILAMENT ------------------------------------------------------------------------------------   
 
        {% elif action == 'unload' %}
          {% set step = (out) // max_extrude|int %}
          {% set rest = (out) % max_extrude|float %} 
          
         ### unload filament from extruder
          MANUAL_STEPPER STEPPER={man_stepper}  SET_POSITION=0  MOVE={(out)*-1}  SPEED={speed}  SYNC=0  
           
          M83
          G92 E0                
          {% for n in range(step) %}
            G1 E{max_extrude *-1} F{speed*60}
          {% endfor %}	
          {% if rest > 0.0 %}
           G1 E{rest*-1} F{speed*60}
          {% endif %}  
          M400
       
         ### unload filament to end_stop pin          
          MANUAL_STEPPER STEPPER={man_stepper}  SET_POSITION=0  MOVE={(switch + 10) *-1}  SPEED={speed}  STOP_ON_ENDSTOP=1 
          
         ### unload filament to park_filament position
          MANUAL_STEPPER STEPPER={man_stepper}  SET_POSITION=0  MOVE={(park)* -1}   SPEED={speed} 
          
     {% endif %}
	 

FYI @koconnor

If I would like to use synchronous movement and configuration for [extruder_stepper], it is not currently possible.

Please consider this as a feature enhancement for [extruder] e.g.

ACTIVATE_EXTRUDER EXTRUDER=config_name  [SET_POSITION=<pos>] [SPEED=<speed>] [ACCEL=<accel>] [MOVE=<pos> [STOP_ON_ENDSTOP=[1|2|-1 |-2]] [SYNC=0]]:
  • it would definitely make things simpler and clearer
 #------------------------------- LOAD FILAMENT ------------------------------------------------------------------------------------   

        {% if action == 'load' %}  
          
          ### load filament to end_stop switch    
            ACTIVATE_EXTRUDER EXTRUDER={act_extruder}  SET_POSITION=0  MOVE={park + 10}  SPEED={speed}  STOP_ON_ENDSTOP=-1
            
          ### load filament to extruder            
            ACTIVATE_EXTRUDER EXTRUDER={act_extruder}  SET_POSITION=0  MOVE={switch + out}  SPEED={speed}  
           
           
 #------------------------------- UNLOAD FILAMENT ------------------------------------------------------------------------------------   
        {% elif action == 'unload' %}
          
          ### unload filament from extruder
           ACTIVATE_EXTRUDER EXTRUDER={act_extruder}  SET_POSITION=0  MOVE=-{out}  SPEED={speed}   
         
          ### unload filament to end_stop pin          
           ACTIVATE_EXTRUDER EXTRUDER={act_extruder}  SET_POSITION=0  MOVE=-{switch + 10}  SPEED={speed}  STOP_ON_ENDSTOP=1 
          
          ### unload filament to park_filament position
           ACTIVATE_EXTRUDER EXTRUDER={act_extruder}  SET_POSITION=0  MOVE=-{park}   SPEED={speed} 
          
     {% endif %}

maybe change only the logic of u

STOP_ON_ENDSTOP=[1|2|-1|-2]

1|-1 will remain the same as for (manual_stepper) movement length - parameter SET_POSITION and MOVE

2|-2 the filament will move until it is activated switch regardless of the specified
parameter SET_POSITION and MOVE, possible here use the ‘max_length’ parameter in the configuration so that there was no infinite motion when there was not filament.

Is there anyone who could program it?
I can test it.

  • Petr

Hi,
it works properly but the problem is when for some reason the switch for MAUAL_STEPPER does not turn on

No trigger on manual_stepper switching_1 after full movement

Printing is canceled!
How to solve it so that printing just pauses?