Merge branch 'lm_wipe_tower_speed_and_ramming'

This commit is contained in:
Lukas Matena 2023-08-21 12:25:54 +02:00
commit 378ae20f98
8 changed files with 118 additions and 19 deletions

View File

@ -239,9 +239,12 @@ namespace Slic3r {
const bool needs_toolchange = gcodegen.writer().need_toolchange(new_extruder_id); const bool needs_toolchange = gcodegen.writer().need_toolchange(new_extruder_id);
const bool will_go_down = ! is_approx(z, current_z); const bool will_go_down = ! is_approx(z, current_z);
if (tcr.force_travel || ! needs_toolchange || (gcodegen.config().single_extruder_multi_material && ! tcr.priming)) { const bool is_ramming = (gcodegen.config().single_extruder_multi_material && ! tcr.priming)
// Move over the wipe tower. If this is not single-extruder MM, the first wipe tower move following the || (! gcodegen.config().single_extruder_multi_material && gcodegen.config().filament_multitool_ramming.get_at(tcr.initial_tool));
// toolchange will travel there anyway (if there is a toolchange). const bool should_travel_to_tower = tcr.force_travel // wipe tower says so
|| ! needs_toolchange // this is just finishing the tower with no toolchange
|| is_ramming;
if (should_travel_to_tower) {
// FIXME: It would be better if the wipe tower set the force_travel flag for all toolchanges, // FIXME: It would be better if the wipe tower set the force_travel flag for all toolchanges,
// then we could simplify the condition and make it more readable. // then we could simplify the condition and make it more readable.
gcode += gcodegen.retract(); gcode += gcodegen.retract();
@ -251,6 +254,9 @@ namespace Slic3r {
ExtrusionRole::Mixed, ExtrusionRole::Mixed,
"Travel to a Wipe Tower"); "Travel to a Wipe Tower");
gcode += gcodegen.unretract(); gcode += gcodegen.unretract();
} else {
// When this is multiextruder printer without any ramming, we can just change
// the tool without travelling to the tower.
} }
if (will_go_down) { if (will_go_down) {
@ -262,7 +268,7 @@ namespace Slic3r {
std::string toolchange_gcode_str; std::string toolchange_gcode_str;
std::string deretraction_str; std::string deretraction_str;
if (tcr.priming || (new_extruder_id >= 0 && needs_toolchange)) { if (tcr.priming || (new_extruder_id >= 0 && needs_toolchange)) {
if (gcodegen.config().single_extruder_multi_material) if (is_ramming)
gcodegen.m_wipe.reset_path(); // We don't want wiping on the ramming lines. gcodegen.m_wipe.reset_path(); // We don't want wiping on the ramming lines.
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z); // TODO: toolchange_z vs print_z toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z); // TODO: toolchange_z vs print_z
if (gcodegen.config().wipe_tower) if (gcodegen.config().wipe_tower)

View File

@ -559,6 +559,7 @@ WipeTower::WipeTower(const PrintConfig& config, const PrintRegionConfig& default
m_extra_loading_move = float(config.extra_loading_move); m_extra_loading_move = float(config.extra_loading_move);
m_set_extruder_trimpot = config.high_current_on_filament_swap; m_set_extruder_trimpot = config.high_current_on_filament_swap;
} }
// Calculate where the priming lines should be - very naive test not detecting parallelograms etc. // Calculate where the priming lines should be - very naive test not detecting parallelograms etc.
const std::vector<Vec2d>& bed_points = config.bed_shape.values; const std::vector<Vec2d>& bed_points = config.bed_shape.values;
BoundingBoxf bb(bed_points); BoundingBoxf bb(bed_points);
@ -625,6 +626,24 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
m_filpar[idx].ramming_step_multiplicator /= 100; m_filpar[idx].ramming_step_multiplicator /= 100;
while (stream >> speed) while (stream >> speed)
m_filpar[idx].ramming_speed.push_back(speed); m_filpar[idx].ramming_speed.push_back(speed);
// ramming_speed now contains speeds to be used for every 0.25s piece of the ramming line.
// This allows to have the ramming flow variable. The 0.25s value is how it is saved in config
// and the same time step has to be used when the ramming is performed.
} else {
// We will use the same variables internally, but the correspondence to the configuration options will be different.
float vol = config.filament_multitool_ramming_volume.get_at(idx);
float flow = config.filament_multitool_ramming_flow.get_at(idx);
m_filpar[idx].multitool_ramming = config.filament_multitool_ramming.get_at(idx);
m_filpar[idx].ramming_line_width_multiplicator = 2.;
m_filpar[idx].ramming_step_multiplicator = 1.;
// Now the ramming speed vector. In this case it contains just one value (flow).
// The time is calculated and saved separately. This is here so that the MM ramming
// is not limited by the 0.25s granularity - it is not possible to create a SEMM-style
// ramming_speed vector that would respect both the volume and flow (because of
// rounding issues with small volumes and high flow).
m_filpar[idx].ramming_speed.push_back(flow);
m_filpar[idx].multitool_ramming_time = vol/flow;
} }
m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later
@ -839,12 +858,17 @@ void WipeTower::toolchange_Unload(
float remaining = xr - xl ; // keeps track of distance to the next turnaround float remaining = xr - xl ; // keeps track of distance to the next turnaround
float e_done = 0; // measures E move done from each segment float e_done = 0; // measures E move done from each segment
if (m_semm) const bool do_ramming = m_semm || m_filpar[m_current_tool].multitool_ramming;
if (do_ramming) {
writer.travel(ramming_start_pos); // move to starting position writer.travel(ramming_start_pos); // move to starting position
writer.disable_linear_advance();
}
else else
writer.set_position(ramming_start_pos); writer.set_position(ramming_start_pos);
// if the ending point of the ram would end up in mid air, align it with the end of the wipe tower: // if the ending point of the ram would end up in mid air, align it with the end of the wipe tower:
if (m_semm && (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion ))) { if (do_ramming && (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion ))) {
// this is y of the center of previous sparse infill border // this is y of the center of previous sparse infill border
float sparse_beginning_y = 0.f; float sparse_beginning_y = 0.f;
@ -873,15 +897,17 @@ void WipeTower::toolchange_Unload(
} }
} }
writer.disable_linear_advance();
// now the ramming itself: // now the ramming itself:
while (m_semm && i < m_filpar[m_current_tool].ramming_speed.size()) while (do_ramming && i < m_filpar[m_current_tool].ramming_speed.size())
{ {
const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height); // The time step is different for SEMM ramming and the MM ramming. See comments in set_extruder() for details.
const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move; const float time_step = m_semm ? 0.25f : m_filpar[m_current_tool].multitool_ramming_time;
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround
const float actual_time = dist/x * 0.25f; const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * time_step, line_width, m_layer_height);
const float e = m_filpar[m_current_tool].ramming_speed[i] * time_step / filament_area(); // transform volume per sec to E move;
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next time_step, or to the next turnaround
const float actual_time = dist/x * time_step;
writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0.f, 0.f, e * (dist / x), dist / (actual_time / 60.f)); writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0.f, 0.f, e * (dist / x), dist / (actual_time / 60.f));
remaining -= dist; remaining -= dist;
@ -953,7 +979,7 @@ void WipeTower::toolchange_Unload(
// this is to align ramming and future wiping extrusions, so the future y-steps can be uniform from the start: // this is to align ramming and future wiping extrusions, so the future y-steps can be uniform from the start:
// the perimeter_width will later be subtracted, it is there to not load while moving over just extruded material // the perimeter_width will later be subtracted, it is there to not load while moving over just extruded material
Vec2f pos = Vec2f(end_of_ramming.x(), end_of_ramming.y() + (y_step/m_extra_spacing-m_perimeter_width) / 2.f + m_perimeter_width); Vec2f pos = Vec2f(end_of_ramming.x(), end_of_ramming.y() + (y_step/m_extra_spacing-m_perimeter_width) / 2.f + m_perimeter_width);
if (m_semm) if (do_ramming)
writer.travel(pos, 2400.f); writer.travel(pos, 2400.f);
else else
writer.set_position(pos); writer.set_position(pos);
@ -1040,8 +1066,9 @@ void WipeTower::toolchange_Wipe(
// the ordered volume, even if it means violating the box. This can later be removed and simply // the ordered volume, even if it means violating the box. This can later be removed and simply
// wipe until the end of the assigned area. // wipe until the end of the assigned area.
float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height); float x_to_wipe = volume_to_length(wipe_volume, m_perimeter_width, m_layer_height) * (is_first_layer() ? m_extra_spacing : 1.f);
float dy = m_extra_spacing*m_perimeter_width; float dy = (is_first_layer() ? 1.f : m_extra_spacing) * m_perimeter_width; // Don't use the extra spacing for the first layer.
// All the calculations in all other places take the spacing into account for all the layers.
const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : m_infill_speed * 60.f; const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : m_infill_speed * 60.f;
float wipe_speed = 0.33f * target_speed; float wipe_speed = 0.33f * target_speed;

View File

@ -241,6 +241,8 @@ public:
std::vector<float> ramming_speed; std::vector<float> ramming_speed;
float nozzle_diameter; float nozzle_diameter;
float filament_area; float filament_area;
bool multitool_ramming;
float multitool_ramming_time = 0.f;
}; };
private: private:

