def gcode_parseline(index): g = v.parsed_gcode[index] if g.Command == 'T': gcode_process_toolchange(int(g.Command_value), v.total_material_extruded, g.Layer) if not v.debug_leaveToolCommands: g.move_to_comment("Color Change") g.issue_command() v.toolchange_processed = True return if g.fullcommand in [ "M140", "M190", "M73", "M84", "M201", "M204"]: g.issue_command() return if g.fullcommand in [ "M104" , "M109" ]: if not v.process_temp or not g.Class in [CLS_TOOL_PURGE, CLS_TOOL_START, CLS_TOOL_UNLOAD]: g.add_comment(" Unprocessed temp ") g.issue_command() v.new_temp = g.get_parameter("S", v.current_temp) v.current_temp = v.new_temp else: v.new_temp = g.get_parameter("S", v.current_temp) if v.new_temp >= v.current_temp: g.fullcommand = "M109" v.temp2_stored_command = g.__str__(); g.move_to_comment("delayed temp rise until after purge {}-->{}".format(v.current_temp, v.new_temp)) v.current_temp = v.new_temp else: v.temp1_stored_command = g.__str__(); g.move_to_comment("delayed temp drop until after purge {}-->{}".format(v.current_temp,v.new_temp)) g.issue_command() return if not g.Class in [CLS_TOOL_PURGE, CLS_TOOL_START, CLS_TOOL_UNLOAD] and v.current_temp != v.new_temp: print(v.temp1_stored_command) gcode.issue_code(v.temp1_stored_command) v.temp1_stored_command = "" # fan speed command if g.fullcommand == "M107": g.issue_command() v.saved_fanspeed = 0 return if g.fullcommand == "M106": g.issue_command() v.saved_fanspeed = g.get_parameter("S", v.saved_fanspeed) return # flow rate changes have an effect on the filament consumption. The effect is taken into account for ping generation if g.fullcommand == "M221": v.extrusion_multiplier = float(g.get_parameter("S", v.extrusion_multiplier * 100)) / 100 g.issue_command() return # feed rate changes in the code are removed as they may interfere with the Palette P2 settings if g.fullcommand in ["M220"]: g.move_to_comment("Feed Rate Adjustments are removed") g.issue_command() return if g.is_movement_command(): if g.has_X(): v.previous_purge_keep_x = v.purge_keep_x v.purge_keep_x = g.X if g.has_Y(): v.previous_purge_keep_y = v.purge_keep_y v.purge_keep_y = g.Y v.keep_speed = g.get_parameter("F", v.keep_speed) previous_block_class = v.parsed_gcode[max(0, index - 1)].Class classupdate = g.Class != previous_block_class if classupdate and previous_block_class in [CLS_TOOL_PURGE, CLS_EMPTY]: if v.purge_count > 0: gcode.issue_code( ";>>> Total purge {:4.0f}mm3 - {:4.0f}mm <<<\n".format(purgetower.volfromlength(v.purge_count), v.purge_count)) if classupdate and g.Class in [CLS_TOOL_PURGE, CLS_EMPTY]: v.purge_count = 0 if classupdate and g.Class == CLS_BRIM and v.side_wipe and v.bigbrain3d_purge_enabled: v.side_wipe_length = v.bigbrain3d_prime * v.bigbrain3d_blob_size create_sidewipe_BigBrain3D() if not v.side_wipe: if x_coordinate_in_tower(g.X): v.keep_x = g.X if y_coordinate_in_tower(g.Y): v.keep_y = g.Y # remove M900 K0 commands during unload if g.Class == CLS_TOOL_UNLOAD: if (g.fullcommand == "G4" or (g.fullcommand in ["M900"] and g.get_parameter("K", 0) == 0)): g.move_to_comment("tool unload") ## ALL SITUATIONS ############################################## if g.Class in [CLS_TOOL_START, CLS_TOOL_UNLOAD]: if g.is_movement_command(): if v.side_wipe or v.tower_delta or v.full_purge_reduction: g.move_to_comment("tool unload") else: if g.has_Z(): g.remove_parameter("X") g.remove_parameter("Y") g.remove_parameter("F") g.remove_parameter("E") else: g.move_to_comment("tool unload") g.issue_command() return if g.Class == CLS_TOOL_PURGE and not (v.side_wipe or v.full_purge_reduction): if g.is_movement_command() and g.has_E(): _x = g.get_parameter("X", v.current_position_x) _y = g.get_parameter("Y", v.current_position_y) # removepositive extrusions while moving into the tower if not (coordinate_in_tower(_x, _y) and coordinate_in_tower(v.purge_keep_x, v.purge_keep_y)) and g.E > 0: g.remove_parameter("E") if v.side_wipe: _x = g.get_parameter("X", v.current_position_x) _y = g.get_parameter("Y", v.current_position_y) if not coordinate_on_bed(_x, _y): g.remove_parameter("X") g.remove_parameter("Y") # top off the purge speed in the tower during tower delta or during no tower processing if not v.full_purge_reduction and not v.side_wipe and g.is_movement_command() and g.has_E() and g.has_parameter( "F"): f = int(g.get_parameter("F", 0)) if f > v.purgetopspeed: g.update_parameter("F", v.purgetopspeed) g.add_comment(" prugespeed topped") ## SIDEWIPE / FULLPURGEREDUCTION / TOWER DELTA ############################################### if v.pathprocessing: if g.Class == CLS_TONORMAL: if not g.is_comment(): g.move_to_comment("post block processing") g.issue_command() return # remove any commands that are part of the purge tower and still perofrm actions WITHIN the tower if g.is_movement_command() and g.Class in [CLS_ENDPURGE, CLS_ENDGRID] and g.has_X() and g.has_Y(): if coordinate_in_tower(g.X, g.Y): g.remove_parameter("X") g.remove_parameter("Y") ################################### # sepcific for FULL_PURGE_REDUCTION ################################### if v.full_purge_reduction: if g.Class == CLS_BRIM_END: create_tower_gcode() purgetower.purge_generate_brim() ################################### # sepcific for SIDEWIPE ################################### if v.side_wipe: # side wipe does not need a brim if g.Class == CLS_BRIM: g.move_to_comment("side wipe - removed") g.issue_command() return ####################################### # specific for TOWER DELTA ####################################### # changed for version 4.09.0 moves in tower were going all wrong. if not v.side_wipe and classupdate and g.Class == CLS_TOOL_PURGE: g.issue_command() gcode.issue_code("G1 X{} Y{} F8640;\n".format(v.keep_x, v.keep_y)) v.current_position_x = v.keep_x v.current_position_x = v.keep_y if v.tower_delta: if classupdate and g.Class == CLS_TOOL_PURGE: entertower(g.Layer * v.layer_height + v.first_layer_height) return if classupdate and previous_block_class == CLS_TOOL_PURGE: leavetower() ################################################################ # EMPTY GRID SKIPPING CHECK FOR SIDE WIPE/TOWER DELTA/FULLPURGE ################################################################ if g.Class == CLS_EMPTY and "EMPTY GRID START" in g.get_comment(): if g.Layer < len(v.skippable_layer) and v.skippable_layer[g.Layer]: v.towerskipped = True remove_previous_move_in_tower() if v.tower_delta: v. cur_tower_z_delta += v.layer_height gcode.issue_code(";-------------------------------------\n") gcode.issue_code("; GRID SKIP --TOWER DELTA {:6.2f}mm\n".format(v.cur_tower_z_delta)) gcode.issue_code(";-------------------------------------\n") else: if "EMPTY GRID START" in g.get_comment() and not v.side_wipe: entertower(g.Layer * v.layer_height + v.first_layer_height) # changing from EMPTY to NORMAL ############################### if (previous_block_class == CLS_ENDGRID) and (g.Class == CLS_NORMAL): v.towerskipped = False if v.towerskipped: if not g.is_comment(): g.move_to_comment("tower skipped") g.issue_command() return else: if classupdate and g.Class in [CLS_TOOL_PURGE, CLS_EMPTY]: if v.acc_ping_left <= 0: pings.check_accessorymode_first() v.enterpurge = True if v.enterpurge and g.is_movement_command(): v.enterpurge = False if g.has_X(): _x = v.previous_purge_keep_x else: _x = v.purge_keep_x if g.has_Y(): _y = v.previous_purge_keep_y else: _y = v.purge_keep_y if not coordinate_in_tower(_x, _y): _x = v.purge_keep_x _y = v.purge_keep_y if v.retraction == 0: purgetower.retract(v.current_tool, 3000) gcode.issue_code( "G1 X{:.3f} Y{:.3f} F8640; P2PP Inserted to realign\n".format(v.purge_keep_x, v.purge_keep_y)) v.current_position_x = _x v.current_position_x = _y if v.temp2_stored_command != "": gcode.issue_code(v.temp2_stored_command) v.temp2_stored_command = "" g.remove_parameter("E") if g.get_parameter("X") == _x: g.remove_parameter("X") if len(g.Parameters) == 0: g.move_to_comment("-useless command-") if v.tower_delta: if g.has_E() and g.Class in [CLS_TOOL_UNLOAD, CLS_TOOL_PURGE]: if not inrange(g.X, v.wipe_tower_info['minx'], v.wipe_tower_info['maxx']): g.remove_parameter("E") if not inrange(g.Y, v.wipe_tower_info['miny'], v.wipe_tower_info['maxy']): g.remove_parameter("E") # process movement commands ########################### if not g.has_E(): g.E = 0 if v.full_purge_reduction and g.Class == CLS_NORMAL and classupdate: purgetower.purge_generate_sequence() if g.is_movement_command(): if v.expect_retract and g.has_X() or g.has_Y(): if not v.retraction < 0: if not g.has_E and g.E < 0: purgetower.retract(v.current_tool) v.expect_retract = False if v.retract_move and g.is_retract_command(): # This is going to break stuff, G10 cannot take X and Y, what to do? if v.retract_x: g.update_parameter("X", v.retract_x) else: g.remove_parameter("X") if v.retract_y: g.update_parameter("Y", v.retract_y) else: g.remove_parameter("Y") v.retract_move = False v.current_position_x = g.get_parameter("X", v.current_position_x) v.current_position_y = g.get_parameter("Y", v.current_position_y) v.current_position_z = g.get_parameter("Z", v.current_position_z) if g.Class == CLS_BRIM and v.full_purge_reduction: g.move_to_comment("replaced by P2PP brim code") g.remove_parameter("E") if v.side_wipe or v.full_purge_reduction: if g.Class in [CLS_TOOL_PURGE, CLS_ENDPURGE, CLS_EMPTY]: if g.Layer < len(v.skippable_layer) and v.skippable_layer[g.Layer]: g.move_to_comment("skipped purge") else: v.side_wipe_length += g.E g.move_to_comment("side wipe/full purge") if v.toolchange_processed: if v.side_wipe and g.Class == CLS_NORMAL and classupdate: if v.bigbrain3d_purge_enabled: create_sidewipe_BigBrain3D() else: create_side_wipe() v.toolchange_processed = False if g.Class == CLS_NORMAL: gcode.GCodeCommand(";TOOLCHANGE PROCESSED").issue_command() v.toolchange_processed = False # check here issue with unretract ################################# # g.Comment = " ; - {}".format(v.total_material_extruded) if g.is_retract_command(): if v.retraction <= - (v.retract_length[v.current_tool] - 0.02): g.move_to_comment("Double Retract") else: if g.has_E(): v.retraction += g.E else: v.retraction -= 1 if g.is_unretract_command(): if g.has_E(): g.update_parameter("E", min(-v.retraction, g.E)) v.retraction += g.E else: v.retraction = 0 if (g.has_X() or g.has_Y()) and (g.has_E() and g.E > 0) and v.retraction < 0 and abs(v.retraction) > 0.01: gcode.issue_code(";fixup retracts\n") purgetower.unretract(v.current_tool) # v.retracted = False g.issue_command() ### PING PROCESSING ################### if v.accessory_mode: pings.check_accessorymode_second(g.E) if (g.has_E() and g.E > 0) and v.side_wipe_length == 0: pings.check_connected_ping() v.previous_position_x = v.current_position_x v.previous_position_y = v.current_position_y
def gcode_parseline(index): g = v.parsedgcode[index] block_class = v.gcodeclass[index] previous_block_class = v.gcodeclass[max(0, index - 1)] classupdate = block_class != previous_block_class if g.Command == 'T': gcode_process_toolchange(int(g.Command_value), v.total_material_extruded, g.Layer) g.move_to_comment("Color Change") g.issue_command() return if g.fullcommand in [ "M104", "M109", "M140", "M190", "M73", "M84", "M201", "M204" ]: g.issue_command() return # fan speed command if g.fullcommand == "M107": g.issue_command() v.saved_fanspeed = 0 return if g.fullcommand == "M106": g.issue_command() v.saved_fanspeed = g.get_parameter("S", v.saved_fanspeed) return if block_class == CLS_TOOL_UNLOAD and g.fullcommand in [ "M900" ] and g.get_parameter("K", 0) == 0: g.move_to_comment("tool unload") if g.fullcommand in ["M220"]: g.move_to_comment("Flow Rate Adjustments are removed") g.issue_command() return if g.fullcommand == "M221": v.extrusion_multiplier = float( g.get_parameter("S", v.extrusion_multiplier * 100)) / 100 g.issue_command() return if g.is_movement_command(): if g.has_X(): v.previous_purge_keep_x = v.purge_keep_x v.purge_keep_x = g.X if g.has_Y(): v.previous_purge_keep_y = v.purge_keep_y v.purge_keep_y = g.Y ## ALL SITUATIONS ############################################## if block_class in [CLS_TOOL_START, CLS_TOOL_UNLOAD]: if g.fullcommand == "G4": g.move_to_comment("tool unload") if g.is_movement_command(): if g.has_Z(): g.remove_parameter("X") g.remove_parameter("Y") g.remove_parameter("F") g.remove_parameter("E") else: g.move_to_comment("tool unload") g.issue_command() return if block_class == CLS_TOOL_PURGE and not (v.side_wipe or v.full_purge_reduction): if g.is_movement_command(): _x = g.get_parameter("X", v.current_position_x) _y = g.get_parameter("Y", v.current_position_y) if not (coordinate_in_tower(_x, _y) and coordinate_in_tower(v.purge_keep_x, v.purge_keep_y)): g.remove_parameter("E") if not v.side_wipe: if g.has_X(): if v.wipe_tower_info['minx'] <= g.X <= v.wipe_tower_info['maxx']: v.keep_x = g.X if g.has_Y(): if v.wipe_tower_info['miny'] <= g.Y <= v.wipe_tower_info['maxy']: v.keep_y = g.Y elif not x_on_bed(g.X): g.remove_parameter("X") ## SIDEWIPE / FULLPURGEREDUCTION / TOWER DELTA ############################################### if v.pathprocessing: if block_class == CLS_TONORMAL: if not g.is_comment(): g.move_to_comment("post block processing") g.issue_command() return if flagset(v.parsecomment[index], SPEC_INTOWER): if coordinate_in_tower(g.X, g.Y): g.remove_parameter("X") g.remove_parameter("Y") # sepcific for FULL_PURGE_REDUCTION if v.full_purge_reduction: # get information about the purge tower dimensions if block_class == CLS_BRIM and not (g.has_X() and g.has_Y()): if g.has_X(): purgetower.purge_width = min( purgetower.purge_width, abs(g.X - v.previous_position_x)) if g.has_Y(): purgetower.purge_height = min( purgetower.purge_height, abs(g.Y - v.previous_position_y)) if block_class == CLS_BRIM_END: # generate a purge tower alternative _x = v.wipe_tower_info['minx'] + 4 * v.extrusion_width _y = v.wipe_tower_info['miny'] + 4 * v.extrusion_width _w = v.wipe_tower_info['maxx'] - v.wipe_tower_info[ 'minx'] - 8 * v.extrusion_width _h = v.wipe_tower_info['maxy'] - v.wipe_tower_info[ 'miny'] - 8 * v.extrusion_width purgetower.purge_create_layers(_x, _y, _w, _h) # generate og items for the new purge tower gui.create_logitem( " Purge Tower :Loc X{:.2f} Y{:.2f} W{:.2f} H{:.2f}". format(_x, _y, _w, _h)) gui.create_logitem( " Layer Length Solid={:.2f}mm Sparse={:.2f}mm".format( purgetower.sequence_length_solid, purgetower.sequence_length_empty)) # issue the new purge tower for i in range(len(purgetower.brimlayer)): purgetower.brimlayer[i].issue_command() if i == 1 and v.retraction: purgetower.unretract(v.current_tool) # set the flag to update the post-session retraction move section v.retract_move = True v.retract_x = purgetower.last_brim_x v.retract_y = purgetower.last_brim_y # correct the amount of extrusion for the brim # sepcific for SIDEWIPE if v.side_wipe: # side wipe does not need a brim if block_class == CLS_BRIM: if not g.is_comment(): g.move_to_comment("side wipe - removed") g.issue_command() return # entering the purge tower with a delta ######################################## if v.tower_delta: if classupdate: if block_class == CLS_TOOL_PURGE: g.issue_command() gcode.issue_code("G1 X{} Y{} ;\n".format( v.keep_x, v.keep_y)) v.current_position_x = v.keep_x v.current_position_x = v.keep_y entertower(g.Layer * v.layer_height) return # going into an empty grid -- check if it should be consolidated ################################################################ if classupdate and block_class in [CLS_FIRST_EMPTY, CLS_EMPTY]: if v.skippable_layer[v.layernumber[index]]: v.towerskipped = True # print("Skipped: {:.3f} now at delta {:.3f}".format(v.current_position_z- v.retract_lift[v.current_tool]+v.layer_height,v.cur_tower_z_delta+v.layer_height)) remove_previous_move_in_tower() if v.tower_delta and "CP EMPTY GRID START" in g.Comment: v.cur_tower_z_delta += v.layer_height gcode.issue_code( ";-------------------------------------\n") gcode.issue_code( "; GRID SKIP --TOWER DELTA {:6.2f}mm\n".format( v.cur_tower_z_delta)) gcode.issue_code( ";-------------------------------------\n") # changing from EMPTY to NORMAL ############################### if (previous_block_class == CLS_ENDGRID) and (block_class == CLS_NORMAL): v.towerskipped = False if v.towerskipped: if not g.is_comment(): g.move_to_comment("tower skipped") g.issue_command() return else: if classupdate and block_class in [CLS_TOOL_PURGE, CLS_EMPTY]: if v.acc_ping_left <= 0: pings.check_accessorymode_first() v.enterpurge = True if v.enterpurge and g.is_movement_command(): v.enterpurge = False if g.has_X(): _x = v.previous_purge_keep_x else: _x = v.purge_keep_x if g.has_Y(): _y = v.previous_purge_keep_y else: _y = v.purge_keep_y if not coordinate_in_tower(_x, _y): _x = v.purge_keep_x _y = v.purge_keep_y gcode.issue_code( "G1 X{:.3f} Y{:.3f}; P2PP Inserted to realign\n".format( v.purge_keep_x, v.purge_keep_y)) v.current_position_x = _x v.current_position_x = _y g.remove_parameter("E") if g.get_parameter("X") == _x: g.remove_parameter("X") if len(g.Parameters) == 0: g.move_to_comment("-useless command-") if v.tower_delta: if g.has_E() and block_class in [CLS_TOOL_UNLOAD, CLS_TOOL_PURGE]: if not inrange(g.X, v.wipe_tower_info['minx'], v.wipe_tower_info['maxx']): g.remove_parameter("E") if not inrange(g.Y, v.wipe_tower_info['miny'], v.wipe_tower_info['maxy']): g.remove_parameter("E") # process movement commands ########################### if not g.has_E(): g.E = 0 if v.full_purge_reduction and block_class == CLS_NORMAL and classupdate: purgetower.purge_generate_sequence() if g.is_movement_command(): if v.expect_retract and g.has_X() or g.has_Y(): if not v.retraction < 0: if not g.has_E and g.E < 0: purgetower.retract(v.current_tool) v.expect_retract = False if v.retract_move and g.is_retract_command(): # This is going to break stuff, G10 cannot take X and Y, what to do? if v.retract_x: g.update_parameter("X", v.retract_x) else: g.remove_parameter("X") if v.retract_y: g.update_parameter("Y", v.retract_y) else: g.remove_parameter("Y") v.retract_move = False v.current_position_x = g.get_parameter("X", v.current_position_x) v.current_position_y = g.get_parameter("Y", v.current_position_y) v.current_position_z = g.get_parameter("Z", v.current_position_z) if block_class == CLS_BRIM and v.full_purge_reduction: g.move_to_comment("replaced by P2PP brim code") g.remove_parameter("E") if v.side_wipe or v.full_purge_reduction: if block_class in [ CLS_TOOL_PURGE, CLS_ENDPURGE, CLS_EMPTY, CLS_FIRST_EMPTY ]: if v.skippable_layer[g.Layer]: g.move_to_comment("skipped purge") else: v.side_wipe_length += g.E g.move_to_comment("side wipe/full purge") if v.side_wipe and block_class == CLS_NORMAL and classupdate: if v.bigbrain3d_purge_enabled: create_sidewipe_BigBrain3D() else: create_side_wipe() # check here issue with unretract ################################# # g.Comment = " ; - {}".format(v.total_material_extruded) if g.is_retract_command(): if g.has_E(): v.retraction += g.E else: v.retraction -= 1 if g.is_unretract_command(): if g.has_E(): v.retraction = min(0, v.retraction + g.E) else: v.retraction = 0 if (g.has_X() or g.has_Y()) and (g.has_E() and g.E > 0) and v.retraction < 0 and abs( v.retraction) > 0.01: gcode.issue_code(";fixup retracts\n") purgetower.unretract(v.current_tool) # v.retracted = False g.issue_command() ### PING PROCESSING ################### if v.accessory_mode: pings.check_accessorymode_second(g.E) if (g.has_E() and g.E > 0) and v.side_wipe_length == 0: pings.check_connected_ping() v.previous_position_x = v.current_position_x v.previous_position_y = v.current_position_y
def parse_gcode_second_pass(): idx = 0 intower = False purge = False total_line_count = len(v.parsed_gcode) v.retraction = 0 v.last_parsed_layer = -1 v.previous_block_classification = v.parsed_gcode[0][gcode.CLASS] # include firmware purge length accounting v.total_material_extruded = v.firmwarepurge v.material_extruded_per_color[v.current_tool] = v.firmwarepurge for process_line_count in range(total_line_count): try: if process_line_count >= v.layer_end[0]: v.last_parsed_layer += 1 v.layer_end.pop(0) v.current_layer_is_skippable = v.skippable_layer[ v.last_parsed_layer] and not v.last_parsed_layer == 0 if v.current_layer_is_skippable: if v.last_parsed_layer == 0: v.cur_tower_z_delta += v.first_layer_height else: v.cur_tower_z_delta += v.layer_height except IndexError: pass g = v.parsed_gcode[idx] idx = idx + 1 # ----- MEMORY MANAGEMENT - when 100K lines are processed, remove the top of the list if idx > 100000: v.parsed_gcode = v.parsed_gcode[idx:] idx = 0 if process_line_count % 10000 == 0: gui.progress_string(50 + 50 * process_line_count // total_line_count) current_block_class = g[gcode.CLASS] # ---- FIRST SECTION HANDLES DELAYED TEMPERATURE COMMANDS ---- if current_block_class not in [ CLS_TOOL_PURGE, CLS_TOOL_START, CLS_TOOL_UNLOAD ] and v.current_temp != v.new_temp: gcode.issue_code(v.temp1_stored_command) v.temp1_stored_command = "" # BLOCK Added 27/11/2021 - PS2.4 - P3 - showinf lines between print and tower if current_block_class != v.previous_block_classification and not v.side_wipe and not v.full_purge_reduction: if v.previous_block_classification == CLS_TOOL_UNLOAD: if v.restore_move_point: v.restore_move_point = False gcode.issue_code( "G1 X{:0.3f} Y{:0.3f} F8640 ; P2PP positional alignment" .format(v.current_position_x, v.current_position_y)) # BLOCK END # ---- SECOND SECTION HANDLES COMMENTS AND NONE-MOVEMENT COMMANDS ---- if g[gcode.COMMAND] is None: if v.disable_z and g[gcode.COMMENT].endswith("END"): v.disable_z = False if v.needpurgetower and g[gcode.COMMENT].endswith("BRIM END"): v.needpurgetower = False purgetower.purge_create_layers(v.wipe_tower_info_minx, v.wipe_tower_info_miny, v.wipe_tower_xsize, v.wipe_tower_ysize) purgetower.purge_generate_brim() v.toolchange_processed = False gcode.issue_command(g) continue elif g[gcode.MOVEMENT] == 0: if g[gcode.COMMAND].startswith('T'): if v.manual_filament_swap and not ( v.side_wipe or v.full_purge_reduction or v.tower_delta) and (v.current_tool != -1): swap.swap_pause("M25") swap.swap_unpause() gcode_process_toolchange(int(g[gcode.COMMAND][1:])) if not v.debug_leaveToolCommands: gcode.move_to_comment(g, "--P2PP-- Color Change") v.toolchange_processed = (current_block_class != CLS_NORMAL) elif v.klipper and g[gcode.COMMAND] == "ACTIVATE_EXTRUDER": extruder = g[gcode.OTHER].strip() if extruder.startswith("EXTRUDER=extruder"): if len(extruder) == 17: extruder_num = 0 else: try: extruder_num = int(extruder[17:]) except (ValueError, IndexError): extruder_num = None gui.log_warning( "KLIPPER - Named extruders are not supported ({})" .format(extruder)) if extruder_num is not None: gcode_process_toolchange(extruder_num) if not v.debug_leaveToolCommands: gcode.move_to_comment(g, "--P2PP-- Color Change") v.toolchange_processed = True else: gui.log_warning( "KLIPPER - Named extruders are not supported ({})". format(extruder)) else: if current_block_class == CLS_TOOL_UNLOAD: if g[gcode.COMMAND] in ["G4", "M900", "M400"]: gcode.move_to_comment(g, "--P2PP-- tool unload") if g[gcode.COMMAND] is not None and g[ gcode.COMMAND].startswith('M'): try: command_num = int(g[gcode.COMMAND][1:]) except (ValueError, KeyError): command_num = 0 if command_num in [104, 109]: if v.process_temp: if current_block_class not in [ CLS_TOOL_PURGE, CLS_TOOL_START, CLS_TOOL_UNLOAD ]: g[gcode.COMMENT] += " Unprocessed temp " v.new_temp = gcode.get_parameter( g, gcode.S, v.current_temp) v.current_temp = v.new_temp else: v.new_temp = gcode.get_parameter( g, gcode.S, v.current_temp) if v.new_temp >= v.current_temp: g[gcode.COMMAND] = "M109" v.temp2_stored_command = gcode.create_commandstring( g) gcode.move_to_comment( g, "--P2PP-- delayed temp rise until after purge {}-->{}" .format(v.current_temp, v.new_temp)) v.current_temp = v.new_temp else: v.temp1_stored_command = gcode.create_commandstring( g) gcode.move_to_comment( g, "--P2PP-- delayed temp drop until after purge {}-->{}" .format(v.current_temp, v.new_temp)) elif command_num == 107: v.saved_fanspeed = 0 elif command_num == 106: v.saved_fanspeed = gcode.get_parameter( g, gcode.S, v.saved_fanspeed) elif command_num == 221: v.extrusion_multiplier = float( gcode.get_parameter( g, gcode.S, v.extrusion_multiplier * 100.0)) / 100.0 elif command_num == 220: gcode.move_to_comment( g, "--P2PP-- Feed Rate Adjustments are removed") elif command_num == 572: for i in range(1, v.filament_count): g[gcode.OTHER] = g[gcode.OTHER].replace( "D{}".format(i), "D0") elif not v.generate_M0 and g[gcode.COMMAND] == "M0": gcode.move_to_comment(g, "--P2PP-- remove M0 command") gcode.issue_command(g) continue classupdate = not current_block_class == v.previous_block_classification v.previous_block_classification = current_block_class # ---- AS OF HERE ONLY MOVEMENT COMMANDS ---- if g[gcode.MOVEMENT] & 1: v.previous_purge_keep_x = v.purge_keep_x v.purge_keep_x = g[gcode.X] v.current_position_x = g[gcode.X] if g[gcode.MOVEMENT] & 2: v.previous_purge_keep_y = v.purge_keep_y v.purge_keep_y = g[gcode.Y] v.current_position_y = g[gcode.Y] if g[gcode.MOVEMENT] & 4: if v.disable_z: gcode.move_to_comment(g, "-- P2PP - invalid move in delta tower") gcode.issue_command(g) continue else: v.current_position_z = g[gcode.Z] if g[gcode.MOVEMENT] & 16: v.keep_speed = g[gcode.F] # this goes for all situations: START and UNLOAD are not needed if current_block_class in [CLS_TOOL_START, CLS_TOOL_UNLOAD]: # BLOCK Added 27/11/2021 - PS2.4 - P3 - showinf lines between print and tower if not (v.side_wipe or v.full_purge_reduction): v.restore_move_point = True # BLOCK END gcode.move_to_comment(g, "--P2PP-- tool unload") gcode.issue_command(g) continue # --------------------- TOWER DELTA PROCESSING if v.tower_delta: if classupdate: if current_block_class == CLS_TOOL_PURGE: gcode.issue_command(g) entertower(v.last_parsed_layer * v.layer_height + v.first_layer_height) continue if current_block_class == CLS_EMPTY and not v.towerskipped: v.towerskipped = ( g[gcode.MOVEMENT] & gcode.INTOWER ) == gcode.INTOWER and v.current_layer_is_skippable if not v.towerskipped: gcode.issue_command(g) entertower(v.last_parsed_layer * v.layer_height + v.first_layer_height) continue if current_block_class == CLS_NORMAL: if v.towerskipped: gcode.issue_code("G1 Z{:.2f} F10810".format( v.current_position_z)) v.towerskipped = False if current_block_class == CLS_TOOL_PURGE: speed_limiter(g) if current_block_class == CLS_TOOL_PURGE: if g[gcode.F] is not None and g[ gcode.F] > v.purgetopspeed and g[gcode.E]: g[gcode.F] = v.purgetopspeed g[gcode.COMMENT] += " prugespeed topped" if v.towerskipped: gcode.move_to_comment(g, "--P2PP-- tower skipped") gcode.issue_command(g) continue # --------------------- SIDE WIPE PROCESSING elif v.side_wipe: if classupdate: if current_block_class == CLS_BRIM: v.towerskipped = True v.side_wipe_state = 0 if not v.towerskipped and (g[gcode.MOVEMENT] & 3) != 0: if (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER: v.towerskipped = True v.side_wipe_state = 1 if (current_block_class == CLS_TOOL_PURGE) else 0 if v.towerskipped and current_block_class == CLS_NORMAL and ( g[gcode.MOVEMENT] & 3) == 3: if (v.bed_origin_x <= g[gcode.X] <= v.bed_max_x) and ( v.bed_origin_y <= g[gcode.Y] <= v.bed_max_y): v.towerskipped = False v.side_wipe_state = 0 if v.toolchange_processed and v.side_wipe_length: create_side_wipe() v.toolchange_processed = False if v.towerskipped: inc = "NO_E" if current_block_class in [ CLS_TOOL_PURGE, CLS_ENDPURGE ] or (current_block_class == CLS_EMPTY and v.side_wipe_state == 1): if g[gcode.EXTRUDE]: v.side_wipe_length += g[gcode.E] inc = "INC_E" gcode.move_to_comment( g, "--P2PP-- side wipe skipped ({})".format(inc)) gcode.issue_command(g) continue # for PS2.4 # before first extrusion prime the nozzle if not v.mechpurge_hasprimed and g[gcode.EXTRUDE]: if v.bigbrain3d_purge_enabled or v.blobster_purge_enabled: create_side_wipe(v.mechpurge_prime_blobs * v.mechpurge_blob_size) v.mechpurge_hasprimed = True # --------------------- FULL PURGE PROCESSING elif v.full_purge_reduction: if (g[gcode.MOVEMENT] & 3) > 0: # if there is a movement intower = (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER if classupdate: if current_block_class == CLS_NORMAL: v.towerskipped = False purge = False if current_block_class == CLS_TOOL_PURGE: purge = True if not v.towerskipped and current_block_class == CLS_EMPTY and v.current_layer_is_skippable: v.towerskipped = (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER if v.towerskipped or current_block_class in [ CLS_BRIM, CLS_ENDGRID ]: gcode.move_to_comment( g, "--P2PP-- full purge skipped [Excluded]") gcode.issue_command(g) continue if current_block_class in [ CLS_TOOL_PURGE, CLS_ENDPURGE, CLS_EMPTY ]: if purge and g[gcode.EXTRUDE]: v.side_wipe_length += g[gcode.E] gcode.move_to_comment( g, "--P2PP-- full purge skipped [Included]") else: gcode.move_to_comment( g, "--P2PP-- full purge skipped [Excluded]") gcode.issue_command(g) continue if v.toolchange_processed and current_block_class == CLS_NORMAL: if v.side_wipe_length and ( g[gcode.MOVEMENT] & 3) == 3 and not (g[gcode.MOVEMENT] & gcode.INTOWER) == gcode.INTOWER: purgetower.purge_generate_sequence() v.toolchange_processed = False # do not issue code here as the next code might require further processing such as retractioncorrection else: gcode.move_to_comment(g, "--P2PP-- full purge skipped") gcode.issue_command(g) continue if v.expect_retract and (g[gcode.MOVEMENT] & 3): v.expect_retract = False if v.retraction >= 0 and g[gcode.RETRACT]: purgetower.retract(v.current_tool) if v.retract_move and g[gcode.RETRACT]: g[gcode.X] = v.retract_x g[gcode.Y] = v.retract_y g[gcode.MOVEMENT] |= 3 v.retract_move = False if v.retraction <= -v.retract_length[v.current_tool]: gcode.move_to_comment(g, "--P2PP-- Double Retract") else: v.retraction += g[gcode.E] if intower: gcode.move_to_comment( g, "--P2PP-- full purge skipped [Excluded]") gcode.issue_command(g) continue # --------------------- NO TOWER PROCESSING else: if current_block_class in [CLS_TOOL_PURGE, CLS_EMPTY ] and g[gcode.E]: if v.acc_ping_left <= 0: pings.check_accessorymode_first() v.enterpurge = True # TOEE - Added to limit the speed of the extrusions during purge to defined WIPEFEEDRATE if current_block_class == CLS_TOOL_PURGE: speed_limiter(g) if v.toolchange_processed: if v.temp2_stored_command != "": wait_location = calculate_temp_wait_position() gcode.issue_code( "G1 X{:.3f} Y{:.3f} F8640; temp wait position\n". format(wait_location[0], wait_location[0])) gcode.issue_code(v.temp2_stored_command) v.temp2_stored_command = "" gcode.issue_code("G1 F8640 ; correct speed") gcode.issue_command(g) if v.wipe_remove_sparse_layers: gcode.issue_code( "G1 X{} Y{} F8640 ;P2PP Position XY to avoid tower crash" .format(v.current_position_x, v.current_position_y)) v.z_correction = "G1 Z{} F10800 ;P2PP correct z-moves".format( v.current_position_z) v.toolchange_processed = False continue if current_block_class == CLS_TOOL_PURGE: if g[gcode.F] is not None and g[ gcode.F] > v.purgetopspeed and g[gcode.E]: g[gcode.F] = v.purgetopspeed g[gcode.COMMENT] += " prugespeed topped" # --------------------- GLOBAL PROCEDDING if g[gcode.UNRETRACT]: g[gcode.E] = min(-v.retraction, g[gcode.E]) v.retraction += g[gcode.E] elif g[gcode.RETRACT]: v.retraction += g[gcode.E] elif (g[gcode.MOVEMENT] & 3) and g[gcode.EXTRUDE]: if v.z_correction is not None or v.retraction < -0.01: if current_block_class != CLS_TOOL_START: gcode.issue_code(";P2PP START Z/E alignment processing") if v.z_correction is not None: gcode.issue_code(v.z_correction) v.z_correction = None if v.retraction < -0.01: purgetower.unretract(v.retraction, -1, ";--- P2PP --- fixup retracts") gcode.issue_code(";P2PP END Z/E alignment processing") else: gcode.issue_command(g) gcode.issue_code(";P2PP START Z/E alignment processing") if v.z_correction is not None: gcode.issue_code(v.z_correction) v.z_correction = None if v.retraction < -0.01: purgetower.unretract(v.retraction, -1, ";--- P2PP --- fixup retracts") g = gcode.create_command( ";P2PP END Z/E alignment processing") # --------------------- PING PROCESSING if v.accessory_mode and g[gcode.EXTRUDE]: if not pings.check_accessorymode_second(g[gcode.E]): gcode.issue_command(g) else: gcode.issue_command(g) if g[gcode.EXTRUDE] and v.side_wipe_length == 0: pings.check_connected_ping() v.previous_position_x = v.current_position_x v.previous_position_y = v.current_position_y # LAST STEP IS ADDING AN EXTRA TOOL UNLOAD TO DETERMINE THE LENGTH OF THE LAST SPLICE gcode_process_toolchange(-1)