diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 1f306c83c6..444fe95e25 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -239,9 +239,12 @@ namespace Slic3r { const bool needs_toolchange = gcodegen.writer().need_toolchange(new_extruder_id); const bool will_go_down = ! is_approx(z, current_z); - if (tcr.force_travel || ! needs_toolchange || (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 - // toolchange will travel there anyway (if there is a toolchange). + const bool is_ramming = (gcodegen.config().single_extruder_multi_material && ! tcr.priming) + || (! gcodegen.config().single_extruder_multi_material && gcodegen.config().filament_multitool_ramming.get_at(tcr.initial_tool)); + 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, // then we could simplify the condition and make it more readable. gcode += gcodegen.retract(); @@ -251,6 +254,9 @@ namespace Slic3r { ExtrusionRole::Mixed, "Travel to a Wipe Tower"); 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) { @@ -262,7 +268,7 @@ namespace Slic3r { std::string toolchange_gcode_str; std::string deretraction_str; 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. toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z); // TODO: toolchange_z vs print_z if (gcodegen.config().wipe_tower) diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 6d04d88c48..00ac858173 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -518,7 +518,6 @@ WipeTower::ToolChangeResult WipeTower::construct_tcr(WipeTowerWriter& writer, WipeTower::WipeTower(const PrintConfig& config, const PrintRegionConfig& default_region_config, const std::vector>& wiping_matrix, size_t initial_tool) : m_semm(config.single_extruder_multi_material.value), - m_ramming(true), // TESTING ONLY m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y), m_wipe_tower_width(float(config.wipe_tower_width)), m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)), @@ -558,9 +557,8 @@ WipeTower::WipeTower(const PrintConfig& config, const PrintRegionConfig& default m_cooling_tube_length = float(config.cooling_tube_length); m_parking_pos_retraction = float(config.parking_pos_retraction); m_extra_loading_move = float(config.extra_loading_move); - } - if (m_ramming) m_set_extruder_trimpot = config.high_current_on_filament_swap; + } // Calculate where the priming lines should be - very naive test not detecting parallelograms etc. const std::vector& bed_points = config.bed_shape.values; @@ -620,7 +618,7 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config) m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio; // all extruders are now assumed to have the same diameter - if (m_ramming) { + if (m_semm) { std::istringstream stream{config.filament_ramming_parameters.get_at(idx)}; float speed = 0.f; stream >> m_filpar[idx].ramming_line_width_multiplicator >> m_filpar[idx].ramming_step_multiplicator; @@ -628,6 +626,14 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config) m_filpar[idx].ramming_step_multiplicator /= 100; while (stream >> speed) m_filpar[idx].ramming_speed.push_back(speed); + } 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.; + m_filpar[idx].ramming_speed.resize(4 *size_t(vol/flow + 0.5f), 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 @@ -842,12 +848,17 @@ void WipeTower::toolchange_Unload( float remaining = xr - xl ; // keeps track of distance to the next turnaround float e_done = 0; // measures E move done from each segment - if (m_ramming) + 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.disable_linear_advance(); + } else 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 (m_ramming && (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 float sparse_beginning_y = 0.f; @@ -875,11 +886,10 @@ void WipeTower::toolchange_Unload( sum_of_depths += tch.required_depth; } } - - writer.disable_linear_advance(); + // now the ramming itself: - while (m_ramming && 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); const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move; @@ -956,7 +966,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: // 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); - if (m_ramming) + if (do_ramming) writer.travel(pos, 2400.f); else writer.set_position(pos); diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index 66a5b348eb..666a3e0075 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -241,6 +241,7 @@ public: std::vector ramming_speed; float nozzle_diameter; float filament_area; + bool multitool_ramming; }; private: @@ -258,7 +259,6 @@ private: bool m_semm = true; // Are we using a single extruder multimaterial printer? - bool m_ramming = true; // Do we want to perform ramming? Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm. float m_wipe_tower_width; // Width of the wipe tower. float m_wipe_tower_depth = 0.f; // Depth of the wipe tower diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 376529a14e..d6ecb782e1 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -468,6 +468,7 @@ static std::vector s_Preset_filament_options { "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_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", "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", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 94b08b8857..9ed95dddf3 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -194,6 +194,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n || opt_key == "filament_cooling_initial_speed" || opt_key == "filament_cooling_final_speed" || 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 == "gcode_flavor" || opt_key == "high_current_on_filament_swap" diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 83dd450c23..fdc3fb70ea 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1103,6 +1103,28 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; 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)."); + 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(""); + def->sidetext = L("mm³"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats { 0. }); + + def = this->add("filament_multitool_ramming_flow", coFloats); + def->label = L("Multitool ramming flow"); + def->tooltip = L(""); + def->sidetext = L("mm³/s"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloats { 0. }); + def = this->add("filament_diameter", coFloats); def->label = L("Diameter"); def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6439d21e9d..e79e520648 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -689,6 +689,9 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, filament_minimal_purge_on_wipe_tower)) ((ConfigOptionFloats, filament_cooling_final_speed)) ((ConfigOptionStrings, filament_ramming_parameters)) + ((ConfigOptionBools, filament_multitool_ramming)) + ((ConfigOptionFloats, filament_multitool_ramming_volume)) + ((ConfigOptionFloats, filament_multitool_ramming_flow)) ((ConfigOptionBool, gcode_comments)) ((ConfigOptionEnum, gcode_flavor)) ((ConfigOptionBool, gcode_label_objects)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index f3dc02e46f..dc922f971b 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2145,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(); @@ -2247,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") update_filament_overrides_page();