View File

@ -468,13 +468,14 @@ static std::vector<std::string> s_Preset_filament_options {
"extrusion_multiplier", "filament_density", "filament_cost", "filament_spool_weight", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time", "extrusion_multiplier", "filament_density", "filament_cost", "filament_spool_weight", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time",
"filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves", "filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves",
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower",
"filament_multitool_ramming", "filament_multitool_ramming_volume", "filament_multitool_ramming_flow",
"temperature", "idle_temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "temperature", "idle_temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed",
"max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "full_fan_speed_layer", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed",
"start_filament_gcode", "end_filament_gcode", "enable_dynamic_fan_speeds", "start_filament_gcode", "end_filament_gcode", "enable_dynamic_fan_speeds",
"overhang_fan_speed_0", "overhang_fan_speed_1", "overhang_fan_speed_2", "overhang_fan_speed_3", "overhang_fan_speed_0", "overhang_fan_speed_1", "overhang_fan_speed_2", "overhang_fan_speed_3",
// Retract overrides // Retract overrides
"filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel", "filament_retract_length", "filament_retract_lift", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_speed", "filament_deretract_speed", "filament_retract_restart_extra", "filament_retract_before_travel",
"filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", "filament_retract_length_toolchange", "filament_retract_restart_extra_toolchange",
// Profile compatibility // Profile compatibility
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits" "filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits"
}; };

