ENH: Increase TPU printing speed.

1.add parameters precooling_temperature, ramming ravel time,prime_tower
max speed , ramming_vol_speed;
2.support modify the wipe tower wipe and lift speed

jira: none
Change-Id: Ic9661e514ef0d4e4c0dcebb5e56f0c962e6c7b9a
This commit is contained in:
jiangkai.zhao 2025-03-14 10:56:33 +08:00 committed by lane.wei
parent ee76a2191f
commit d6fc36daba
13 changed files with 229 additions and 85 deletions

View File

@ -363,6 +363,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
double wipe_speed = gcodegen.config().role_base_wipe_speed && cur_speed > EPSILON ? cur_speed / 60 : double wipe_speed = gcodegen.config().role_base_wipe_speed && cur_speed > EPSILON ? cur_speed / 60 :
gcodegen.writer().config.travel_speed.get_at(get_extruder_index(gcodegen.writer().config, gcodegen.writer().filament()->id())) * gcodegen.config().wipe_speed.value / 100; gcodegen.writer().config.travel_speed.get_at(get_extruder_index(gcodegen.writer().config, gcodegen.writer().filament()->id())) * gcodegen.config().wipe_speed.value / 100;
if (toolchange) { wipe_speed = gcodegen.m_print->config().prime_tower_max_speed.value; }
// get the retraction length // get the retraction length
double length = toolchange double length = toolchange
@ -899,7 +900,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
gcodegen.m_wipe.reset_path(); gcodegen.m_wipe.reset_path();
for (const Vec2f& wipe_pt : tcr.wipe_path) for (const Vec2f& wipe_pt : tcr.wipe_path)
gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt) + plate_origin_2d)); gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt) + plate_origin_2d));
gcode += gcodegen.retract(false, false, auto_lift_type, true); gcode += gcodegen.retract(true, false, auto_lift_type, true);
} }
// Let the planner know we are traveling between objects. // Let the planner know we are traveling between objects.
@ -5961,9 +5962,9 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
if (m_writer.filament()->retraction_length() > 0 || m_config.use_firmware_retraction) { if (m_writer.filament()->retraction_length() > 0 || m_config.use_firmware_retraction) {
// BBS: force to use normal lift for spiral vase mode // BBS: force to use normal lift for spiral vase mode
if (apply_instantly) if (apply_instantly)
gcode += m_writer.eager_lift(lift_type); gcode += m_writer.eager_lift(lift_type,toolchange);
else else
gcode += m_writer.lazy_lift(lift_type, m_spiral_vase != nullptr); gcode += m_writer.lazy_lift(lift_type, m_spiral_vase != nullptr, toolchange);
} }

View File

