# filament states: # is_ready_to_print - # load_state # hotend_filament - the filament currently in the hotend. Set to the current loaded filament # loaded_filament - the filament spool which is currently connected to the extruder. Modifiable when filament is # heater_state - cold, heating, heated # if the heater state is 'heated' on printer boot, # and the current hotend and bed temperature is within 15c of the set temperature, then turn the heaters back on. [filaments] on_set_filament_gcode: # A list of G-Code commands to execute after the SET_FILAMENT macro runs. See # docs/Command_Templates.md for G-Code format. These parameters are passed # to the gcode: # * 'EXTRUDER' - the name of the extruder. 'extruder', 'extruder1' etc. # * 'T' - the integer index of the extruder # * 'PRESET' - the filament preset that was just assigned to th extruder # * 'LAST_PRESET' - the filament preset that was previously assigned to the extruder, if any on_clear_filament_gcode: # A list of G-Code commands to execute after the CLEAR_FILAMENT macro runs. See # docs/Command_Templates.md for G-Code format. These parameters are pass to the gcode: # * 'EXTRUDER' - the name of the extruder. 'extruder', 'extruder1' etc. # * 'T' - the integer index of the extruder # * 'LAST_PRESET' - the filament preset that was previously assigned to the extruder, if any [gcode_macro QUERY_FILAMENT] description: Prompts the user to select a filament, and sets the value of filament_extruder to that filament gcode: {% set response = params.RESPONSE|default(False) %} {% set name = params.NAME|default(False) %} {% set return_macro = params.RETURN_MACRO|default(False) %} {% if not response %} RESPOND TYPE=command MSG="action:prompt_begin Select Filament" {% for filament_name in printer.filaments.presets|map(attribute='name',default='None') %} RESPOND TYPE=command MSG="action:prompt_button {filament_name}|QUERY_FILAMENT {rawparams} NAME={filament_name} RESPONSE=True|primary" {% endfor %} RESPOND TYPE=command MSG="action:prompt_show" {% else %} # close the dialog RESPOND TYPE=command MSG="action:prompt_end" SET_EXTRUDER_FILAMENT NAME={name} # if we've specified a return macro, run this next. {% if return_macro %} {return_macro} {% endif %} {% endif %} [gcode_macro UNPRIME_FILAMENT] description: Unprimes the filament, leaving it in a state where it can be unloaded without changing temperatures gcode: {% set svv = printer.save_variables.variables %} {% set unload = params.UNLOAD|default(False) %} {% if svv.filament_load_state == "primed" %} # check if there is a valid value for the currently loaded filament. if not, prompt the user for it. {% if svv.filament_extruder == 'None' %} # if there isn't a set loaded filament, run QUERY_FILAMENT QUERY_FILAMENT RETURN_MACRO=UNPRIME_FILAMENT {% else %} SET_FILAMENT_LOAD_STATE STATE="processing" # tell the end macro wether to call the unload macro after this SET_GCODE_VARIABLE MACRO=END_UNPRIME_FILAMENT VARIABLE=unload VALUE={unload} # If the extruder was cold, keep it cold after finishing. SET_GCODE_VARIABLE MACRO=END_UNPRIME_FILAMENT VARIABLE=etemp VALUE={printer['extruder'].target} # set temperature of extruder # if in auto mode, set temperature and wait. Otherwise wait for the set temperature if it it's above 25c. {% if svv.heater_mode == "auto" %} SET_TEMPERATURE_AND_WAIT HEATER=extruder TARGET={printer['extruder'].filament.extruder} MODE=auto {% elif printer['extruder'].target > 25 %} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={printer['extruder'].target|float - 1} MAXIMUM={printer['extruder'].target|float + 2} {% endif %} # run the loop to retract until the switch is no longer pressed CLEAN_NOZZLE # mini purge to ensure filament remains connected _CLIENT_LINEAR_MOVE E=10 F={60*20} _CLIENT_LINEAR_MOVE E=-30 F={60*30} UPDATE_DELAYED_GCODE ID=LOOP_UNPRIME_FILAMENT DURATION=0.15 # retract filament until the button is no longer pressed {% endif %} {% else %} {action_respond_info("unable to unprime filament. Current filament state: %s " %(svv.filament_load_state))} {% endif %} [delayed_gcode LOOP_UNPRIME_FILAMENT] # Retracts filament until the extruder_exit button is no longer pressed gcode: {% if printer["gcode_button extruder_exit"].state == "PRESSED" %} G0 E-2 F{20*60} # retract by -2mm at 20mm/s (0.1s) UPDATE_DELAYED_GCODE ID=LOOP_UNPRIME_FILAMENT DURATION=0.15 # really long wait here. Otherwise klipper gets angry and queues up moves or something. {% else %} END_UNPRIME_FILAMENT {% endif %} [gcode_macro END_UNPRIME_FILAMENT] description: Called by LOOP_UNPRIME_FILAMENT, finishes up unpriming the filament. variable_etemp = 0 variable_unload = False gcode: # set temperature to what it was before SET_HEATER_TEMPERATURE HEATER='extruder' TARGET={etemp} MODE=auto # set filament state SET_FILAMENT_LOAD_STATE STATE="loaded" # if we want to unload after this, do so {% if unload %} UNLOAD_FILAMENT {% else %} # reload filament by an extra 10mm to press the button again _CLIENT_LINEAR_MOVE E=10 F={60*60} {% endif %} [gcode_macro UNLOAD_FILAMENT] description: Unloads the current filament gcode: {% set svv = printer.save_variables.variables %} # check against current filament state {% if svv.filament_load_state == "loaded" %} _CLIENT_LINEAR_MOVE E=-40 F={60*10} {action_respond_info('fuck')} SET_STEPPER_ENABLE STEPPER=extruder ENABLE=0 SET_FILAMENT_LOAD_STATE STATE="unloaded_waiting" SET_EXTRUDER_FILAMENT NAME="None" {% elif svv.filament_load_state == "primed" %} {action_respond_info('shit')} UNPRIME_FILAMENT UNLOAD=True {% else %} {action_respond_info("unable to unload filament. Current filament state: %s " %(svv.filament_load_state))} {% endif %} [gcode_macro LOAD_FILAMENT] # loads filament after it has been detected in the entry sensor or manually triggered gcode: {% set svv = printer.save_variables.variables %} {% set prompt = params.PROMPT|default(False) %}M84 E {% set prime = params.PRIME|default(False) %} # tell the end macro wether to call the prime macro after this SET_GCODE_VARIABLE MACRO=END_LOAD_FILAMENT VARIABLE=prime VALUE={prime} {% if not filament_state in ['unloaded'] %} # forward the filament name to the next macro SET_GCODE_VARIABLE MACRO=END_LOAD_FILAMENT VARIABLE=name VALUE="'{params.NAME}'" # we could set it here, but it avoids weird states if the macro fails for some reason. SET_FILAMENT_LOAD_STATE STATE="processing" M83 # relative extruder moves # load filament into extruder gear UPDATE_DELAYED_GCODE ID=LOOP_LOAD_FILAMENT DURATION=0.15 {% else %} {action_respond_info("unable to load filament. Current filament state: %s " %(svv.filament_load_state))} {% endif %} [delayed_gcode LOOP_LOAD_FILAMENT] gcode: {% if printer["gcode_button extruder_exit"].state == "RELEASED" %} G0 E2 F{20*60} # Extrude by 2mm at 20mm/s (0.1s) UPDATE_DELAYED_GCODE ID=LOOP_LOAD_FILAMENT DURATION=0.15 # really long wait here. Otherwise klipper gets angry and queues up moves or something. {% else %} END_LOAD_FILAMENT {% endif %} [gcode_macro END_LOAD_FILAMENT] variable_prime = False variable_name = None gcode: {% set svv = printer.save_variables.variables %} M82 # absolute extruder moves # set loaded filament SET_FILAMENT_LOAD_STATE STATE="loaded" # check if there is a valid value for the currently loaded filament. if not, prompt the user for it. {% if not svv.filament_extruder in printer.filaments.presets|map(attribute='name',default='yeet') %} # if there isn't a set loaded filament, extrude a bit then run QUERY_FILAMENT G0 E4 F{20*60} QUERY_FILAMENT RETURN_MACRO=LOAD_FILAMENT {% endif %} {% if prime %} PRIME_FILAMENT {% endif %} [gcode_macro PRIME_FILAMENT] gcode: {% set svv = printer.save_variables.variables %} {% if svv.filament_load_state in ['unloaded', 'loaded', 'primed'] %} # check if there is a valid value for the currently loaded filament. if not, prompt the user for it. {% if not svv.filament_extruder in printer.filaments.presets|map(attribute='name',default='yeet') %} # if there isn't a set loaded filament, run QUERY_FILAMENT QUERY_FILAMENT RETURN_MACRO=PRIME_FILAMENT {% elif svv.filament_load_state in ['unloaded'] %} LOAD_FILAMENT PRIME=True {% elif svv.filament_load_state in ['loaded', 'primed'] %} # ensure that the filament in the hotend is the same as the filament in the extruder {% if svv.filament_extruder == svv.filament_hotend %} SET_HOTEND_TO_FILAMENT MOVE_TO_PURGE_BUCKET SET_HOTEND_TO_FILAMENT WAIT=True # if the filament is only loaded, then extrude a bit to get it to the end of the extruder {% if svv.filament_load_state in ['loaded'] %} _CLIENT_LINEAR_MOVE E=25 F={60*20} {% endif %} _CLIENT_LINEAR_MOVE E=10 F={60*10} _CLIENT_LINEAR_MOVE E={-printer['gcode_macro VARIABLES'].retraction_length} F={60*20} CLEAN_NOZZLE SET_FILAMENT_LOAD_STATE STATE=primed {% else %} {action_respond_info("unable to prime filament. Filament in hotend doesn't match current filament")} {% endif %} {% endif %} {% else %} {action_respond_info("unable to prime filament. Current filament state: %s " % (svv.filament_load_state))} {% endif %} [gcode_macro PURGE_FILAMENT] gcode: {% set svv = printer.save_variables.variables %} {% if not svv.filament_extruder in printer.filaments.presets|map(attribute='name',default='yeet') %} # if there isn't a set loaded filament, run QUERY_FILAMENT QUERY_FILAMENT RETURN_MACRO=PURGE_FILAMENT {% elif svv.filament_load_state in ["loaded", "primed"] %} # if the filament is loaded or primed, then continue SET_HOTEND_TO_FILAMENT POSITION=both # move to purge bucket MOVE_TO_PURGE_BUCKET SET_HOTEND_TO_FILAMENT Wait=True POSITION=both {% if svv.filament_load_state in ['loaded'] %} _CLIENT_LINEAR_MOVE E=25 F={60*20} {% endif %} _CLIENT_LINEAR_MOVE E={printer['gcode_macro VARIABLES'].purge_line_length} F={60*10} _CLIENT_LINEAR_MOVE E={-printer['gcode_macro VARIABLES'].retraction_length} F={60*20} CLEAN_NOZZLE SET_HOTEND_FILAMENT NAME={svv.filament_extruder} SET_FILAMENT_LOAD_STATE STATE=primed {% else %} {action_respond_info("unable to purge filament. Current filament state: %s " %(svv.filament_load_state))} {% endif %} [gcode_macro MOVE_TO_PURGE_BUCKET] gcode: # move z to minimum of 2 {% if printer['gcode_move'].position.z < 6 %} _CLIENT_LINEAR_MOVE Z=6 F={60*60} ABSOLUTE=1 {% endif %} # move y out if necessary {% if printer['gcode_move'].position.y > 254 %} _CLIENT_LINEAR_MOVE Y=254 F={60*700} ABSOLUTE=1 {% endif %} # move xy to purge bucket _CLIENT_LINEAR_MOVE Y=254 X=25 F={60*700} ABSOLUTE=1 _CLIENT_LINEAR_MOVE Y=258 F={60*60} ABSOLUTE=1 [gcode_macro CLEAN_NOZZLE] description: wipes filament off the nozzle gcode: MOVE_TO_PURGE_BUCKET # wipe a few times {% for x in range(2) %} _CLIENT_LINEAR_MOVE X=55 F={60*700} _CLIENT_LINEAR_MOVE X=-55 F={60*700} {% endfor %} [gcode_macro STABILIZE_NOZZLE] description: tries to prevent the nozzle from leaking filament too much gcode: [gcode_button bowden_sensor] pin: PF2 press_gcode: {% set svv = printer.save_variables.variables %} { action_respond_info("bowden_load") } #DEBUG # TODO - USER LOAD FILAMENT. Setup some sort of response? Maybe wake printer from sleep mode and turn on lights? # can't switch back frgom near runout as the extruder can't grab further filament release_gcode: {% set svv = printer.save_variables.variables %} {% if svv.filament_load_state in ['primed', 'loaded'] %} {action_raise_error("Warning: bowden sensor released, nearing filament runout")} # disable the encoder sensor # TODO IMPLEMENT MORE WARNINGS. {% elif svv.filament_load_state != 'unloaded' %} {action_raise_error("Warning: bowden sensor released during nonsensical filament state.")} {% endif %} [filament_motion_sensor bowden_encoder_sensor] detection_length: 10 extruder: extruder switch_pin: ^PF3 pause_on_runout: False insert_gcode: runout_gcode: # if the printer is both printing, and the bowden sensor is pressed, then pause print. {% if (printer["gcode_button bowden_sensor"].state == "PRESSED") and printer['print_stats'].state == "printing" %} PAUSE {% endif %} # check if the bowden sensor is pressed [gcode_button extruder_entry] pin: printHead:PB7 press_gcode: {% set svv = printer.save_variables.variables %} { action_respond_info("extruder_entry_insert") } {% if svv.filament_load_state == 'unloaded' %} LOAD_FILAMENT {% endif %} release_gcode: { action_respond_info("extruder_entry_release") } {% set svv = printer.save_variables.variables %} # if filament is loaded, check if it's running out or being unloaded {% if svv.filament_load_state == 'loaded' %} # runout {% if printer['gcode_button extruder_exit'].state == PRESSED %} {action_raise_error("Warning: extruder entry sensor released, filament runout")} SET_FILAMENT_LOAD_STATE STATE="runout" # pause printer on runout {% if svv.printer_state == 'printing'%} # PAUSE {% endif %} # being unloaded {% else %} SET_FILAMENT_LOAD_STATE STATE="unloaded" {% endif %} {% elif svv.filament_load_state == 'unloaded_waiting' %} SET_FILAMENT_LOAD_STATE STATE="unloaded" {% elif svv.filament_load_state != 'unloaded' %} {action_raise_error("Warning: bowden sensor released during nonsensical filament state.")} {% endif %} [gcode_button extruder_exit] pin: printHead:PB5 press_gcode: { action_respond_info("extruder_exit_insert") } {% set svv = printer.save_variables.variables %} # auto state update if the user is manually doing things {% if svv.filament_load_state not in ['loaded', 'primed'] %} SET_FILAMENT_LOAD_STATE STATE="loaded" {% endif %} release_gcode: { action_respond_info("extruder_exit_runout") } {% set svv = printer.save_variables.variables %}