View File

@ -194,6 +194,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "filament_cooling_initial_speed" || opt_key == "filament_cooling_initial_speed"
|| opt_key == "filament_cooling_final_speed" || opt_key == "filament_cooling_final_speed"
|| opt_key == "filament_ramming_parameters" || opt_key == "filament_ramming_parameters"
|| opt_key == "filament_multitool_ramming"
|| opt_key == "filament_multitool_ramming_volume"
|| opt_key == "filament_multitool_ramming_flow"
|| opt_key == "filament_max_volumetric_speed" || opt_key == "filament_max_volumetric_speed"
|| opt_key == "gcode_flavor" || opt_key == "gcode_flavor"
|| opt_key == "high_current_on_filament_swap" || opt_key == "high_current_on_filament_swap"

View File

@ -1103,6 +1103,30 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert; def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats { 0. }); def->set_default_value(new ConfigOptionFloats { 0. });
def = this->add("filament_multitool_ramming", coBools);
def->label = L("Enable ramming for multitool setups");
def->tooltip = L("Perform ramming when using multitool printer (i.e. when the 'Single Extruder Multimaterial' in Printer Settings is unchecked). "
"When checked, a small amount of filament is rapidly extruded on the wipe tower just before the toolchange. "
"This option is only used when the wipe tower is enabled.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBools { false });
def = this->add("filament_multitool_ramming_volume", coFloats);
def->label = L("Multitool ramming volume");
def->tooltip = L("The volume to be rammed before the toolchange.");
def->sidetext = L("mm³");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats { 10. });
def = this->add("filament_multitool_ramming_flow", coFloats);
def->label = L("Multitool ramming flow");
def->tooltip = L("Flow used for ramming the filament before the toolchange.");
def->sidetext = L("mm³/s");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloats { 10. });
def = this->add("filament_diameter", coFloats); def = this->add("filament_diameter", coFloats);
def->label = L("Diameter"); def->label = L("Diameter");
def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper " def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper "
@ -3376,7 +3400,8 @@ void PrintConfigDef::init_fff_params()
// Declare retract values for filament profile, overriding the printer's extruder profile. // Declare retract values for filament profile, overriding the printer's extruder profile.
for (const char *opt_key : { for (const char *opt_key : {
// floats // floats
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed",
"deretract_speed", "retract_restart_extra", "retract_before_travel", "retract_length_toolchange", "retract_restart_extra_toolchange",
// bools // bools
"retract_layer_change", "wipe", "retract_layer_change", "wipe",
// percents // percents
@ -3415,10 +3440,12 @@ void PrintConfigDef::init_extruder_option_keys()
"retract_before_wipe", "retract_before_wipe",
"retract_layer_change", "retract_layer_change",
"retract_length", "retract_length",
"retract_length_toolchange",
"retract_lift", "retract_lift",
"retract_lift_above", "retract_lift_above",
"retract_lift_below", "retract_lift_below",
"retract_restart_extra", "retract_restart_extra",
"retract_restart_extra_toolchange",
"retract_speed", "retract_speed",
"wipe" "wipe"
}; };

View File

@ -689,6 +689,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloats, filament_minimal_purge_on_wipe_tower)) ((ConfigOptionFloats, filament_minimal_purge_on_wipe_tower))
((ConfigOptionFloats, filament_cooling_final_speed)) ((ConfigOptionFloats, filament_cooling_final_speed))
((ConfigOptionStrings, filament_ramming_parameters)) ((ConfigOptionStrings, filament_ramming_parameters))
((ConfigOptionBools, filament_multitool_ramming))
((ConfigOptionFloats, filament_multitool_ramming_volume))
((ConfigOptionFloats, filament_multitool_ramming_flow))
((ConfigOptionBool, gcode_comments)) ((ConfigOptionBool, gcode_comments))
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor)) ((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
((ConfigOptionBool, gcode_label_objects)) ((ConfigOptionBool, gcode_label_objects))

View File

@ -1903,6 +1903,13 @@ void TabFilament::add_filament_overrides_page()
"filament_retract_before_wipe" "filament_retract_before_wipe"
}) })
create_line_with_near_label_widget(optgroup, opt_key, extruder_idx); create_line_with_near_label_widget(optgroup, opt_key, extruder_idx);
optgroup = page->new_optgroup(L("Retraction when tool is disabled"));
for (const std::string opt_key : { "filament_retract_length_toolchange",
"filament_retract_restart_extra_toolchange"
})
create_line_with_near_label_widget(optgroup, opt_key, extruder_idx);
} }
void TabFilament::update_filament_overrides_page() void TabFilament::update_filament_overrides_page()
@ -1911,7 +1918,7 @@ void TabFilament::update_filament_overrides_page()
return; return;
Page* page = m_active_page; Page* page = m_active_page;
const auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Retraction"; }); auto og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Retraction"; });
if (og_it == page->m_optgroups.end()) if (og_it == page->m_optgroups.end())
return; return;
ConfigOptionsGroupShp optgroup = *og_it; ConfigOptionsGroupShp optgroup = *og_it;
@ -1939,6 +1946,16 @@ void TabFilament::update_filament_overrides_page()
bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length; bool is_checked = opt_key=="filament_retract_length" ? true : have_retract_length;
update_line_with_near_label_widget(optgroup, opt_key, extruder_idx, is_checked); update_line_with_near_label_widget(optgroup, opt_key, extruder_idx, is_checked);
} }
og_it = std::find_if(page->m_optgroups.begin(), page->m_optgroups.end(), [](const ConfigOptionsGroupShp og) { return og->title == "Retraction when tool is disabled"; });
if (og_it == page->m_optgroups.end())
return;
optgroup = *og_it;
for (const std::string& opt_key : {"filament_retract_length_toolchange", "filament_retract_restart_extra_toolchange"})
update_line_with_near_label_widget(optgroup, opt_key, extruder_idx);
} }
void TabFilament::create_extruder_combobox() void TabFilament::create_extruder_combobox()
@ -2128,6 +2145,12 @@ void TabFilament::build()
}); });
optgroup = page->new_optgroup(L("Toolchange parameters with multi extruder MM printers"));
optgroup->append_single_option_line("filament_multitool_ramming");
optgroup->append_single_option_line("filament_multitool_ramming_volume");
optgroup->append_single_option_line("filament_multitool_ramming_flow");
add_filament_overrides_page(); add_filament_overrides_page();
@ -2230,6 +2253,13 @@ void TabFilament::toggle_options()
} }
} }
if (m_active_page->title() == "Advanced")
{
bool multitool_ramming = m_config->opt_bool("filament_multitool_ramming", 0);
toggle_option("filament_multitool_ramming_volume", multitool_ramming);
toggle_option("filament_multitool_ramming_flow", multitool_ramming);
}
if (m_active_page->title() == "Filament Overrides") if (m_active_page->title() == "Filament Overrides")
update_filament_overrides_page(); update_filament_overrides_page();