@ -20,9 +20,11 @@ float flat_iron_area = 4.f;
constexpr float flat_iron_speed = 10.f * 60.f; constexpr float flat_iron_speed = 10.f * 60.f;
static const double wipe_tower_wall_infill_overlap = 0.0; static const double wipe_tower_wall_infill_overlap = 0.0;
static constexpr double WIPE_TOWER_RESOLUTION = 0.1; static constexpr double WIPE_TOWER_RESOLUTION = 0.1;
static constexpr double WT_SIMPLIFY_TOLERANCE_SCALED = 0.001 / SCALING_FACTOR; static constexpr double WT_SIMPLIFY_TOLERANCE_SCALED = 0.001 / SCALING_FACTOR;
static constexpr int arc_fit_size = 20; static constexpr int arc_fit_size = 20;
#define SCALED_WIPE_TOWER_RESOLUTION (WIPE_TOWER_RESOLUTION / SCALING_FACTOR) #define SCALED_WIPE_TOWER_RESOLUTION (WIPE_TOWER_RESOLUTION / SCALING_FACTOR)
enum class LimitFlow { None, LimitPrintFlow, LimitRammingFlow };
inline float align_round(float value, float base) inline float align_round(float value, float base)
{ {
return std::round(value / base) * base; return std::round(value / base) * base;
@ -638,7 +640,7 @@ public:
float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; } float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; }
// Extrude with an explicitely provided amount of extrusion. // Extrude with an explicitely provided amount of extrusion.
WipeTowerWriter& extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true) WipeTowerWriter &extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false ,LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{ {
if ((std::abs(x - m_current_pos.x()) <= (float)EPSILON) && (std::abs(y - m_current_pos.y()) < (float)EPSILON) && e == 0.f && (f == 0.f || f == m_current_feedrate)) if ((std::abs(x - m_current_pos.x()) <= (float)EPSILON) && (std::abs(y - m_current_pos.y()) < (float)EPSILON) && e == 0.f && (f == 0.f || f == m_current_feedrate))
// Neither extrusion nor a travel move. // Neither extrusion nor a travel move.
@ -680,9 +682,11 @@ public:
m_gcode += set_format_E(e); m_gcode += set_format_E(e);
if (f != 0.f && f != m_current_feedrate) { if (f != 0.f && f != m_current_feedrate) {
if (limit_volumetric_flow) { if (limit_flow!= LimitFlow::None) {
float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f); float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed); float tmp = m_filpar[m_current_tool].max_e_speed;
if (limit_flow == LimitFlow::LimitRammingFlow) tmp = m_filpar[m_current_tool].max_e_ramming_speed;
f /= std::max(1.f, e_speed / tmp);
} }
m_gcode += set_format_F(f); m_gcode += set_format_F(f);
} }
@ -697,7 +701,7 @@ public:
} }
// Extrude with an explicitely provided amount of extrusion. // Extrude with an explicitely provided amount of extrusion.
WipeTowerWriter &extrude_arc_explicit(ArcSegment &arc, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true) WipeTowerWriter &extrude_arc_explicit(ArcSegment &arc, float f = 0.f, bool record_length = false, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{ {
float x = (float)unscale(arc.end_point).x(); float x = (float)unscale(arc.end_point).x();
float y = (float)unscale(arc.end_point).y(); float y = (float)unscale(arc.end_point).y();
@ -747,9 +751,11 @@ public:
if (e != 0.f) m_gcode += set_format_E(e); if (e != 0.f) m_gcode += set_format_E(e);
if (f != 0.f && f != m_current_feedrate) { if (f != 0.f && f != m_current_feedrate) {
if (limit_volumetric_flow) { if (limit_flow != LimitFlow::None) {
float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f); float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed); float tmp = m_filpar[m_current_tool].max_e_speed;
if (limit_flow == LimitFlow::LimitRammingFlow) tmp = m_filpar[m_current_tool].max_e_ramming_speed;
f /= std::max(1.f, e_speed / tmp);
} }
m_gcode += set_format_F(f); m_gcode += set_format_F(f);
} }
@ -763,8 +769,10 @@ public:
return *this; return *this;
} }
WipeTowerWriter& extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, bool limit_volumetric_flow = true) WipeTowerWriter &extrude_explicit(const Vec2f &dest, float e, float f = 0.f, bool record_length = false, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{ return extrude_explicit(dest.x(), dest.y(), e, f, record_length); } {
return extrude_explicit(dest.x(), dest.y(), e, f, record_length, limit_flow);
}
// Travel to a new XY position. f=0 means use the current value. // Travel to a new XY position. f=0 means use the current value.
WipeTowerWriter& travel(float x, float y, float f = 0.f) WipeTowerWriter& travel(float x, float y, float f = 0.f)
@ -774,15 +782,15 @@ public:
{ return extrude_explicit(dest.x(), dest.y(), 0.f, f); } { return extrude_explicit(dest.x(), dest.y(), 0.f, f); }
// Extrude a line from current position to x, y with the extrusion amount given by m_extrusion_flow. // Extrude a line from current position to x, y with the extrusion amount given by m_extrusion_flow.
WipeTowerWriter& extrude(float x, float y, float f = 0.f) WipeTowerWriter &extrude(float x, float y, float f = 0.f, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{ {
float dx = x - m_current_pos.x(); float dx = x - m_current_pos.x();
float dy = y - m_current_pos.y(); float dy = y - m_current_pos.y();
return extrude_explicit(x, y, std::sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true); return extrude_explicit(x, y, std::sqrt(dx * dx + dy * dy) * m_extrusion_flow, f, false, limit_flow);
} }
WipeTowerWriter &extrude_arc(ArcSegment &arc, float f = 0.f) WipeTowerWriter &extrude_arc(ArcSegment &arc, float f = 0.f, LimitFlow limit_flow = LimitFlow::LimitPrintFlow)
{ {
return extrude_arc_explicit(arc, f, true); return extrude_arc_explicit(arc, f, false , limit_flow);
} }
WipeTowerWriter& extrude(const Vec2f &dest, const float f = 0.f) WipeTowerWriter& extrude(const Vec2f &dest, const float f = 0.f)
@ -968,7 +976,7 @@ public:
} }
float end_point = x() + (farthest_x > x() ? 1.f : -1.f) * x_distance; float end_point = x() + (farthest_x > x() ? 1.f : -1.f) * x_distance;
return extrude_explicit(end_point, y(), loading_dist, x_speed * 60.f, false, false); return extrude_explicit(end_point, y(), loading_dist, x_speed * 60.f, false, LimitFlow::None);
} }
// Elevate the extruder head above the current print_z position. // Elevate the extruder head above the current print_z position.
@ -989,8 +997,8 @@ public:
// extrude quickly amount e to x2 with feed f. // extrude quickly amount e to x2 with feed f.
WipeTowerWriter& ram(float x1, float x2, float dy, float e0, float e, float f) WipeTowerWriter& ram(float x1, float x2, float dy, float e0, float e, float f)
{ {
extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, false); extrude_explicit(x1, m_current_pos.y() + dy, e0, f, true, LimitFlow::None);
extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, false); extrude_explicit(x2, m_current_pos.y(), e, 0.f, true, LimitFlow::None);
return *this; return *this;
} }
@ -999,8 +1007,8 @@ public:
// at the current Y position to spread the leaking material. // at the current Y position to spread the leaking material.
WipeTowerWriter& cool(float x1, float x2, float e1, float e2, float f) WipeTowerWriter& cool(float x1, float x2, float e1, float e2, float f)
{ {
extrude_explicit(x1, m_current_pos.y(), e1, f, false, false); extrude_explicit(x1, m_current_pos.y(), e1, f, false, LimitFlow::None);
extrude_explicit(x2, m_current_pos.y(), e2, false, false); extrude_explicit(x2, m_current_pos.y(), e2, 0.f, false, LimitFlow::None);
return *this; return *this;
} }
@ -1507,7 +1515,8 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
m_rib_width((float)config.prime_tower_rib_width.value), m_rib_width((float)config.prime_tower_rib_width.value),
m_used_fillet(config.prime_tower_fillet_wall.value), m_used_fillet(config.prime_tower_fillet_wall.value),
m_extra_spacing((float)config.prime_tower_infill_gap.value/100.f), m_extra_spacing((float)config.prime_tower_infill_gap.value/100.f),
m_tower_framework(config.prime_tower_enable_framework.value) m_tower_framework(config.prime_tower_enable_framework.value),
m_max_speed((float)config.prime_tower_max_speed.value*60.f)
{ {
// Read absolute value of first layer speed, if given as percentage, // Read absolute value of first layer speed, if given as percentage,
// it is taken over following default. Speeds from config are not // it is taken over following default. Speeds from config are not
@ -1592,6 +1601,24 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
if (max_vol_speed!= 0.f) if (max_vol_speed!= 0.f)
m_filpar[idx].max_e_speed = (max_vol_speed / filament_area()); m_filpar[idx].max_e_speed = (max_vol_speed / filament_area());
float ramming_vol_speed = float(config.filament_ramming_volumetric_speed.get_at(idx));
if (config.filament_ramming_volumetric_speed.is_nil(idx) || is_approx(config.filament_ramming_volumetric_speed.get_at(idx),-1.)) ramming_vol_speed = max_vol_speed;
m_filpar[idx].max_e_ramming_speed = (ramming_vol_speed / filament_area());
std::unordered_set<int> uniqueElements(m_filament_map.begin(), m_filament_map.end());
m_filpar[idx].precool_t.resize(uniqueElements.size(), 0.f);
m_filpar[idx].precool_t_first_layer.resize(uniqueElements.size(), 0.f);
if (config.enable_pre_heating.value && !config.filament_pre_cooling_temperature.is_nil(idx) && config.filament_pre_cooling_temperature.get_at(idx) != 0) {
for (int i = 0; i < m_filpar[idx].precool_t.size(); i++) {
m_filpar[idx].precool_t[i] = std::max(0.f, float(config.nozzle_temperature.get_at(idx)) - float(config.filament_pre_cooling_temperature.get_at(idx))) /
float(config.hotend_cooling_rate.values.at(i));
m_filpar[idx].precool_t_first_layer[i] = std::max(0.f, float(config.nozzle_temperature_initial_layer.get_at(idx)) -
float(config.filament_pre_cooling_temperature.get_at(idx))) /
float(config.hotend_cooling_rate.values.at(i));
}
}
if (!config.filament_ramming_travel_time.is_nil(idx))
m_filpar[idx].ramming_travel_time = float(config.filament_ramming_travel_time.get_at(idx));
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter
m_nozzle_change_perimeter_width = 2*m_perimeter_width; m_nozzle_change_perimeter_width = 2*m_perimeter_width;
// BBS: remove useless config // BBS: remove useless config
@ -2507,7 +2534,7 @@ void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned in
double e_flow = nozzle_change_extrusion_flow(layer_height_par); double e_flow = nozzle_change_extrusion_flow(layer_height_par);
double length = m_filaments_change_length[old_tool] / e_flow; double length = m_filaments_change_length[old_tool] / e_flow;
int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1; int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1;
if (has_tpu_filament()) if (m_need_reverse_travel)
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width; nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width; nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
@ -2643,6 +2670,11 @@ bool WipeTower::is_tpu_filament(int filament_id) const
return m_filpar[filament_id].material == "TPU"; return m_filpar[filament_id].material == "TPU";
} }
bool WipeTower::is_need_reverse_travel(int filament_id) const
{
return m_filpar[filament_id].ramming_travel_time > EPSILON;
}
// BBS: consider both soluable and support properties // BBS: consider both soluable and support properties
// Return index of first toolchange that switches to non-soluble and non-support extruder // Return index of first toolchange that switches to non-soluble and non-support extruder
// ot -1 if there is no such toolchange. // ot -1 if there is no such toolchange.
@ -2655,14 +2687,13 @@ int WipeTower::first_toolchange_to_nonsoluble_nonsupport(
return -1; return -1;
} }
static WipeTower::ToolChangeResult merge_tcr(WipeTower::ToolChangeResult& first, WipeTower::ToolChangeResult WipeTower::merge_tcr(ToolChangeResult &first, ToolChangeResult &second)
WipeTower::ToolChangeResult& second)
{ {
assert(first.new_tool == second.initial_tool); assert(first.new_tool == second.initial_tool);
WipeTower::ToolChangeResult out = first; WipeTower::ToolChangeResult out = first;
if ((first.end_pos - second.start_pos).norm() > (float)EPSILON) { if ((first.end_pos - second.start_pos).norm() > (float)EPSILON) {
std::string travel_gcode = "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3) std::string travel_gcode = "G1 X" + Slic3r::float_to_string_decimal_point(second.start_pos.x(), 3) + " Y" +
+ " Y" + Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3) +"F5400" + "\n"; Slic3r::float_to_string_decimal_point(second.start_pos.y(), 3) + "F" + std::to_string(m_max_speed) + "\n";
bool need_insert_travel = true; bool need_insert_travel = true;
if (second.is_tool_change if (second.is_tool_change
&& is_approx(second.start_pos.x(), second.tool_change_start_pos.x()) && is_approx(second.start_pos.x(), second.tool_change_start_pos.x())
@ -2712,7 +2743,7 @@ void WipeTower::get_wall_skip_points(const WipeTowerInfo &layer)
size_t old_filament = tool_change.old_tool; size_t old_filament = tool_change.old_tool;
size_t new_filament = tool_change.new_tool; size_t new_filament = tool_change.new_tool;
float spacing = m_layer_info->extra_spacing; float spacing = m_layer_info->extra_spacing;
if (has_tpu_filament() && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1; if (m_need_reverse_travel && m_layer_info->extra_spacing < m_tpu_fixed_spacing) spacing = 1;
float nozzle_change_depth = tool_change.nozzle_change_depth * spacing; float nozzle_change_depth = tool_change.nozzle_change_depth * spacing;
//float nozzle_change_depth = tool_change.nozzle_change_depth * (has_tpu_filament() ? m_tpu_fixed_spacing : layer.extra_spacing); //float nozzle_change_depth = tool_change.nozzle_change_depth * (has_tpu_filament() ? m_tpu_fixed_spacing : layer.extra_spacing);
auto* block = get_block_by_category(m_filpar[new_filament].category, false); auto* block = get_block_by_category(m_filpar[new_filament].category, false);
@ -2775,7 +2806,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
wipe_depth = b.required_depth; wipe_depth = b.required_depth;
purge_volume = b.purge_volume; purge_volume = b.purge_volume;
nozzle_change_depth = b.nozzle_change_depth; nozzle_change_depth = b.nozzle_change_depth;
if (has_tpu_filament()) if (m_need_reverse_travel)
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2; nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2;
else else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width; nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
@ -2817,8 +2848,8 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
is_first_layer() ? m_filpar[new_tool].nozzle_temperature_initial_layer : m_filpar[new_tool].nozzle_temperature); is_first_layer() ? m_filpar[new_tool].nozzle_temperature_initial_layer : m_filpar[new_tool].nozzle_temperature);
toolchange_Change(writer, new_tool, m_filpar[new_tool].material); // Change the tool, set a speed override for soluble and flex materials. toolchange_Change(writer, new_tool, m_filpar[new_tool].material); // Change the tool, set a speed override for soluble and flex materials.
toolchange_Load(writer, cleaning_box); toolchange_Load(writer, cleaning_box);
# if 0
if (m_is_multi_extruder && is_tpu_filament(new_tool)) { if (m_is_multi_extruder && is_need_reverse_travel(new_tool)) {
float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width; float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width;
if (m_layer_info->extra_spacing < m_tpu_fixed_spacing) { if (m_layer_info->extra_spacing < m_tpu_fixed_spacing) {
dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width; dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width;
@ -2849,7 +2880,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change_new(size_t new_tool, bool sol
} }
writer.travel(initial_position); writer.travel(initial_position);
} }
#endif
toolchange_wipe_new(writer, cleaning_box, wipe_length, solid_toolchange); toolchange_wipe_new(writer, cleaning_box, wipe_length, solid_toolchange);
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n"); writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Tower_End) + "\n");
@ -2882,14 +2913,13 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
if (new_filament_id != (unsigned int) (-1)) { if (new_filament_id != (unsigned int) (-1)) {
for (const auto &b : m_layer_info->tool_changes) for (const auto &b : m_layer_info->tool_changes)
if (b.new_tool == new_filament_id) { if (b.new_tool == new_filament_id) {
if (has_tpu_filament()) if (m_need_reverse_travel)
nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2; nozzle_change_line_count = ((b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width) / 2;
else else
nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width; nozzle_change_line_count = (b.nozzle_change_depth + WT_EPSILON) / m_nozzle_change_perimeter_width;
break; break;
} }
} }
auto format_nozzle_change_line = [](bool start, int old_filament_id, int new_filament_id) -> std::string { auto format_nozzle_change_line = [](bool start, int old_filament_id, int new_filament_id) -> std::string {
char buff[64]; char buff[64];
std::string tag = start ? GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeStart) : GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeEnd); std::string tag = start ? GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeStart) : GCodeProcessor::reserved_tag(GCodeProcessor::ETags::NozzleChangeEnd);
@ -2898,13 +2928,11 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
}; };
float nz_extrusion_flow = nozzle_change_extrusion_flow(m_layer_height); float nz_extrusion_flow = nozzle_change_extrusion_flow(m_layer_height);
float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_speed / nz_extrusion_flow; float nozzle_change_speed = 60.0f * m_filpar[m_current_tool].max_e_ramming_speed / nz_extrusion_flow;
nozzle_change_speed = solid_infill ? 40.f * 60.f : nozzle_change_speed;//If the contact layers belong to different categories, then reduce the speed. if (solid_infill)
nozzle_change_speed = std::min( 40.f * 60.f , nozzle_change_speed);//If the contact layers belong to different categories, then reduce the speed.
if (is_tpu_filament(m_current_tool)) { float bridge_speed = std::min(60.0f * m_filpar[m_current_tool].max_e_ramming_speed / nozzle_change_extrusion_flow(0.2), nozzle_change_speed); // limit the bridge speed by add flow
nozzle_change_speed *= 0.25;
}
float bridge_speed = std::min(60.0f * m_filpar[m_current_tool].max_e_speed / nozzle_change_extrusion_flow(0.2), nozzle_change_speed); // limit the bridge speed by add flow
WipeTowerWriter writer(m_layer_height, m_nozzle_change_perimeter_width, m_gcode_flavor, m_filpar); WipeTowerWriter writer(m_layer_height, m_nozzle_change_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(nz_extrusion_flow) writer.set_extrusion_flow(nz_extrusion_flow)
@ -2920,13 +2948,13 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
} }
m_cur_block = block; m_cur_block = block;
float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width; float dy = m_layer_info->extra_spacing * m_nozzle_change_perimeter_width;
if (has_tpu_filament() && m_extra_spacing < m_tpu_fixed_spacing) if (m_need_reverse_travel && m_extra_spacing < m_tpu_fixed_spacing)
dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width; dy = m_tpu_fixed_spacing * m_nozzle_change_perimeter_width;
float x_offset = m_perimeter_width + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2; float x_offset = m_perimeter_width + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2;
box_coordinates cleaning_box(Vec2f(x_offset,block->cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2), box_coordinates cleaning_box(Vec2f(x_offset,block->cur_depth + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2),
m_wipe_tower_width - 2 * x_offset, m_wipe_tower_width - 2 * x_offset,
nozzle_change_line_count * dy - (m_nozzle_change_perimeter_width - m_perimeter_width) / 2); nozzle_change_line_count * dy - (m_nozzle_change_perimeter_width - m_perimeter_width) / 2);//top can not print
Vec2f initial_position = cleaning_box.ld; Vec2f initial_position = cleaning_box.ld;
writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
@ -2934,10 +2962,20 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
const float &xl = cleaning_box.ld.x(); const float &xl = cleaning_box.ld.x();
const float &xr = cleaning_box.rd.x(); const float &xr = cleaning_box.rd.x();
dy = solid_infill ? m_nozzle_change_perimeter_width : dy; dy = solid_infill ? m_nozzle_change_perimeter_width : dy;
nozzle_change_line_count = solid_infill ? std::numeric_limits<int>::max() : nozzle_change_line_count; if (solid_infill)
nozzle_change_line_count = std::floor(EPSILON + (cleaning_box.ru[1] - cleaning_box.rd[1] + (m_nozzle_change_perimeter_width - m_perimeter_width) / 2.f) /
m_nozzle_change_perimeter_width);
m_left_to_right = true; m_left_to_right = true;
int real_nozzle_change_line_count = 0;
bool need_change_flow = false; bool need_change_flow = false;
float ramming_length = nozzle_change_line_count * (xr - xl);
int extruder_id = m_filament_map[m_current_tool]-1;
float per_cooling_max_speed = m_filpar[m_current_tool].precool_t[extruder_id] > EPSILON ? ramming_length / m_filpar[m_current_tool].precool_t[extruder_id] * 60.f :
nozzle_change_speed;
if (is_first_layer())
per_cooling_max_speed = m_filpar[m_current_tool].precool_t_first_layer[extruder_id] > EPSILON ? ramming_length / m_filpar[m_current_tool].precool_t_first_layer[extruder_id] * 60.f :
nozzle_change_speed;
if (nozzle_change_speed > per_cooling_max_speed) nozzle_change_speed = per_cooling_max_speed;
if (bridge_speed > per_cooling_max_speed) bridge_speed = per_cooling_max_speed;
for (int i = 0; true; ++i) { for (int i = 0; true; ++i) {
if (need_thick_bridge_flow(writer.pos().y())) { if (need_thick_bridge_flow(writer.pos().y())) {
writer.set_extrusion_flow(nozzle_change_extrusion_flow(0.2)); writer.set_extrusion_flow(nozzle_change_extrusion_flow(0.2));
@ -2945,10 +2983,9 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
need_change_flow = true; need_change_flow = true;
} }
if (m_left_to_right) if (m_left_to_right)
writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed); writer.extrude(xr + wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed,LimitFlow::LimitRammingFlow);
else else
writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed); writer.extrude(xl - wipe_tower_wall_infill_overlap * m_perimeter_width, writer.y(), need_change_flow ? bridge_speed : nozzle_change_speed,LimitFlow::LimitRammingFlow);
real_nozzle_change_line_count++;
if (i == nozzle_change_line_count - 1) if (i == nozzle_change_line_count - 1)
break; break;
if ((writer.y() + dy - cleaning_box.ru.y()+(m_nozzle_change_perimeter_width+m_perimeter_width)/2) > (float)EPSILON) break; if ((writer.y() + dy - cleaning_box.ru.y()+(m_nozzle_change_perimeter_width+m_perimeter_width)/2) > (float)EPSILON) break;
@ -2957,29 +2994,40 @@ WipeTower::NozzleChangeResult WipeTower::nozzle_change_new(int old_filament_id,
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n"); writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
need_change_flow = false; need_change_flow = false;
} }
writer.extrude(writer.x(), writer.y() + dy, nozzle_change_speed); writer.extrude(writer.x(), writer.y() + dy, nozzle_change_speed, LimitFlow::LimitRammingFlow);
m_left_to_right = !m_left_to_right; m_left_to_right = !m_left_to_right;
} }
if (need_change_flow) { if (need_change_flow) {
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n"); writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
} }
writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow. writer.set_extrusion_flow(nz_extrusion_flow); // Reset the extrusion flow.
block->cur_depth += real_nozzle_change_line_count * dy; block->cur_depth += nozzle_change_line_count * dy;
block->last_nozzle_change_id = old_filament_id; block->last_nozzle_change_id = old_filament_id;
NozzleChangeResult result; NozzleChangeResult result;
if (is_tpu_filament(m_current_tool)) { if (is_need_reverse_travel(m_current_tool)) {
bool left_to_right = !m_left_to_right; bool left_to_right = !m_left_to_right;
int tpu_line_count = (real_nozzle_change_line_count + 2 - 1) / 2; // nozzle_change_line_count / 2 round up int tpu_line_count = nozzle_change_line_count - 1 ; // nozzle_change_line_count / 2 round up
nozzle_change_speed *= 2; if (tpu_line_count <= 0) tpu_line_count = 1;
nozzle_change_speed *= 2; // due to nozzle change 2 perimeter
float need_reverse_travel_dis = m_filpar[m_current_tool].ramming_travel_time * nozzle_change_speed/60.f;
float real_travel_dis = tpu_line_count * (xr - xl - 2 * m_perimeter_width);
if (real_travel_dis < need_reverse_travel_dis)
nozzle_change_speed *= real_travel_dis / need_reverse_travel_dis;
writer.travel(writer.x(), writer.y() - m_nozzle_change_perimeter_width); writer.travel(writer.x(), writer.y() - m_nozzle_change_perimeter_width);
for (int i = 0; true; ++i) { for (int i = 0; true; ++i) {
need_reverse_travel_dis -= (xr - xl - 2 * m_perimeter_width);
float offset_dis = 0.f;
if (need_reverse_travel_dis < 0) {
offset_dis = -need_reverse_travel_dis;
}
if (left_to_right) if (left_to_right)
writer.travel(xr - m_perimeter_width, writer.y(), nozzle_change_speed); writer.travel(xr - m_perimeter_width - offset_dis, writer.y(), nozzle_change_speed);
else else
writer.travel(xl + m_perimeter_width, writer.y(), nozzle_change_speed); writer.travel(xl + m_perimeter_width + offset_dis , writer.y(), nozzle_change_speed);
if (need_reverse_travel_dis < EPSILON) break;
if (i == tpu_line_count - 1) if (i == tpu_line_count - 1)
break; break;
@ -3020,7 +3068,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer_new(bool extrude_perimeter,
// Slow down on the 1st layer. // Slow down on the 1st layer.
bool first_layer = is_first_layer(); bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer // BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, 5400.f); float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, m_max_speed);
float fill_box_depth = m_wipe_tower_depth - 2 * m_perimeter_width; float fill_box_depth = m_wipe_tower_depth - 2 * m_perimeter_width;
if (m_wipe_tower_blocks.size() == 1) { if (m_wipe_tower_blocks.size() == 1) {
@ -3191,7 +3239,7 @@ WipeTower::ToolChangeResult WipeTower::finish_block(const WipeTowerBlock &block,
// Slow down on the 1st layer. // Slow down on the 1st layer.
bool first_layer = is_first_layer(); bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer // BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, 5400.f); float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, m_max_speed);
box_coordinates fill_box(Vec2f(0, 0), 0, 0); box_coordinates fill_box(Vec2f(0, 0), 0, 0);
fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, block.start_depth + block.layer_depths[m_cur_layer_id] - block.cur_depth - m_perimeter_width); fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, block.start_depth + block.layer_depths[m_cur_layer_id] - block.cur_depth - m_perimeter_width);
@ -3305,7 +3353,7 @@ WipeTower::ToolChangeResult WipeTower::finish_block_solid(const WipeTowerBlock &
// Slow down on the 1st layer. // Slow down on the 1st layer.
bool first_layer = is_first_layer(); bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer // BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, 5400.f); float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[filament_id].max_e_speed / m_extrusion_flow, m_max_speed);
feedrate = interface_solid ? 20.f * 60.f : feedrate; feedrate = interface_solid ? 20.f * 60.f : feedrate;
box_coordinates fill_box(Vec2f(0, 0), 0, 0); box_coordinates fill_box(Vec2f(0, 0), 0, 0);
fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width, fill_box = box_coordinates(Vec2f(m_perimeter_width, block.cur_depth), m_wipe_tower_width - 2 * m_perimeter_width,
@ -3688,7 +3736,7 @@ void WipeTower::plan_tower_new()
double e_flow = nozzle_change_extrusion_flow(m_plan[idx].height); double e_flow = nozzle_change_extrusion_flow(m_plan[idx].height);
double length = m_filaments_change_length[toolchange.old_tool] / e_flow; double length = m_filaments_change_length[toolchange.old_tool] / e_flow;
int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1; int nozzle_change_line_count = length / (m_wipe_tower_width - 2*m_nozzle_change_perimeter_width) + 1;
if (has_tpu_filament()) if (m_need_reverse_travel)
nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width; nozzle_change_depth = m_tpu_fixed_spacing * nozzle_change_line_count * m_nozzle_change_perimeter_width;
else else
nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width; nozzle_change_depth = nozzle_change_line_count * m_nozzle_change_perimeter_width;
@ -4163,7 +4211,7 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
// Slow down on the 1st layer. // Slow down on the 1st layer.
bool first_layer = is_first_layer(); bool first_layer = is_first_layer();
// BBS: speed up perimeter speed to 90mm/s for non-first layer // BBS: speed up perimeter speed to 90mm/s for non-first layer
float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, 5400.f); float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, m_max_speed) : std::min(60.0f * m_filpar[m_current_tool].max_e_speed / m_extrusion_flow, m_max_speed);
float fill_box_y = m_layer_info->toolchanges_depth() + m_perimeter_width; float fill_box_y = m_layer_info->toolchanges_depth() + m_perimeter_width;
box_coordinates fill_box(Vec2f(m_perimeter_width, fill_box_y), m_wipe_tower_width - 2 * m_perimeter_width, m_layer_info->depth - fill_box_y); box_coordinates fill_box(Vec2f(m_perimeter_width, fill_box_y), m_wipe_tower_width - 2 * m_perimeter_width, m_layer_info->depth - fill_box_y);

View File

@ -302,6 +302,15 @@ public:
void set_filament_map(const std::vector<int> &filament_map) { m_filament_map = filament_map; } void set_filament_map(const std::vector<int> &filament_map) { m_filament_map = filament_map; }
void set_has_tpu_filament(bool has_tpu) { m_has_tpu_filament = has_tpu; } void set_has_tpu_filament(bool has_tpu) { m_has_tpu_filament = has_tpu; }
void set_need_reverse_travel() {
for (int i = 0; i < m_filpar.size(); i++) {
if(m_filpar[i].ramming_travel_time>EPSILON)
{
m_need_reverse_travel = true;
return;
}
}
}
bool has_tpu_filament() const { return m_has_tpu_filament; } bool has_tpu_filament() const { return m_has_tpu_filament; }
struct FilamentParameters { struct FilamentParameters {
@ -330,6 +339,10 @@ public:
float retract_length; float retract_length;
float retract_speed; float retract_speed;
float wipe_dist; float wipe_dist;
float max_e_ramming_speed = 0.f;
float ramming_travel_time=0.f; //Travel time after ramming
std::vector<float> precool_t;//Pre-cooling time, set to 0 to ensure the ramming speed is controlled solely by ramming volumetric speed.
std::vector<float> precool_t_first_layer;
}; };
@ -433,6 +446,7 @@ private:
bool m_used_fillet{false}; bool m_used_fillet{false};
Vec2f m_rib_offset{Vec2f(0.f, 0.f)}; Vec2f m_rib_offset{Vec2f(0.f, 0.f)};
bool m_tower_framework{false}; bool m_tower_framework{false};
bool m_need_reverse_travel{false};
// G-code generator parameters. // G-code generator parameters.
// BBS: remove useless config // BBS: remove useless config
@ -480,6 +494,7 @@ private:
bool m_left_to_right = true; bool m_left_to_right = true;
float m_extra_spacing = 1.f; float m_extra_spacing = 1.f;
float m_tpu_fixed_spacing = 2; float m_tpu_fixed_spacing = 2;
float m_max_speed = 5400.f; // the maximum printing speed on the prime tower.
std::vector<Vec2f> m_wall_skip_points; std::vector<Vec2f> m_wall_skip_points;
std::map<float,Polylines> m_outer_wall; std::map<float,Polylines> m_outer_wall;
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; } bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
@ -501,7 +516,7 @@ private:
void save_on_last_wipe(); void save_on_last_wipe();
bool is_tpu_filament(int filament_id) const; bool is_tpu_filament(int filament_id) const;
bool is_need_reverse_travel(int filament) const;
// BBS // BBS
box_coordinates align_perimeter(const box_coordinates& perimeter_box); box_coordinates align_perimeter(const box_coordinates& perimeter_box);
@ -567,6 +582,7 @@ private:
const box_coordinates &cleaning_box, const box_coordinates &cleaning_box,
float wipe_volume); float wipe_volume);
void get_wall_skip_points(const WipeTowerInfo &layer); void get_wall_skip_points(const WipeTowerInfo &layer);
ToolChangeResult merge_tcr(ToolChangeResult &first, ToolChangeResult &second);
}; };

View File

@ -353,7 +353,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
/* If this method is called more than once before calling unlift(), /* If this method is called more than once before calling unlift(),
it will not perform subsequent lifts, even if Z was raised manually it will not perform subsequent lifts, even if Z was raised manually
(i.e. with travel_to_z()) and thus _lifted was reduced. */ (i.e. with travel_to_z()) and thus _lifted was reduced. */
std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase) std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase, bool tool_change)
{ {
// check whether the above/below conditions are met // check whether the above/below conditions are met
double target_lift = 0; double target_lift = 0;
@ -363,14 +363,16 @@ std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
int filament_id = filament()->id(); int filament_id = filament()->id();
double above = this->config.retract_lift_above.get_at(extruder_id); double above = this->config.retract_lift_above.get_at(extruder_id);
double below = this->config.retract_lift_below.get_at(extruder_id); double below = this->config.retract_lift_below.get_at(extruder_id);
if (m_pos.z() >= above && m_pos.z() <= below) if (m_pos.z() >= above && m_pos.z() <= below){
target_lift = this->config.z_hop.get_at(filament_id); target_lift = this->config.z_hop.get_at(filament_id);
if (tool_change && this->config.prime_tower_lift_height.value > 0) target_lift = this->config.prime_tower_lift_height.value;
}
} }
// BBS // BBS
if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) { if (m_lifted == 0 && m_to_lift == 0 && target_lift > 0) {
if (spiral_vase) { if (spiral_vase) {
m_lifted = target_lift; m_lifted = target_lift;
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z"); return this->_travel_to_z(m_pos(2) + target_lift, "lift Z",tool_change);
} }
else { else {
m_to_lift = target_lift; m_to_lift = target_lift;
@ -382,7 +384,8 @@ std::string GCodeWriter::lazy_lift(LiftType lift_type, bool spiral_vase)
// BBS: immediately execute an undelayed lift move with a spiral lift pattern // BBS: immediately execute an undelayed lift move with a spiral lift pattern
// designed specifically for subsequent gcode injection (e.g. timelapse) // designed specifically for subsequent gcode injection (e.g. timelapse)
std::string GCodeWriter::eager_lift(const LiftType type) { std::string GCodeWriter::eager_lift(const LiftType type, bool tool_change)
{
std::string lift_move; std::string lift_move;
double target_lift = 0; double target_lift = 0;
{ {
@ -391,8 +394,10 @@ std::string GCodeWriter::eager_lift(const LiftType type) {
int filament_id = filament()->id(); int filament_id = filament()->id();
double above = this->config.retract_lift_above.get_at(extruder_id); double above = this->config.retract_lift_above.get_at(extruder_id);
double below = this->config.retract_lift_below.get_at(extruder_id); double below = this->config.retract_lift_below.get_at(extruder_id);
if (m_pos.z() >= above && m_pos.z() <= below) if (m_pos.z() >= above && m_pos.z() <= below){
target_lift = this->config.z_hop.get_at(filament_id); target_lift = this->config.z_hop.get_at(filament_id);
if (tool_change && this->config.prime_tower_lift_height.value > 0) target_lift = this->config.prime_tower_lift_height.value;
}
} }
// BBS: spiral lift only safe with known position // BBS: spiral lift only safe with known position
@ -403,12 +408,12 @@ std::string GCodeWriter::eager_lift(const LiftType type) {
// spiral centra is a radius distance to the right (y=0) // spiral centra is a radius distance to the right (y=0)
Vec2d ij_offset = { radius, 0 }; Vec2d ij_offset = { radius, 0 };
if (target_lift > 0) { if (target_lift > 0) {
lift_move = this->_spiral_travel_to_z(m_pos(2) + target_lift, ij_offset, "spiral lift Z"); lift_move = this->_spiral_travel_to_z(m_pos(2) + target_lift, ij_offset, "spiral lift Z",tool_change);
} }
} }
//BBS: if position is unknown use normal lift //BBS: if position is unknown use normal lift
else if (target_lift > 0) { else if (target_lift > 0) {
lift_move = _travel_to_z(m_pos(2) + target_lift, "normal lift Z"); lift_move = _travel_to_z(m_pos(2) + target_lift, "normal lift Z",tool_change);
} }
m_lifted = target_lift; m_lifted = target_lift;
m_to_lift = 0; m_to_lift = 0;
@ -559,14 +564,16 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
return this->_travel_to_z(z, comment); return this->_travel_to_z(z, comment);
} }
std::string GCodeWriter::_travel_to_z(double z, const std::string &comment) std::string GCodeWriter::_travel_to_z(double z, const std::string &comment, bool tool_change)
{ {
m_pos(2) = z; m_pos(2) = z;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.) if (speed == 0.)
speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
if (tool_change && this->config.prime_tower_lift_speed.value>0) {
speed = this->config.prime_tower_lift_speed.value; // lift speed
}
GCodeG1Formatter w; GCodeG1Formatter w;
w.emit_z(z); w.emit_z(z);
w.emit_f(speed * 60.0); w.emit_f(speed * 60.0);
@ -575,14 +582,16 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
return w.string(); return w.string();
} }
std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment) std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment, bool tool_change)
{ {
m_pos(2) = z; m_pos(2) = z;
double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id())); double speed = this->config.travel_speed_z.get_at(get_extruder_index(this->config, filament()->id()));
if (speed == 0.) if (speed == 0.)
speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id())); speed = this->config.travel_speed.get_at(get_extruder_index(this->config, filament()->id()));
if (tool_change && this->config.prime_tower_lift_speed.value>0) {
speed = this->config.prime_tower_lift_speed.value; // lift speed
}
std::string output = "G17\n"; std::string output = "G17\n";
GCodeG2G3Formatter w(true); GCodeG2G3Formatter w(true);
w.emit_z(z); w.emit_z(z);

