From 6f5628ccd5542a4132d701c48dafc0e9fcdf09b4 Mon Sep 17 00:00:00 2001 From: HelgeKeck Date: Sat, 27 Apr 2024 09:54:59 +0200 Subject: [PATCH] handle multiple rmmu initial filaments --- klippy/rmmu.py | 47 +------- klippy/rmmu_hub.py | 179 +++++++++++++++++----------- macros.cfg | 44 ++++--- scripts/ratos_idex_postprocessor.py | 14 +-- 4 files changed, 150 insertions(+), 134 deletions(-) diff --git a/klippy/rmmu.py b/klippy/rmmu.py index 5d064307..507a92bf 100644 --- a/klippy/rmmu.py +++ b/klippy/rmmu.py @@ -66,6 +66,7 @@ def __init__(self, config): # rmmu default status self.is_homed = False self.runout_detected = False + self.initial_filament = -1 self.needs_initial_purging = False self.spool_joins = [] self.spool_mapping = [] @@ -212,6 +213,7 @@ def get_status(self, eventtime): return {'name': self.name, 'tool_count': self.tool_count, 'is_homed': self.is_homed, + 'initial_filament': self.initial_filament, 'needs_initial_purging': self.needs_initial_purging, 'loaded_filament': self.get_setting(self.name.lower() + self.VARS_LOADED_FILAMENT), 'loaded_filament_temp': self.get_setting(self.name.lower() + self.VARS_LOADED_FILAMENT_TEMP)} @@ -221,6 +223,7 @@ def reset(self): self.is_homed = False self.runout_detected = False self.start_print_param = None + self.initial_filament = -1 self.needs_initial_purging = False # # update frontend @@ -832,57 +835,13 @@ def unload_filament_from_toolhead_sensor_to_reverse_bowden(self, tool): ##### # Filament presence check ##### - def test_filaments(self, param): - # echo - self.ratos_echo("Testing needed filaments...") - - # home if needed - if not self.is_homed and len(self.parking_t_sensor_endstop) != self.tool_count: - self.home() - - # test filaments - for i in range(0, self.tool_count): - toolhead_used = param.get('T' + str(i), "true") - if toolhead_used == "true": - toolhead = self.get_remapped_toolhead(i) - if not self.test_filament(toolhead): - self.select_filament(-1) - raise self.printer.command_error("Can not start print because Filament T" + str(toolhead) + " is not available!") - - # release idler - if len(self.parking_t_sensor_endstop) != self.tool_count: - self.select_filament(-1) - - # echo - self.ratos_echo("All needed filaments available!") - - # testing spool join - if len(self.spool_joins) > 0: - self.ratos_echo("Validating spool join...") - for spool_join in self.spool_joins: - counter = 0 - for spool in spool_join: - for i in range(0, self.tool_count): - if param.get('T' + str(i), "true") == "true": - if spool == i: - counter += 1 - if counter > 1: - raise self.printer.command_error("Can not start print because joined spools are part of the print!") - self.ratos_echo("Spool join validated!") - def test_filament(self, filament): - # echo - self.ratos_echo("Testing filament T" + str(filament) + "...") - - # test filament if len(self.parking_t_sensor_endstop) == self.tool_count or len(self.feeder_filament_sensors) == self.tool_count: if len(self.parking_t_sensor_endstop) == self.tool_count: if not self.is_endstop_triggered(self.parking_t_sensor_endstop[filament]): - self.ratos_echo("Filament T" + str(filament) + " not detected!") return False if len(self.feeder_filament_sensors) == self.tool_count: if not self.is_sensor_triggered(self.feeder_filament_sensors[filament]): - self.ratos_echo("Filament T" + str(filament) + " runout detected!") return False return True else: diff --git a/klippy/rmmu_hub.py b/klippy/rmmu_hub.py index d656e6a3..e0e40ac8 100644 --- a/klippy/rmmu_hub.py +++ b/klippy/rmmu_hub.py @@ -23,7 +23,6 @@ def __init__(self, config): self.mapping = {} self.mode = "multi" self.total_tool_count = 0 - self.initial_filament = 0 self.register_commands() self.register_handler() @@ -165,7 +164,6 @@ def cmd_RMMU_END_PRINT(self, param): def get_status(self, eventtime): return {'name': self.name, 'mode': self.mode, - 'initial_filament': self.initial_filament, 'total_tool_count': self.total_tool_count, 'mapping': self.mapping} @@ -174,83 +172,130 @@ def get_status(self, eventtime): ##### def start_print(self, param): # parameter - self.initial_filament = param.get_int('INITIAL_TOOL', None, minval=0, maxval=self.total_tool_count) - self.wipe_accel = param.get_int('WIPE_ACCEL', None, minval=0, maxval=100000) self.start_print_param = param - - # handle toolhead mapping - # self.initial_filament = self.get_remapped_toolhead(self.initial_filament) - - # home RMMUs - for rmmu in self.rmmu: - rmmu.home() - - # # get used physical toolheads - # used_toolheads = [] - # for t in range(0, self.total_tool_count): - # if param.get('T' + str(t), "true") == "true": - # if not t in used_toolheads: - # used_toolheads.append(t) - # self.ratos_echo("used_toolheads: " + str(used_toolheads)) - - # get initial RMMU and tool - rmmu = self.rmmu[0] - rmmu_tool = self.initial_filament - if rmmu_tool >= self.rmmu[0].tool_count: - rmmu = self.rmmu[1] - rmmu_tool = rmmu_tool - self.rmmu[0].tool_count + self.wipe_accel = param.get_int('WIPE_ACCEL', None, minval=0, maxval=100000) + used_tools = [] + try: + used_tools = [int(v.strip()) for v in str(param.get('USED_TOOLS', None)).split(',')] + except: + raise self.printer.command_error("Unable to parse START_PRINT parameter USED_TOOLS.") + if len(used_tools) == 0: + raise self.printer.command_error("Unable to parse START_PRINT parameter USED_TOOLS.") + + # home needed RMMUs + for t in used_tools: + physical_toolhead = int(self.mapping[str(t)]["TOOLHEAD"]) + if not self.rmmu[physical_toolhead].is_homed: + self.rmmu[physical_toolhead].home() + + # get used physical toolheads + used_toolheads = [] + for t in used_tools: + physical_toolhead = int(self.mapping[str(t)]["TOOLHEAD"]) + if physical_toolhead not in used_toolheads: + used_toolheads.append(physical_toolhead) # check for filament in hotend - rmmu.needs_initial_purging = True - if rmmu.is_sensor_triggered(rmmu.toolhead_filament_sensor): - loaded_filament = rmmu.get_status(self.toolhead.get_last_move_time())['loaded_filament'] - loaded_filament_temp = rmmu.get_status(self.toolhead.get_last_move_time())['loaded_filament_temp'] - if loaded_filament >=0 and loaded_filament <= self.total_tool_count: - if loaded_filament != rmmu_tool: - if loaded_filament_temp > rmmu.heater.min_extrude_temp and loaded_filament_temp < rmmu.heater.max_temp: - # unloaded the filament that is already loaded - self.ratos_echo("Wrong filament detected in hotend!") - self.ratos_echo("Unloading filament T" + str(loaded_filament) + "! Please wait...") - - # start heating up extruder but dont wait for it so we can save some time - self.ratos_echo("Preheating extruder to " + str(loaded_filament_temp) + "°C.") - rmmu.extruder_set_temperature(loaded_filament_temp, False) - - # home printer if needed and move toolhead to its parking position - self.gcode.run_script_from_command('MAYBE_HOME') - if rmmu_tool >= self.rmmu[0].tool_count: - self.gcode.run_script_from_command('_MOVE_TO_LOADING_POSITION TOOLHEAD=1') - else: - self.gcode.run_script_from_command('_MOVE_TO_LOADING_POSITION TOOLHEAD=0') - - # wait for the extruder to heat up - self.ratos_echo("Heating up extruder to " + str(loaded_filament_temp) + "°C! Please wait...") - rmmu.extruder_set_temperature(loaded_filament_temp, True) - - # unload filament - if not rmmu.unload_filament(loaded_filament): + for physical_toolhead in used_toolheads: + initial_tool = -1 + for t in used_tools: + if physical_toolhead == int(self.mapping[str(t)]["TOOLHEAD"]): + initial_tool = int(self.mapping[str(t)]["FILAMENT"]) + break + # handle toolhead mapping + # self.initial_filament = self.get_remapped_toolhead(self.initial_filament) + rmmu = self.rmmu[physical_toolhead] + rmmu.initial_filament = initial_tool + rmmu.needs_initial_purging = True + if rmmu.is_sensor_triggered(rmmu.toolhead_filament_sensor): + loaded_filament = rmmu.get_status(self.toolhead.get_last_move_time())['loaded_filament'] + loaded_filament_temp = rmmu.get_status(self.toolhead.get_last_move_time())['loaded_filament_temp'] + if loaded_filament >=0 and loaded_filament <= self.total_tool_count: + if loaded_filament != rmmu.initial_filament: + if loaded_filament_temp > rmmu.heater.min_extrude_temp and loaded_filament_temp < rmmu.heater.max_temp: + # unloaded the filament that is already loaded + self.ratos_echo("Wrong filament detected in hotend!") + self.ratos_echo("Unloading filament T" + str(loaded_filament) + "! Please wait...") + + # start heating up extruder but dont wait for it so we can save some time + self.ratos_echo("Preheating extruder to " + str(loaded_filament_temp) + "°C.") + rmmu.extruder_set_temperature(loaded_filament_temp, False) + + # home printer if needed and move toolhead to its parking position + self.gcode.run_script_from_command('MAYBE_HOME') + if rmmu.initial_filament >= self.rmmu[0].tool_count: + self.gcode.run_script_from_command('_MOVE_TO_LOADING_POSITION TOOLHEAD=1') + else: + self.gcode.run_script_from_command('_MOVE_TO_LOADING_POSITION TOOLHEAD=0') + + # wait for the extruder to heat up + self.ratos_echo("Heating up extruder to " + str(loaded_filament_temp) + "°C! Please wait...") + rmmu.extruder_set_temperature(loaded_filament_temp, True) + + # unload filament + if not rmmu.unload_filament(loaded_filament): + rmmu.extruder_set_temperature(0, False) + raise self.printer.command_error("Could not unload filament! Please unload the filament and restart the print.") + + # cool down extruder, dont wait for it rmmu.extruder_set_temperature(0, False) - raise self.printer.command_error("Could not unload filament! Please unload the filament and restart the print.") - - # cool down extruder, dont wait for it - rmmu.extruder_set_temperature(0, False) + else: + raise self.printer.command_error("Unknown filament detected in toolhead! Please unload the filament and restart the print.") else: - raise self.printer.command_error("Unknown filament detected in toolhead! Please unload the filament and restart the print.") + # tell RatOS that initial purging is not needed + rmmu.needs_initial_purging = False else: - # tell RatOS that initial purging is not needed - rmmu.needs_initial_purging = False - else: - raise self.printer.command_error("Unknown filament detected in toolhead! Please unload the filament and restart the print.") + raise self.printer.command_error("Unknown filament detected in toolhead! Please unload the filament and restart the print.") - # # test if all demanded filaments are available and raises an error if not - # rmmu.test_filaments(param) + # disable toolhead filament sensor + rmmu.toolhead_filament_sensor.runout_helper.sensor_enabled = False - # disable toolhead filament sensor - rmmu.toolhead_filament_sensor.runout_helper.sensor_enabled = False + # test if all demanded filaments are available and raises an error if not + self.test_filaments(used_tools) # call RatOS start print gcode macro self.gcode.run_script_from_command('START_PRINT ' + str(param.get_raw_command_parameters().strip())) + ##### + # Filament presence check + ##### + def test_filaments(self, used_tools): + # echo + self.ratos_echo("Testing needed filaments...") + + # test filaments + for filament in used_tools: + rmmu_filament = int(self.mapping[str(filament)]["FILAMENT"]) + # filament = self.get_remapped_toolhead(filament) + physical_toolhead = int(self.mapping[str(filament)]["TOOLHEAD"]) + rmmu = self.rmmu[physical_toolhead] + self.ratos_echo("Testing filament T" + str(filament) + "...") + if not rmmu.test_filament(rmmu_filament): + self.ratos_echo("Filament T" + str(filament) + " not found!") + rmmu.select_filament(-1) + raise self.printer.command_error("Can not start print because Filament T" + str(filament) + " is not available!") + + # release idler + if len(rmmu.parking_t_sensor_endstop) != rmmu.tool_count: + rmmu.select_filament(-1) + + # echo + self.ratos_echo("All needed filaments available!") + + # # testing spool join + # if len(self.spool_joins) > 0: + # self.ratos_echo("Validating spool join...") + # for spool_join in self.spool_joins: + # counter = 0 + # for spool in spool_join: + # for i in range(0, self.tool_count): + # if param.get('T' + str(i), "true") == "true": + # if spool == i: + # counter += 1 + # if counter > 1: + # raise self.printer.command_error("Can not start print because joined spools are part of the print!") + # self.ratos_echo("Spool join validated!") + ##### # Change Filament ##### diff --git a/macros.cfg b/macros.cfg index 14abd38d..c4bb109f 100644 --- a/macros.cfg +++ b/macros.cfg @@ -313,16 +313,6 @@ gcode: {% if printer["dual_carriage"] is defined %} SET_GCODE_VARIABLE MACRO=T1 VARIABLE=active VALUE=True {% endif %} - # {% if printer["rmmu"] is defined %} - # {% for i in range(printer["rmmu"].tool_count) %} - # SET_GCODE_VARIABLE MACRO=T{i} VARIABLE=active VALUE=False - # {% set color_key = "COLOR" if i==0 else "COLOR_%s" % i|string %} - # {% if params[color_key] is defined %} - # {% set color_parameter = params[color_key] %} - # SET_GCODE_VARIABLE MACRO=T{i} VARIABLE=color VALUE='"{color_parameter|string}"' - # {% endif %} - # {% endfor %} - # {% endif %} # set both_toolheads variable based on toolshift count. we first assume both toolheads will be needed {% set both_toolheads = true %} @@ -629,11 +619,32 @@ gcode: {% endif %} # rmmu load initial tool - {% if printer["rmmu_hub"] is defined and printer["rmmu RMMU_T%s" % initial_tool].loaded_filament|int != printer["rmmu_hub"].initial_filament|int %} - _MOVE_TO_LOADING_POSITION TOOLHEAD={initial_tool} - RMMU_LOAD_FILAMENT FILAMENT={printer["rmmu_hub"].initial_filament|int} - {% if printer["dual_carriage"] is defined %} - PARK_TOOLHEAD + {% if printer["rmmu_hub"] is defined %} + {% if physical_t0_used and printer["rmmu RMMU_T0"] is defined and printer["rmmu RMMU_T0"].loaded_filament|int != printer["rmmu RMMU_T0"].initial_filament|int %} + {% if initial_tool == 1 %} + SET_DUAL_CARRIAGE CARRIAGE=0 MODE=PRIMARY + {% endif %} + _MOVE_TO_LOADING_POSITION TOOLHEAD=0 + RMMU_LOAD_FILAMENT FILAMENT={printer["rmmu RMMU_T0"].initial_filament|int} + {% if printer["dual_carriage"] is defined %} + PARK_TOOLHEAD + {% endif %} + {% if initial_tool == 1 %} + SET_DUAL_CARRIAGE CARRIAGE=1 MODE=PRIMARY + {% endif %} + {% endif %} + {% if physical_t1_used and printer["rmmu RMMU_T1"] is defined and printer["rmmu RMMU_T1"].loaded_filament|int != printer["rmmu RMMU_T1"].initial_filament|int %} + {% if initial_tool == 0 %} + SET_DUAL_CARRIAGE CARRIAGE=1 MODE=PRIMARY + {% endif %} + _MOVE_TO_LOADING_POSITION TOOLHEAD=1 + RMMU_LOAD_FILAMENT FILAMENT={printer["rmmu RMMU_T1"].initial_filament|int} + {% if printer["dual_carriage"] is defined %} + PARK_TOOLHEAD + {% endif %} + {% if initial_tool == 0 %} + SET_DUAL_CARRIAGE CARRIAGE=0 MODE=PRIMARY + {% endif %} {% endif %} {% endif %} @@ -736,13 +747,14 @@ gcode: # config {% set min_temp = printer["gcode_macro RatOS"].preheat_extruder_temp|float %} {% set max_temp = printer["gcode_macro RatOS"].preheat_extruder_temp|float + 5 %} + {% set default_toolhead = printer["gcode_macro RatOS"].default_toolhead|default(0)|int %} # preheat extruder {% if printer["gcode_macro RatOS"].preheat_extruder|lower == 'true' %} RATOS_ECHO MSG="Pre-heating extruder..." # Wait for extruder to reach a predefined preheat temp so an inductive probe (if present) is at a predictable temp. # Also allows the bed heat to spread a little, and softens any plastic that might be stuck to the nozzle. - M104 S{min_temp} + M104 S{min_temp} T{default_toolhead} TEMPERATURE_WAIT SENSOR=extruder MINIMUM={min_temp} MAXIMUM={max_temp} {% endif %} diff --git a/scripts/ratos_idex_postprocessor.py b/scripts/ratos_idex_postprocessor.py index 1cf2d8a9..d14b1b9d 100644 --- a/scripts/ratos_idex_postprocessor.py +++ b/scripts/ratos_idex_postprocessor.py @@ -60,7 +60,7 @@ def process_file(args, sourcefile): start_print_line = 0 file_has_changed = False wipe_accel = 0 - tools_usage = [] + used_tools = [] for line in range(len(lines)): # get slicer profile settings @@ -85,14 +85,14 @@ def process_file(args, sourcefile): if start_print_line > 0: if lines[line].rstrip().startswith("T") and lines[line].rstrip()[1:].isdigit(): # add initial tool to the list if not already added - if len(tools_usage) == 0: + if len(used_tools) == 0: index = lines[start_print_line].rstrip().find("INITIAL_TOOL=") if index != -1: - tools_usage.append(lines[start_print_line].rstrip()[index + len("INITIAL_TOOL="):].split()[0]) + used_tools.append(lines[start_print_line].rstrip()[index + len("INITIAL_TOOL="):].split()[0]) # add Tx to the list if not already added t = lines[line].rstrip()[1:] - if t not in tools_usage: - tools_usage.append(t) + if t not in used_tools: + used_tools.append(t) # get first XY coordinates if start_print_line > 0 and first_x < 0 and first_y < 0: @@ -248,9 +248,9 @@ def process_file(args, sourcefile): if min_x < 1000: file_has_changed = True lines[start_print_line] = lines[start_print_line].rstrip() + ' MIN_X=' + str(min_x) + ' MAX_X=' + str(max_x) + '\n' - if len(tools_usage) > 0: + if len(used_tools) > 0: file_has_changed = True - lines[start_print_line] = lines[start_print_line].rstrip() + ' TOOLS_USAGE=' + ','.join(tools_usage) + '\n' + lines[start_print_line] = lines[start_print_line].rstrip() + ' USED_TOOLS=' + ','.join(used_tools) + '\n' lines[start_print_line] = lines[start_print_line].rstrip() + ' WIPE_ACCEL=' + str(wipe_accel) + '\n' # save file if it has changed