def create_tower_gcode(): # generate a purge tower alternative _x = v.wipe_tower_info['minx'] _y = v.wipe_tower_info['miny'] _w = v.wipe_tower_info['maxx'] - v.wipe_tower_info['minx'] _h = v.wipe_tower_info['maxy'] - v.wipe_tower_info['miny'] 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))
def find_alternative_tower(): v.wipe_tower_info_maxx = v.wipe_tower_posx v.wipe_tower_info_minx = v.wipe_tower_posx v.wipe_tower_info_maxy = v.wipe_tower_posy v.wipe_tower_info_miny = v.wipe_tower_posy if v.wipe_tower_posx and v.wipe_tower_posy: state = 0 for i in range(len(v.input_gcode)): line = v.input_gcode[i] if line.startswith(";"): if line.startswith(";TYPE:Wipe tower"): state = 1 continue if state == 1 and line.startswith(";TYPE"): check_tower_update(False) purgetower.purge_create_layers(v.wipe_tower_info_minx, v.wipe_tower_info_miny, v.wipe_tower_xsize, v.wipe_tower_ysize) gui.create_logitem( "Tower detected from ({}, {}) to ({}, {})".format( v.wipe_tower_info_minx, v.wipe_tower_info_miny, v.wipe_tower_info_maxx, v.wipe_tower_info_maxy)) break if state == 1: gc = gcode.create_command(line) if gc[gcode.EXTRUDE]: if gc[gcode.X] is not None: v.wipe_tower_info_maxx = max( v.wipe_tower_info_maxx, gc[gcode.X] + 6 * v.extrusion_width) v.wipe_tower_info_minx = min( v.wipe_tower_info_minx, gc[gcode.X] - 6 * v.extrusion_width) if gc[gcode.Y] is not None: v.wipe_tower_info_maxy = max( v.wipe_tower_info_maxy, gc[gcode.Y] + 6 * v.extrusion_width) v.wipe_tower_info_miny = min( v.wipe_tower_info_miny, gc[gcode.Y] - 6 * v.extrusion_width)
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)
def process_gcode(): gui.comment("Processing " + v.filename) line_count = len(v.rawfile) line_idx = 0 for line in v.rawfile: line_idx += 1 gui.setprogress(int(50 * line_idx / line_count)) # skip fully empty lines if len(line) == 0: continue # parse comments if line.startswith(";"): line = parameters.parse_comment(line) tmp = gcode.GCodeCommand(line) # we calculate the purge for tower position # afterwards this code is removed ######################################################### if v.mode == parameters.MODE_PURGE: if tmp.E: v.purge_minx = min(v.purge_minx, tmp.get_parameter("X", 9999)) v.purge_maxx = max(v.purge_maxx, tmp.get_parameter("X", -9999)) v.purge_miny = min(v.purge_miny, tmp.get_parameter("Y", 9999)) v.purge_maxy = max(v.purge_maxy, tmp.get_parameter("Y", -9999)) if tmp.is_comment() and tmp.comment.startswith(' process'): v.gcodes.append(tmp) else: v.gcodes.append(tmp) toolchange = tmp.is_toolchange() if toolchange in [0, 1, 2, 3]: # keep track of the tools used if not v.toolsused[toolchange]: if not v.filament_type[toolchange]: error( "TOOL_{} setting command missing - output file cannot be created" .format(toolchange)) v.toolsused[toolchange] = True # calculate the purge if not (v.parse_curtool == -1): v.layer_toolchange_count[-1] += 1 if v.filament_type[toolchange] and v.filament_type[ v.parse_curtool] and not (v.parse_curtool == toolchange): v.layer_purge_volume[-1] += purgetower.calc_purge_length( v.parse_curtool, toolchange) v.parse_prevtool = v.parse_curtool v.parse_curtool = toolchange else: v.parse_curtool = v.parse_prevtool = toolchange comment("filament Info: " + v.filament_type.__str__()) comment("Tool unload info: " + v.unloadinfo.__str__()) comment("Tool load info: " + v.loadinfo.__str__()) comment("Algorithms:" + v.algorithm.__str__()) comment("Maximum purge needed per layer: {}mm".format( max(v.layer_purge_volume))) comment("Autotower function active: {}".format(v.autotower)) if v.autotower: autotower.init_autotower() _x = 0.0 _y = 0.0 for g in v.gcodes: if g.is_movement_command(): _ux = g.get_parameter("X", _x) _uy = g.get_parameter("Y", _y) _ue = g.get_parameter("E", 0) if _ue > 0: autotower.filament_mark(_x, _y, _ux, _uy) _x = _ux _y = _uy autotower.calculate_purgevolume() tower_fits = False while not tower_fits: purgetower.purge_create_layers( autotower.purge_minx - 1, autotower.purge_miny - 1, autotower.purge_maxx - autotower.purge_minx + 2, autotower.purge_maxy - autotower.purge_miny + 2) tower_fits = purgetower.simulate_tower( purgetower.sequence_length_solid, purgetower.sequence_length_empty, purgetower.sequence_length_fill, 5) if not tower_fits: if not autotower.tower_expand(): error("COULD NOT GENERATE SUITABLE TOWER") tower_fits = True v.purge_minx = autotower.purge_minx v.purge_miny = autotower.purge_miny v.purge_maxx = autotower.purge_maxx v.purge_maxy = autotower.purge_maxy else: expand = 0 tower_fits = False while not tower_fits: purgetower.purge_create_layers(v.purge_minx - 1, v.purge_miny - 1, v.purge_maxx - v.purge_minx + 2, v.purge_maxy - v.purge_miny + 2) tower_fits = purgetower.simulate_tower( purgetower.sequence_length_solid, purgetower.sequence_length_empty, purgetower.sequence_length_fill, 5) if not tower_fits: purgetower.tower_auto_expand(10) expand += 10 if expand > 0: warning("Tower expanded by {}mm".format(expand)) comment('Calculated purge volume : {:.3f},{:.3f} -> {:.3f},{:.3f}'.format( v.purge_minx, v.purge_miny, v.purge_maxx, v.purge_maxy)) line_idx = 0 line_count = len(v.gcodes) layer = -1 for g in v.gcodes: if g.layer != layer: layer = g.layer purgetower.checkfill(g.layer, v.maxtowerdelta / v.layer_height) line_idx += 1 gui.setprogress(50 + int(50 * line_idx / line_count)) if g.command in ["M220"]: g.move_to_comment("IGNORED COMMAND") g.issue_command() continue # no further mcf required if g.command == "M221": v.extrusion_multiplier = g.get_parameter( "S", v.extrusion_multiplier * 100) / 100 g.issue_command() continue # no further mcf required if g.command in ["T0", "T1", "T2", "T3"]: gcode.GCodeCommand(";---- {} TOOLCHANGE -----".format( g.command)).issue_command() process_tool_change(g) g.issue_command() continue # no further mcf required if g.command in [ "M104", "M106", "M109", "M140", "M190", "M73", "M900", "M84" ]: g.issue_command() continue # no further mcf required if g.is_movement_command(): 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 purgetower.moveintower(): error("MODEL COLLIDES WITH TOWER.") g.issue_command() process_tool_change(None) if v.maxdelta > 1 or v.mindelta < -1: warning( "Tower hight deviates {:.2f}mm above and {:.2f}mm below print level" .format(-v.mindelta, v.maxdelta)) warning( "Make sure to keep enough distance between tower and object to avoid collisions" ) warning( "If the tower grows over the print height, consider increasing the prime pillar width in S3D" ) gui.completed()