From c99fcd454c2499b0c0e3ed9402a2182c00a9bffa Mon Sep 17 00:00:00 2001 From: "xun.zhang" Date: Sat, 4 Jan 2025 16:46:59 +0800 Subject: [PATCH] ENH: refine time estimation in filament change 1.Add sync command. Now gcode and dirrectly add time sync command 2.Add support for ceil and floor in placeholder 3.Update change filament gcode for H2D jira: NONE Signed-off-by: xun.zhang Change-Id: I6dd97cbd96bae1c2751c08357ff64947876d7471 --- .../BBL/machine/Bambu Lab H2D 0.4 nozzle.json | 10 +- src/libslic3r/GCode/GCodeProcessor.cpp | 98 ++++++++++++++++++- src/libslic3r/GCode/GCodeProcessor.hpp | 2 + src/libslic3r/PlaceholderParser.cpp | 38 +++++++ 4 files changed, 141 insertions(+), 7 deletions(-) diff --git a/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json index 83db5a8ec..955ad456f 100644 --- a/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json @@ -27,6 +27,7 @@ "0x0,325x0,325x320,0x320", "25x0,350x0,350x320,25x320" ], + "machine_load_filament_time": "24", "machine_max_acceleration_x": [ "16000", "16000", @@ -77,11 +78,9 @@ "30", "30" ], + "machine_switch_extruder_time": "5.6", + "machine_unload_filament_time": "24", "master_extruder_id": "2", - "physical_extruder_map": [ - "1", - "0" - ], "printable_area": [ "0x0", "350x0", @@ -99,5 +98,6 @@ "machine_end_gcode": ";===== date: 2024/12/19 =====================\n;===== H2D =====================\nG392 S0 ;turn off nozzle clog detect\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if timelapse_type == 2}\nM991 S0 P-1 ;end timelapse immediately\n{endif}\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-0.8 F1800 ; retract\nG1 Z{max_layer_z + 0.5} F900 ; lower z a little\n\nG90\nG150.3\n\n{if timelapse_type == 1}\nM991 S0 P-1 ;end timelapse at safe pos\n{endif}\n\nM141 S0 ; turn off chamber heating\nM140 S0 ; turn off bed\nM106 S0 ; turn off fan\nM106 P2 S0 ; turn off remote part cooling fan\nM106 P3 S0 ; turn off chamber cooling fan\n\n; pull back filament to AMS\nM620 S65535\nT65535\nG150.2\nM621 S65535\n\nM620 S65279\nT65279\nG150.2\nM621 S65279\n\nG150.3\n\nM104 S0 T0; turn off hotend\nM104 S0 T1; turn off hotend\n\nM400 ; wait all motion done\nM17 S\nM17 Z0.4 ; lower z motor current to reduce impact if there is something in the bottom\n{if (max_layer_z + 100.0) < 320}\n G1 Z{max_layer_z + 100.0} F600\n G1 Z{max_layer_z +98.0}\n{else}\n G1 Z320 F600\n G1 Z320\n{endif}\nM400 P100\nM17 R ; restore z current\n\nM220 S100 ; Reset feedrate magnitude\nM201.2 K1.0 ; Reset acc magnitude\nM73.2 R1.0 ;Reset left time magnitude\nM1002 set_gcode_claim_speed_level : 0\n\nM1015.4 S0 K0 ;disable air printing detect\n;=====printer finish sound=========\nM17\nM400 S1\nM1006 S1\nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A53 B10 L99 C53 D10 M99 E53 F10 N99 \nM1006 A57 B10 L99 C57 D10 M99 E57 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A48 B10 L99 C48 D10 M99 E48 F10 N99 \nM1006 A0 B15 L0 C0 D15 M0 E0 F15 N0 \nM1006 A60 B10 L99 C60 D10 M99 E60 F10 N99 \nM1006 W\n;=====printer finish sound=========\nM400\nM18\n\n", "layer_change_gcode": ";======== H2D 20250101========\n; layer num/total_layer_count: {layer_num+1}/[total_layer_count]\n; update layer progress\nM73 L{layer_num+1}\nM991 S0 P{layer_num} ;notify layer change", "time_lapse_gcode": ";======== H2D 20250101========\nM622.1 S1 ; for prev firware, default turned on\n\nM1002 judge_flag timelapse_record_flag\nM622 J1\nM9712 E{most_used_physical_extruder_id} M{timelapse_type}\nM83\nG1 E-[retraction_length] F1800\nG17\nG2 Z{layer_z + 0.4} I0.86 J0.86 P1 F20000 ; spiral lift a little\nG1 Z{max_layer_z + 0.4} F1200\nM400\nM9713\n\nM9711 M{timelapse_type} E{most_used_physical_extruder_id} Z{layer_z} S11 C10 O0 T3000\n\nM9712 E{most_used_physical_extruder_id}\nG90\n;G1 Z{max_layer_z + 3.0} F1200\nG1 Y295 F30000\nG1 Y265 F18000\nM83\nG1 E[retraction_length] F300\nM9713\nM623", - "change_filament_gcode": ";======== H2D ========\n;===== 2024/12/23 =====\nM993 A2 B2 C2 ; nozzle cam detection allow status save.\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K0 ;disable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\n\n;nozzle_change_gcode\n\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\n\nM620.10 A0 F{filament_max_volumetric_speed[current_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[current_extruder]} T{nozzle_temperature_range_high[current_extruder]} P{nozzle_temperature[current_extruder]}\nM620.10 A1 F{filament_max_volumetric_speed[next_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[next_extruder]} T{nozzle_temperature_range_high[next_extruder]} P{nozzle_temperature[next_extruder]}\n\n{if filament_type[current_extruder] == \"TPU\"}\nM620.11 S0 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\nM620.11 S1 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{endif}\n\n{if filament_type[current_extruder] == \"TPU\" || filament_type[next_extruder] == \"TPU\"}\nM620.11 H2 C331\n{else}\nM620.11 H0\n{endif}\n\nT[next_extruder]\n\n; VFLUSH_START\n{if flush_length>41.5}\n;VG1 E41.5 F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n;VG1 E{flush_length-41.5} F{new_filament_e_feedrate}\n{else}\n;VG1 E{flush_length} F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n{endif}\n; VFLUSH_END\n\nM400\nM83\n{if next_extruder < 255}\n\nM628 S0\n\nM629\nM400\n\nM983.3 F{filament_max_volumetric_speed[next_extruder]/2.4} A0.4\n\nM400\n{if wipe_avoid_perimeter}\nG1 Y320\nG1 X{wipe_avoid_pos_x} F30000\n{endif}\nG1 Y295 F30000\nG1 Y265 F18000\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n\nM993 A3 B3 C3 ; nozzle cam detection allow status restore.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K1 H[nozzle_diameter] ;enable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620.6 I[next_extruder] W1 ;enable ams air printing detect\n\n" + "change_filament_gcode": ";======== H2D ========\n;===== 2025/01/09 =====\nM993 A2 B2 C2 ; nozzle cam detection allow status save.\nM993 A0 B0 C0 ; nozzle cam detection not allowed.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K0 ;disable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\nM620 S[next_extruder]A\nM204 S9000\n{if toolchange_count > 1 && (z_hop_types[current_extruder] == 0 || z_hop_types[current_extruder] == 3)}\nG17\nG2 Z{z_after_toolchange + 0.4} I0.86 J0.86 P1 F10000 ; spiral lift a little from second lift\n{endif}\n\n;nozzle_change_gcode\n\nG1 Z{max_layer_z + 3.0} F1200\n\nM400\nM106 P1 S0\nM106 P2 S0\n\n{if toolchange_count == 2}\n; get travel path for change filament\n;M620.1 X[travel_point_1_x] Y[travel_point_1_y] F21000 P0\n;M620.1 X[travel_point_2_x] Y[travel_point_2_y] F21000 P1\n;M620.1 X[travel_point_3_x] Y[travel_point_3_y] F21000 P2\n{endif}\n\nM620.10 A0 F{filament_max_volumetric_speed[current_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[current_extruder]} T{nozzle_temperature_range_high[current_extruder]} P{nozzle_temperature[current_extruder]}\nM620.10 A1 F{filament_max_volumetric_speed[next_extruder]/2.4053*60} L[flush_length] H{nozzle_diameter[next_extruder]} T{nozzle_temperature_range_high[next_extruder]} P{nozzle_temperature[next_extruder]}\n\n{if filament_type[current_extruder] == \"TPU\"}\nM620.11 S0 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{else}\nM620.11 S1 L0 I[current_extruder] E-{retraction_distances_when_cut[current_extruder]} F{max((filament_max_volumetric_speed[current_extruder]/2.4053*60), 200)}\n{endif}\n\n{if filament_type[current_extruder] == \"TPU\" || filament_type[next_extruder] == \"TPU\"}\nM620.11 H2 C331\n{else}\nM620.11 H0\n{endif}\n\nT[next_extruder]\n\n;deretract\n{if filament_type[next_extruder] == \"TPU\"}\n{else}\n{if filament_type[next_extruder] == \"PA\"}\n;VG1 E1 F{max(new_filament_e_feedrate, 200)}\n;VG1 E1 F{max(new_filament_e_feedrate/2, 100)}\n{else}\n;VG1 E4 F{max(new_filament_e_feedrate, 200)}\n;VG1 E4 F{max(new_filament_e_feedrate/2, 100)}\n{endif}\n{endif}\n\n; VFLUSH_START\n\n{if flush_length>41.5}\n;VG1 E41.5 F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n;VG1 E{flush_length-41.5} F{new_filament_e_feedrate}\n{else}\n;VG1 E{flush_length} F{min(old_filament_e_feedrate,new_filament_e_feedrate)}\n{endif}\n\nSYNC T{ceil(flush_length / 125) * 5}\n\n; VFLUSH_END\n\nM400\nM83\n{if next_extruder < 255}\n\nM628 S0\n\nM629\nM400\n\nM983.3 F{filament_max_volumetric_speed[next_extruder]/2.4} A0.4\n\nM400\n{if wipe_avoid_perimeter}\nG1 Y320\nG1 X{wipe_avoid_pos_x} F30000\n{endif}\nG1 Y295 F30000\nG1 Y265 F18000\nG1 Z{max_layer_z + 3.0} F3000\n{if layer_z <= (initial_layer_print_height + 0.001)}\nM204 S[initial_layer_acceleration]\n{else}\nM204 S[default_acceleration]\n{endif}\n{else}\nG1 X[x_after_toolchange] Y[y_after_toolchange] Z[z_after_toolchange] F12000\n{endif}\nM621 S[next_extruder]A\n\nM993 A3 B3 C3 ; nozzle cam detection allow status restore.\n\n{if (filament_type[next_extruder] == \"PLA\") || (filament_type[next_extruder] == \"PETG\")\n || (filament_type[next_extruder] == \"PLA-CF\") || (filament_type[next_extruder] == \"PETG-CF\")\n || (filament_type[next_extruder] == \"PA-CF\") || (filament_type[next_extruder] == \"PET-CF\")}\nM1015.4 S1 K1 H[nozzle_diameter] ;enable E air printing detect\n{else}\nM1015.4 S0 ; disable E air printing detect\n{endif}\n\nM620.6 I[next_extruder] W1 ;enable ams air printing detect\n\n" + } \ No newline at end of file diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index fd2021697..0f6e70b3c 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2571,6 +2571,29 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool case 'T': process_T(line); // Select Tool break; + case 'S': + switch (cmd.size()) { + case 4: + switch (cmd[1]){ + case 'Y': + switch (cmd[2]){ + case 'N': + switch (cmd[3]){ + case 'C': + process_SYNC(line); + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; + default: break; + } + break; default: break; } @@ -4016,8 +4039,69 @@ void GCodeProcessor::process_VG1(const GCodeReader::GCodeLine& line) return; EMoveType type = move_type(delta_pos); - // BBS: now we only support virtual flush - if (EMoveType::Unretract == type && m_virtual_flushing) { + if (type == EMoveType::Extrude) { + float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); + float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; + float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; + + if(m_extrusion_role == ExtrusionRole::erSupportMaterial || m_extrusion_role == ExtrusionRole::erSupportMaterialInterface || m_extrusion_role ==ExtrusionRole::erSupportTransition) + m_used_filaments.increase_support_caches(volume_extruded_filament); + else if (m_extrusion_role==ExtrusionRole::erWipeTower) { + m_used_filaments.increase_wipe_tower_caches(volume_extruded_filament); + } + else { + // save extruded volume to the cache + m_used_filaments.increase_model_caches(volume_extruded_filament); + } + // volume extruded filament / tool displacement = area toolpath cross section + m_mm3_per_mm = area_toolpath_cross_section; +#if ENABLE_GCODE_VIEWER_DATA_CHECKING + m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role); +#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING + + if (m_forced_height > 0.0f) + m_height = m_forced_height; + else { + if (m_end_position[Z] > m_extruded_last_z + EPSILON) + m_height = m_end_position[Z] - m_extruded_last_z; + } + + if (m_height == 0.0f) + m_height = DEFAULT_TOOLPATH_HEIGHT; + + if (m_end_position[Z] == 0.0f) + m_end_position[Z] = m_height; + + m_extruded_last_z = m_end_position[Z]; + m_options_z_corrector.update(m_height); + +#if ENABLE_GCODE_VIEWER_DATA_CHECKING + m_height_compare.update(m_height, m_extrusion_role); +#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING + + if (m_forced_width > 0.0f) + m_width = m_forced_width; + else if (m_extrusion_role == erExternalPerimeter) + // cross section: rectangle + m_width = delta_pos[E] * static_cast(M_PI * sqr(1.05f * filament_radius)) / (delta_xyz * m_height); + else if (m_extrusion_role == erBridgeInfill || m_extrusion_role == erNone) + // cross section: circle + m_width = static_cast(m_result.filament_diameters[filament_id]) * std::sqrt(delta_pos[E] / delta_xyz); + else + // cross section: rectangle + 2 semicircles + m_width = delta_pos[E] * static_cast(M_PI * sqr(filament_radius)) / (delta_xyz * m_height) + static_cast(1.0 - 0.25 * M_PI) * m_height; + + if (m_width == 0.0f) + m_width = DEFAULT_TOOLPATH_WIDTH; + + // clamp width to avoid artifacts which may arise from wrong values of m_height + m_width = std::min(m_width, std::max(2.0f, 4.0f * m_height)); + +#if ENABLE_GCODE_VIEWER_DATA_CHECKING + m_width_compare.update(m_width, m_extrusion_role); +#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING + } + else if (EMoveType::Unretract == type && m_virtual_flushing) { int extruder_id = get_extruder_id(); float volume_flushed_filament = area_filament_cross_section * delta_pos[E]; if (m_remaining_volume[extruder_id] > volume_flushed_filament) @@ -5208,6 +5292,16 @@ void GCodeProcessor::process_M702(const GCodeReader::GCodeLine& line) } } + +void GCodeProcessor::process_SYNC(const GCodeReader::GCodeLine& line) +{ + float time = 0; + if (line.has_value('T', time) ) { + simulate_st_synchronize(time); + } +} + + void GCodeProcessor::process_T(const GCodeReader::GCodeLine& line) { process_T(line.cmd()); diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index e3088285b..47bd167bb 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -1182,6 +1182,8 @@ namespace Slic3r { // Unload the current filament into the MK3 MMU2 unit at the end of print. void process_M702(const GCodeReader::GCodeLine& line); + void process_SYNC(const GCodeReader::GCodeLine& line); + // Processes T line (Select Tool) void process_T(const GCodeReader::GCodeLine& line); void process_T(const std::string_view command); diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index ee563e9d0..10dd7f6c1 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -361,6 +361,36 @@ namespace client return expr(); } + expr floor(const Iterator start_pos)const + { + switch (this->type) { + case TYPE_INT: + return expr(this->i(), start_pos, this->it_range.end()); + case TYPE_DOUBLE: + return expr(static_cast(std::floor(this->d())), start_pos, this->it_range.end()); + default: + this->throw_exception("Cannot floor a non-numeric value."); + } + assert(false); + // Suppress compiler warnings. + return expr(); + } + + expr ceil(const Iterator start_pos)const + { + switch (this->type) { + case TYPE_INT: + return expr(this->i(), start_pos, this->it_range.end()); + case TYPE_DOUBLE: + return expr(static_cast(std::ceil(this->d())), start_pos, this->it_range.end()); + default: + this->throw_exception("Cannot ceil a non-numeric value."); + } + assert(false); + // Suppress compiler warnings. + return expr(); + } + expr unary_not(const Iterator start_pos) const { switch (this->type) { @@ -1322,6 +1352,10 @@ namespace client { out = value.unary_integer(out.it_range.begin()); } static void round(expr &value, expr &out) { out = value.round(out.it_range.begin()); } + static void floor(expr &value, expr &out) + { out = value.floor(out.it_range.begin()); } + static void ceil(expr &value, expr &out) + { out = value.ceil(out.it_range.begin());} // For indicating "no optional parameter". static void noexpr(expr &out) { out.reset(); } }; @@ -1344,6 +1378,8 @@ namespace client [ px::bind(&expr::template digits, _val, _2, _3) ] | (kw["int"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ] | (kw["round"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::round, _1, _val) ] + | (kw["ceil"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::ceil, _1, _val) ] + | (kw["floor"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::floor, _1, _val) ] | (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ] | (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ] | (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ] @@ -1390,6 +1426,8 @@ namespace client ("random") ("filament_change") ("round") + ("floor") + ("ceil") ("not") ("or") ("true");