View File

@ -81,9 +81,9 @@ public:
std::string retract_for_toolchange(bool before_wipe = false); std::string retract_for_toolchange(bool before_wipe = false);
std::string unretract(); std::string unretract();
// do lift instantly // do lift instantly
std::string eager_lift(const LiftType type); std::string eager_lift(const LiftType type,bool tool_change = false);
// record a lift request, do realy lift in next travel // record a lift request, do realy lift in next travel
std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false); std::string lazy_lift(LiftType lift_type = LiftType::NormalLift, bool spiral_vase = false, bool tool_change=false);
std::string unlift(); std::string unlift();
Vec3d get_position() const { return m_pos; } Vec3d get_position() const { return m_pos; }
void set_position(Vec3d& in) { m_pos = in; } void set_position(Vec3d& in) { m_pos = in; }
@ -152,8 +152,8 @@ private:
std::string m_gcode_label_objects_start; std::string m_gcode_label_objects_start;
std::string m_gcode_label_objects_end; std::string m_gcode_label_objects_end;
std::string _travel_to_z(double z, const std::string &comment); std::string _travel_to_z(double z, const std::string &comment,bool tool_change=false);
std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment); std::string _spiral_travel_to_z(double z, const Vec2d &ij_offset, const std::string &comment, bool tool_change = false);
std::string _retract(double length, double restart_extra, const std::string &comment); std::string _retract(double length, double restart_extra, const std::string &comment);
}; };

