diff --git a/resources/profiles/BBL/machine/fdm_machine_common.json b/resources/profiles/BBL/machine/fdm_machine_common.json index e0968ac56..6cec08b5a 100644 --- a/resources/profiles/BBL/machine/fdm_machine_common.json +++ b/resources/profiles/BBL/machine/fdm_machine_common.json @@ -20,6 +20,9 @@ "0x0" ], "gcode_flavor": "marlin", + "grab_length" : [ + "0" + ], "silent_mode": "0", "long_retractions_when_cut": [ "0" diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 0ecc94d8c..51032b052 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5396,6 +5396,8 @@ std::string GCode::set_extruder(unsigned int filament_id, double print_z, bool b old_retract_length_toolchange = m_config.retract_length_toolchange.get_at(previous_extruder_id); old_filament_temp = this->on_first_layer()? m_config.nozzle_temperature_initial_layer.get_at(previous_filament_id) : m_config.nozzle_temperature.get_at(previous_filament_id); + //During the filament change, the extruder will extrude an extra length of grab_length for the corresponding detection, so the purge can reduce this length. + float grab_purge_volume = m_config.grab_length.get_at(extruder_id) * 2.4; if (previous_extruder_id != extruder_id) { //calc flush volume between the same extruder id int previous_filament_id_in_new_extruder = m_writer.filament(extruder_id) != nullptr ? m_writer.filament(extruder_id)->id() : -1; @@ -5410,6 +5412,7 @@ std::string GCode::set_extruder(unsigned int filament_id, double print_z, bool b wipe_volume = flush_matrix[previous_filament_id * number_of_extruders + filament_id]; wipe_volume *= m_config.flush_multiplier.get_at(extruder_id); // if is multi_extruder only use the fist extruder matrix } + wipe_volume = std::max(0.f, wipe_volume-grab_purge_volume); old_filament_e_feedrate = (int) (60.0 * m_config.filament_max_volumetric_speed.get_at(previous_filament_id) / filament_area); old_filament_e_feedrate = old_filament_e_feedrate == 0 ? 100 : old_filament_e_feedrate; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index bd422f739..b07aec406 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -958,7 +958,8 @@ static std::vector s_Preset_printer_options { "print_host_webui", "printhost_cafile","printhost_port","printhost_authorization_type", "printhost_user", "printhost_password", "printhost_ssl_ignore_revoke", - "use_relative_e_distances", "extruder_type","use_firmware_retraction" + "use_relative_e_distances", "extruder_type","use_firmware_retraction", + "grab_length" }; static std::vector s_Preset_sla_print_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index eafdb50c5..a3182c04c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -186,7 +186,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "long_retractions_when_cut", "retraction_distances_when_cut", "filament_long_retractions_when_cut", - "filament_retraction_distances_when_cut" + "filament_retraction_distances_when_cut", + "grab_length" }; static std::unordered_set steps_ignore; @@ -2465,112 +2466,64 @@ void Print::_make_wipe_tower() { // Get wiping matrix to get number of extruders and convert vector to vector: bool is_mutli_extruder = m_config.nozzle_diameter.values.size() > 1; - size_t nozzle_nums = m_config.nozzle_diameter.values.size(); - if (is_mutli_extruder) { - using FlushMatrix = std::vector>; - std::vector multi_extruder_flush; - for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { - std::vector flush_matrix(cast(get_flush_volumes_matrix(m_config.flush_volumes_matrix.values, nozzle_id, nozzle_nums))); - std::vector> wipe_volumes; - for (unsigned int i = 0; i < number_of_extruders; ++i) - wipe_volumes.push_back(std::vector(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders)); - - multi_extruder_flush.emplace_back(wipe_volumes); - } - - std::vectorfilament_maps = get_filament_maps(); - - std::vector nozzle_cur_filament_ids(nozzle_nums, -1); - unsigned int current_filament_id = m_wipe_tower_data.tool_ordering.first_extruder(); - size_t cur_nozzle_id = filament_maps[current_filament_id] - 1; - nozzle_cur_filament_ids[cur_nozzle_id] = current_filament_id; - - for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers - if (!layer_tools.has_wipe_tower) continue; - bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); - wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_filament_id, current_filament_id); - - for (const auto filament_id : layer_tools.extruders) { - if (filament_id == current_filament_id) - continue; - - int nozzle_id = filament_maps[filament_id] - 1; - unsigned int pre_filament_id = nozzle_cur_filament_ids[nozzle_id]; - - float volume_to_purge = 0; - if (pre_filament_id != (unsigned int)(-1) && pre_filament_id != filament_id) { - volume_to_purge = multi_extruder_flush[nozzle_id][pre_filament_id][filament_id]; - volume_to_purge *= m_config.flush_multiplier.get_at(nozzle_id); - volume_to_purge = pre_filament_id == -1 ? 0 : - layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_filament_id, filament_id, volume_to_purge); - } - - wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_filament_id, filament_id, - m_config.prime_volume, volume_to_purge); - current_filament_id = filament_id; - nozzle_cur_filament_ids[nozzle_id] = filament_id; - } - layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this); - - // if enable timelapse, slice all layer - if (enable_timelapse_print()) { - if (layer_tools.wipe_tower_partitions == 0) wipe_tower.set_last_layer_extruder_fill(false); - continue; - } - - if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0) - break; - } - } - else { - std::vector flush_matrix(cast(get_flush_volumes_matrix(m_config.flush_volumes_matrix.values, 0, nozzle_nums))); - - // Extract purging volumes for each extruder pair: + size_t nozzle_nums = m_config.nozzle_diameter.values.size(); + using FlushMatrix = std::vector>; + std::vector multi_extruder_flush; + for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { + std::vector flush_matrix(cast(get_flush_volumes_matrix(m_config.flush_volumes_matrix.values, nozzle_id, nozzle_nums))); std::vector> wipe_volumes; for (unsigned int i = 0; i < number_of_extruders; ++i) wipe_volumes.push_back(std::vector(flush_matrix.begin() + i * number_of_extruders, flush_matrix.begin() + (i + 1) * number_of_extruders)); + multi_extruder_flush.emplace_back(wipe_volumes); + } - // BBS: priming logic is removed, so get the initial extruder by first_extruder() - unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.first_extruder(); - for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers - if (!layer_tools.has_wipe_tower) continue; - bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); - wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id); + std::vectorfilament_maps = get_filament_maps(); - for (const auto extruder_id : layer_tools.extruders) { - // BBS: priming logic is removed, so no need to do toolchange for first extruder - if (/*(first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || */extruder_id != current_extruder_id) { - float volume_to_purge = wipe_volumes[current_extruder_id][extruder_id]; - volume_to_purge *= m_config.flush_multiplier.get_at(0); + std::vector nozzle_cur_filament_ids(nozzle_nums, -1); + unsigned int current_filament_id = m_wipe_tower_data.tool_ordering.first_extruder(); + size_t cur_nozzle_id = filament_maps[current_filament_id] - 1; + nozzle_cur_filament_ids[cur_nozzle_id] = current_filament_id; - // Not all of that can be used for infill purging: - //volume_to_purge -= (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); + for (auto& layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers + if (!layer_tools.has_wipe_tower) continue; + bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front(); + wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_filament_id, current_filament_id); - // try to assign some infills/objects for the wiping: - volume_to_purge = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, volume_to_purge); - - // add back the minimal amount toforce on the wipe tower: - //volume_to_purge += (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id); - - // request a toolchange at the wipe tower with at least volume_to_wipe purging amount - wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, - current_extruder_id, extruder_id, m_config.prime_volume, volume_to_purge); - current_extruder_id = extruder_id; - } - } - layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this); - - // if enable timelapse, slice all layer - if (enable_timelapse_print()) { - if (layer_tools.wipe_tower_partitions == 0) - wipe_tower.set_last_layer_extruder_fill(false); + for (const auto filament_id : layer_tools.extruders) { + if (filament_id == current_filament_id) continue; + + int nozzle_id = filament_maps[filament_id] - 1; + unsigned int pre_filament_id = nozzle_cur_filament_ids[nozzle_id]; + + float volume_to_purge = 0; + if (pre_filament_id != (unsigned int)(-1) && pre_filament_id != filament_id) { + volume_to_purge = multi_extruder_flush[nozzle_id][pre_filament_id][filament_id]; + volume_to_purge *= m_config.flush_multiplier.get_at(nozzle_id); + volume_to_purge = pre_filament_id == -1 ? 0 : + layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_filament_id, filament_id, volume_to_purge); } - if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0) - break; + //During the filament change, the extruder will extrude an extra length of grab_length for the corresponding detection, so the purge can reduce this length. + float grab_purge_volume = m_config.grab_length.get_at(nozzle_id) * 2.4; //(diameter/2)^2*PI=2.4 + volume_to_purge = std::max(0.f, volume_to_purge - grab_purge_volume); + + wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_filament_id, filament_id, + m_config.prime_volume, volume_to_purge); + current_filament_id = filament_id; + nozzle_cur_filament_ids[nozzle_id] = filament_id; } + layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this); + + // if enable timelapse, slice all layer + if (enable_timelapse_print()) { + if (layer_tools.wipe_tower_partitions == 0) wipe_tower.set_last_layer_extruder_fill(false); + continue; + } + + if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0) + break; } } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 79364095a..1180106b0 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1464,6 +1464,13 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(68)); + def = this->add("grab_length",coFloats); + def->label = L("Grab length"); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comDevelop; + def->set_default_value(new ConfigOptionFloats({0})); + def = this->add("extruder_colour", coStrings); def->label = L("Extruder Color"); def->tooltip = L("Only used as a visual help on UI"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 76c112b38..367c8cd35 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1174,6 +1174,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionBool, independent_support_layer_height)) ((ConfigOptionBool, exclude_object)) ((ConfigOptionPercents, filament_shrink)) + ((ConfigOptionFloats, grab_length)) ) // This object is mapped to Perl as Slic3r::Config::Full.