View File

@ -879,8 +879,8 @@ static std::vector<std::string> s_Preset_print_options {
"inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width", "inner_wall_line_width", "outer_wall_line_width", "sparse_infill_line_width", "internal_solid_infill_line_width",
"top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow", "top_surface_line_width", "support_line_width", "infill_wall_overlap", "bridge_flow",
"elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower", "prime_tower_enable_framework", "elefant_foot_compensation", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower", "prime_tower_enable_framework",
"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points","prime_tower_max_speed",
"prime_tower_rib_wall","prime_tower_extra_rib_length","prime_tower_rib_width","prime_tower_fillet_wall","prime_tower_infill_gap", "prime_tower_rib_wall","prime_tower_extra_rib_length","prime_tower_rib_width","prime_tower_fillet_wall","prime_tower_infill_gap","prime_tower_lift_speed","prime_tower_lift_height",
"enable_circle_compensation", "circle_compensation_manual_offset", "apply_scarf_seam_on_circles", "enable_circle_compensation", "circle_compensation_manual_offset", "apply_scarf_seam_on_circles",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits", "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support","process_notes", "flush_into_infill", "flush_into_objects", "flush_into_support","process_notes",
@ -908,7 +908,7 @@ static std::vector<std::string> s_Preset_print_options {
static std::vector<std::string> s_Preset_filament_options { static std::vector<std::string> s_Preset_filament_options {
/*"filament_colour", */ "default_filament_colour","required_nozzle_HRC","filament_diameter", "filament_type", "filament_soluble", "filament_is_support","filament_scarf_seam_type", "filament_scarf_height", "filament_scarf_gap","filament_scarf_length", /*"filament_colour", */ "default_filament_colour","required_nozzle_HRC","filament_diameter", "filament_type", "filament_soluble", "filament_is_support","filament_scarf_seam_type", "filament_scarf_height", "filament_scarf_gap","filament_scarf_length",
"filament_max_volumetric_speed", "impact_strength_z", "filament_max_volumetric_speed", "impact_strength_z", "filament_ramming_volumetric_speed",
"filament_flow_ratio", "filament_density", "filament_adhesiveness_category", "filament_cost", "filament_minimal_purge_on_wipe_tower", "filament_flow_ratio", "filament_density", "filament_adhesiveness_category", "filament_cost", "filament_minimal_purge_on_wipe_tower",
"nozzle_temperature", "nozzle_temperature_initial_layer", "nozzle_temperature", "nozzle_temperature_initial_layer",
// BBS // BBS
@ -918,7 +918,7 @@ static std::vector<std::string> s_Preset_filament_options {
"counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit", "counter_limit_min", "counter_limit_max", "hole_limit_min", "hole_limit_max", "diameter_limit",
// "bed_type", // "bed_type",
//BBS:temperature_vitrification //BBS:temperature_vitrification
"temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "fan_min_speed", "temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "fan_min_speed","filament_ramming_travel_time","filament_pre_cooling_temperature",
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "pre_start_fan_time", "overhang_fan_threshold", "overhang_threshold_participating_cooling","close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed", "fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "pre_start_fan_time", "overhang_fan_threshold", "overhang_threshold_participating_cooling","close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
"filament_start_gcode", "filament_end_gcode", "filament_start_gcode", "filament_end_gcode",
//exhaust fan control //exhaust fan control

View File

@ -258,9 +258,12 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "nozzle_temperature_initial_layer" || opt_key == "nozzle_temperature_initial_layer"
|| opt_key == "filament_minimal_purge_on_wipe_tower" || opt_key == "filament_minimal_purge_on_wipe_tower"
|| opt_key == "filament_max_volumetric_speed" || opt_key == "filament_max_volumetric_speed"
|| opt_key == "filament_ramming_volumetric_speed"
|| opt_key == "gcode_flavor" || opt_key == "gcode_flavor"
|| opt_key == "single_extruder_multi_material" || opt_key == "single_extruder_multi_material"
|| opt_key == "nozzle_temperature" || opt_key == "nozzle_temperature"
|| opt_key == "filament_pre_cooling_temperature"
|| opt_key == "filament_ramming_travel_time"
// BBS // BBS
|| opt_key == "supertack_plate_temp" || opt_key == "supertack_plate_temp"
|| opt_key == "cool_plate_temp" || opt_key == "cool_plate_temp"
@ -270,6 +273,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "enable_prime_tower" || opt_key == "enable_prime_tower"
|| opt_key == "prime_tower_enable_framework" || opt_key == "prime_tower_enable_framework"
|| opt_key == "prime_tower_width" || opt_key == "prime_tower_width"
|| opt_key == "prime_tower_max_speed"
|| opt_key == "prime_tower_lift_speed"
|| opt_key == "prime_tower_lift_height"
|| opt_key == "prime_tower_brim_width" || opt_key == "prime_tower_brim_width"
|| opt_key == "prime_tower_skip_points" || opt_key == "prime_tower_skip_points"
|| opt_key == "prime_tower_rib_wall" || opt_key == "prime_tower_rib_wall"
@ -2677,7 +2683,7 @@ void Print::_make_wipe_tower()
// Set the extruder & material properties at the wipe tower object. // Set the extruder & material properties at the wipe tower object.
for (size_t i = 0; i < number_of_extruders; ++ i) for (size_t i = 0; i < number_of_extruders; ++ i)
wipe_tower.set_extruder(i, m_config); wipe_tower.set_extruder(i, m_config);
wipe_tower.set_need_reverse_travel();
// BBS: remove priming logic // BBS: remove priming logic
//m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>( //m_wipe_tower_data.priming = Slic3r::make_unique<std::vector<WipeTower::ToolChangeResult>>(
// wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false)); // wipe_tower.prime((float)this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), false));

View File

@ -36,7 +36,7 @@ class SupportLayer;
// BBS // BBS
class TreeSupportData; class TreeSupportData;
class TreeSupport; class TreeSupport;
class ExtrusionLayers; struct ExtrusionLayers;
#define MARGIN_HEIGHT 1.5 #define MARGIN_HEIGHT 1.5
#define MAX_OUTER_NOZZLE_RADIUS 4 #define MAX_OUTER_NOZZLE_RADIUS 4

View File

@ -1731,6 +1731,18 @@ void PrintConfigDef::init_fff_params()
def->nullable = true; def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable { 2. }); def->set_default_value(new ConfigOptionFloatsNullable { 2. });
def = this->add("filament_ramming_volumetric_speed", coFloats);
def->label = L("Ramming volumetric speed");
def->tooltip = L("This setting is used to define the ramming speed on the prime tower before nozzle change, "
"-1 means it will use the maximum volumetric speed.");
def->sidetext = L("mm³/s");
def->min = -1;
def->max = 200;
def->mode = comAdvanced;
def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable{-1});
def = this->add("filament_minimal_purge_on_wipe_tower", coFloats); def = this->add("filament_minimal_purge_on_wipe_tower", coFloats);
def->label = L("Minimal purge on wipe tower"); def->label = L("Minimal purge on wipe tower");
//def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside " //def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
@ -1940,6 +1952,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionInts{ 100 }); def->set_default_value(new ConfigOptionInts{ 100 });
def = this->add("filament_ramming_travel_time", coFloats);
def->label = L("Ramming travel time");
def->tooltip = L("To prevent oozing, the nozzle will perform a reverse travel movement for a certain period after "
"the ramming is complete. The setting define the travel time.");
def->mode = comAdvanced;
def->sidetext = "s";
def->min = 0;
def->nullable = true;
def->set_default_value(new ConfigOptionFloatsNullable{0});
def = this->add("filament_pre_cooling_temperature", coInts);
def->label = L("Precooling target temperature");
def->tooltip = L("This setting is used to set the target pre-cooling temperature before nozzle change to prevent oozing,"
"so if you enable this setting, your ramming time must be greater than the cooldown time."
"And this setting only takes effect when the machine has preheating. 0 means no set.");
//def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
def->mode = comAdvanced;
def->sidetext = "°C";
def->min = 0;
//def->enum_values.push_back("-1");
//def->enum_labels.push_back(L("None"));
def->nullable = true;
def->set_default_value(new ConfigOptionIntsNullable{0});
def = this->add("filament_cost", coFloats); def = this->add("filament_cost", coFloats);
def->label = L("Price"); def->label = L("Price");
def->tooltip = L("Filament price. For statistics only"); def->tooltip = L("Filament price. For statistics only");
@ -4450,6 +4486,20 @@ void PrintConfigDef::init_fff_params()
def->mode = comDevelop; def->mode = comDevelop;
def->set_default_value(new ConfigOptionFloat(0.)); def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("prime_tower_max_speed", coFloat);
def->label = L("Max speed");
def->tooltip = L("The maximum printing speed when purging in the prime tower and printing the prime tower sparse layers.");
def->sidetext = L("mm/s");
def->mode = comAdvanced;
def->min = 10;
def->set_default_value(new ConfigOptionFloat(90.));
def = this->add("prime_tower_lift_speed", coFloat);
def->set_default_value(new ConfigOptionFloat(90.));
def = this->add("prime_tower_lift_height", coFloat);
def->set_default_value(new ConfigOptionFloat(-1));
def = this->add("prime_tower_brim_width", coFloat); def = this->add("prime_tower_brim_width", coFloat);
def->gui_type = ConfigOptionDef::GUIType::f_enum_open; def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
def->label = L("Brim width"); def->label = L("Brim width");
@ -5601,6 +5651,9 @@ std::set<std::string> print_options_with_variant = {
std::set<std::string> filament_options_with_variant = { std::set<std::string> filament_options_with_variant = {
"filament_flow_ratio", "filament_flow_ratio",
"filament_max_volumetric_speed", "filament_max_volumetric_speed",
"filament_ramming_volumetric_speed",
"filament_pre_cooling_temperature",
"filament_ramming_travel_time",
//"filament_extruder_id", //"filament_extruder_id",
"filament_extruder_variant", "filament_extruder_variant",
"filament_retraction_length", "filament_retraction_length",

View File

@ -1037,7 +1037,12 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionString, filament_notes)) ((ConfigOptionString, filament_notes))
((ConfigOptionStrings, default_filament_colour)) ((ConfigOptionStrings, default_filament_colour))
((ConfigOptionInts, temperature_vitrification)) //BBS ((ConfigOptionInts, temperature_vitrification)) //BBS
((ConfigOptionFloatsNullable, filament_ramming_travel_time)) //BBS
((ConfigOptionIntsNullable, filament_pre_cooling_temperature))// BBS
((ConfigOptionFloatsNullable, filament_max_volumetric_speed)) ((ConfigOptionFloatsNullable, filament_max_volumetric_speed))
((ConfigOptionFloatsNullable, filament_ramming_volumetric_speed))
((ConfigOptionFloat, prime_tower_lift_speed))
((ConfigOptionFloat, prime_tower_lift_height))
((ConfigOptionInts, required_nozzle_HRC)) ((ConfigOptionInts, required_nozzle_HRC))
((ConfigOptionEnum<FilamentMapMode>, filament_map_mode)) ((ConfigOptionEnum<FilamentMapMode>, filament_map_mode))
((ConfigOptionInts, filament_map)) ((ConfigOptionInts, filament_map))
@ -1220,6 +1225,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_per_color_wipe)) ((ConfigOptionFloat, wipe_tower_per_color_wipe))
((ConfigOptionFloat, wipe_tower_rotation_angle)) ((ConfigOptionFloat, wipe_tower_rotation_angle))
((ConfigOptionFloat, prime_tower_brim_width)) ((ConfigOptionFloat, prime_tower_brim_width))
((ConfigOptionFloat, prime_tower_max_speed))
((ConfigOptionFloat, prime_tower_extra_rib_length)) ((ConfigOptionFloat, prime_tower_extra_rib_length))
((ConfigOptionFloat, prime_tower_rib_width)) ((ConfigOptionFloat, prime_tower_rib_width))
((ConfigOptionPercent, prime_tower_infill_gap)) ((ConfigOptionPercent, prime_tower_infill_gap))

View File

@ -691,7 +691,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, in
toggle_field("standby_temperature_delta", have_ooze_prevention); toggle_field("standby_temperature_delta", have_ooze_prevention);
bool have_prime_tower = config->opt_bool("enable_prime_tower"); bool have_prime_tower = config->opt_bool("enable_prime_tower");
for (auto el : {"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap","prime_tower_enable_framework"}) for (auto el :
{"prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_rib_wall", "prime_tower_infill_gap", "prime_tower_enable_framework", "prime_tower_max_speed"})
toggle_line(el, have_prime_tower); toggle_line(el, have_prime_tower);
bool have_rib_wall = config->opt_bool("prime_tower_rib_wall")&&have_prime_tower; bool have_rib_wall = config->opt_bool("prime_tower_rib_wall")&&have_prime_tower;

View File

@ -4255,7 +4255,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"nozzle_height", "skirt_loops", "skirt_distance", "nozzle_height", "skirt_loops", "skirt_distance",
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_tower_skip_points", "prime_tower_enable_framework","prime_tower_max_speed",
"prime_tower_rib_wall","prime_tower_extra_rib_length", "prime_tower_rib_width","prime_tower_fillet_wall", "prime_tower_infill_gap","filament_prime_volume", "prime_tower_rib_wall","prime_tower_extra_rib_length", "prime_tower_rib_width","prime_tower_fillet_wall", "prime_tower_infill_gap","filament_prime_volume",
"extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology", "extruder_colour", "filament_colour", "filament_type", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.

View File

@ -2232,6 +2232,7 @@ void TabPrint::build()
optgroup->append_single_option_line("prime_tower_skip_points", "parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_skip_points", "parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_enable_framework", "parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_enable_framework", "parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_width","parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_width","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_max_speed","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_brim_width","parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_brim_width","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_infill_gap","parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_infill_gap","parameter/prime-tower");
optgroup->append_single_option_line("prime_tower_rib_wall", "parameter/prime-tower"); optgroup->append_single_option_line("prime_tower_rib_wall", "parameter/prime-tower");
@ -3209,6 +3210,8 @@ void TabFilament::build()
//BBS //BBS
optgroup->append_single_option_line("temperature_vitrification"); optgroup->append_single_option_line("temperature_vitrification");
optgroup->append_single_option_line("filament_ramming_travel_time", "",0);
optgroup->append_single_option_line("filament_pre_cooling_temperature", "", 0);
Line line = { L("Recommended nozzle temperature"), L("Recommended nozzle temperature range of this filament. 0 means no set") }; Line line = { L("Recommended nozzle temperature"), L("Recommended nozzle temperature range of this filament. 0 means no set") };
line.append_option(optgroup->get_option("nozzle_temperature_range_low")); line.append_option(optgroup->get_option("nozzle_temperature_range_low"));
line.append_option(optgroup->get_option("nozzle_temperature_range_high")); line.append_option(optgroup->get_option("nozzle_temperature_range_high"));
@ -3292,6 +3295,7 @@ void TabFilament::build()
//BBS //BBS
optgroup = page->new_optgroup(L("Volumetric speed limitation"), L"param_volumetric_speed"); optgroup = page->new_optgroup(L("Volumetric speed limitation"), L"param_volumetric_speed");
optgroup->append_single_option_line("filament_max_volumetric_speed", "", 0); optgroup->append_single_option_line("filament_max_volumetric_speed", "", 0);
optgroup->append_single_option_line("filament_ramming_volumetric_speed", "",0);
// BBS // BBS
optgroup = page->new_optgroup(L("Filament scarf seam settings"), L"param_volumetric_speed"); optgroup = page->new_optgroup(L("Filament scarf seam settings"), L"param_volumetric_speed");