From 67b62c28d39395b431a50fc92379d6d6ea02e3b4 Mon Sep 17 00:00:00 2001 From: supermerill Date: Tue, 14 Nov 2023 23:58:33 +0100 Subject: [PATCH] Rework of fan speed control by extrusion type . now easier to add new control and do complicate stuff in the cooling buffer. . less overall number of lines of code for better results. . add 6 new fan control. . now if the disable_fan_first_layers is at 0 and full_fan_speed_layer at more than 1, the first layer has some fan speed. . updated fan speeds that cannot be increased even with low layer time (top solid, ironing, support, support interface) . updated fan speeds that cannot be reduced by full_fan_speed_layer (bridge, infill bridge, overhangs, support interface) . updated extrusion speed that can't be reduced (overhang, bridge) . updated extrusion speed that shouldn't be reduced if possible (external, ironing, infill bridge, thin wall, support interface) . better name for CoolingBuffer::process_layer variables supermerill/SuperSlicer#3735 supermerill/SuperSlicer#3608 supermerill/SuperSlicer#3568 supermerill/SuperSlicer#3415 supermerill/SuperSlicer#3408 supermerill/SuperSlicer#3380 supermerill/SuperSlicer#3367 supermerill/SuperSlicer#3361 supermerill/SuperSlicer#3271 supermerill/SuperSlicer#3152 supermerill/SuperSlicer#2872 supermerill/SuperSlicer#2696 supermerill/SuperSlicer#2419 supermerill/SuperSlicer#2326 --- resources/ui_layout/default/filament.ui | 30 +- resources/ui_layout/example/filament.ui | 30 +- src/libslic3r/ExtrusionEntity.hpp | 2 +- src/libslic3r/GCode.cpp | 63 ++-- src/libslic3r/GCode.hpp | 9 +- src/libslic3r/GCode/CoolingBuffer.cpp | 436 +++++++++++------------- src/libslic3r/GCode/FanMover.cpp | 4 +- src/libslic3r/GCode/WipeTower.cpp | 3 +- src/libslic3r/Preset.cpp | 14 +- src/libslic3r/Print.cpp | 6 + src/libslic3r/PrintConfig.cpp | 118 ++++++- src/libslic3r/PrintConfig.hpp | 6 + 12 files changed, 427 insertions(+), 294 deletions(-) diff --git a/resources/ui_layout/default/filament.ui b/resources/ui_layout/default/filament.ui index 76a269f9fa4..60f105f24c6 100644 --- a/resources/ui_layout/default/filament.ui +++ b/resources/ui_layout/default/filament.ui @@ -20,7 +20,7 @@ group:Temperature °C group:Filament properties setting:width$7:filament_type setting:filament_soluble - setting:filament_shrink + setting:filament_shrink setting:filament_max_overlap group:Print speed override setting:filament_max_speed @@ -30,18 +30,30 @@ group:Print speed override page:Cooling:time group:Fan speed - default setting:label$Run the fan at default speed when possible:fan_always_on + line:Disable fan for the first + setting:width$5:label$_:sidetext_width$7:disable_fan_first_layers + setting:width$5:label_width$12:full_fan_speed_layer + end_line setting:min_fan_speed + line:Perimeter fan speed + setting:label$:perimeter_fan_speed + setting:label_width$12:label$External:external_perimeter_fan_speed + end_line + setting:overhang_perimeter_fan_speed + setting:infill_fan_speed + line:Solid Infill fan speed + setting:label$:solid_infill_fan_speed + setting:label_width$12:label$Top:top_fan_speed + end_line + line:Support Material fan speed + setting:label$:support_material_fan_speed + setting:label_width$12:label$Support Interface:support_material_interface_fan_speed + end_line line:Bridges fan speed setting:label$:bridge_fan_speed - setting:label$Infill bridges:bridge_internal_fan_speed - end_line - setting:top_fan_speed - setting:external_perimeter_fan_speed - setting:support_material_interface_fan_speed - line:Disable fan for the first - setting:label$_:sidetext_width$12:disable_fan_first_layers - setting:full_fan_speed_layer + setting:label_width$12:label$Infill bridges:bridge_internal_fan_speed end_line + setting:gap_fill_fan_speed group:Short layer time - began to increase base fan speed setting:fan_below_layer_time setting:label$Max fan speed:max_fan_speed diff --git a/resources/ui_layout/example/filament.ui b/resources/ui_layout/example/filament.ui index 76a269f9fa4..60f105f24c6 100644 --- a/resources/ui_layout/example/filament.ui +++ b/resources/ui_layout/example/filament.ui @@ -20,7 +20,7 @@ group:Temperature °C group:Filament properties setting:width$7:filament_type setting:filament_soluble - setting:filament_shrink + setting:filament_shrink setting:filament_max_overlap group:Print speed override setting:filament_max_speed @@ -30,18 +30,30 @@ group:Print speed override page:Cooling:time group:Fan speed - default setting:label$Run the fan at default speed when possible:fan_always_on + line:Disable fan for the first + setting:width$5:label$_:sidetext_width$7:disable_fan_first_layers + setting:width$5:label_width$12:full_fan_speed_layer + end_line setting:min_fan_speed + line:Perimeter fan speed + setting:label$:perimeter_fan_speed + setting:label_width$12:label$External:external_perimeter_fan_speed + end_line + setting:overhang_perimeter_fan_speed + setting:infill_fan_speed + line:Solid Infill fan speed + setting:label$:solid_infill_fan_speed + setting:label_width$12:label$Top:top_fan_speed + end_line + line:Support Material fan speed + setting:label$:support_material_fan_speed + setting:label_width$12:label$Support Interface:support_material_interface_fan_speed + end_line line:Bridges fan speed setting:label$:bridge_fan_speed - setting:label$Infill bridges:bridge_internal_fan_speed - end_line - setting:top_fan_speed - setting:external_perimeter_fan_speed - setting:support_material_interface_fan_speed - line:Disable fan for the first - setting:label$_:sidetext_width$12:disable_fan_first_layers - setting:full_fan_speed_layer + setting:label_width$12:label$Infill bridges:bridge_internal_fan_speed end_line + setting:gap_fill_fan_speed group:Short layer time - began to increase base fan speed setting:fan_below_layer_time setting:label$Max fan speed:max_fan_speed diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 4f1116d4a71..73fca1ba17d 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -52,7 +52,7 @@ enum ExtrusionRole : uint16_t { }; */ enum ExtrusionRole : uint8_t { - erNone, + erNone, // erNone needs to be 0 (for cooling and everything that use the role as index) erPerimeter, erExternalPerimeter, erOverhangPerimeter, diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 529d2c642cf..fc917dcea0b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -5386,8 +5386,38 @@ double_t GCode::_compute_speed_mm_per_sec(const ExtrusionPath& path, double spee return speed; } + +void GCode::cooldown_marker_init() { + if (!_cooldown_marker_speed[ExtrusionRole::erExternalPerimeter].empty()) { + std::string allow_speed_change = ";CM_extrude_speed;_EXTRUDE_SET_SPEED"; + //only change speed on external perimeter (and similar) speed if really necessary. + std::string maybe_allow_speed_change = ";CM_extrude_speed_external;_EXTRUDE_SET_SPEED_MAYBE"; + _cooldown_marker_speed[erNone] = ""; + _cooldown_marker_speed[erPerimeter] = allow_speed_change; + _cooldown_marker_speed[erExternalPerimeter] = maybe_allow_speed_change; + _cooldown_marker_speed[erOverhangPerimeter] = ""; + _cooldown_marker_speed[erInternalInfill] = allow_speed_change; + _cooldown_marker_speed[erSolidInfill] = allow_speed_change; + _cooldown_marker_speed[erTopSolidInfill] = allow_speed_change; + _cooldown_marker_speed[erIroning] = maybe_allow_speed_change; + _cooldown_marker_speed[erBridgeInfill] = ""; + _cooldown_marker_speed[erInternalBridgeInfill] = maybe_allow_speed_change; + _cooldown_marker_speed[erThinWall] = maybe_allow_speed_change; + _cooldown_marker_speed[erGapFill] = allow_speed_change; + _cooldown_marker_speed[erSkirt] = allow_speed_change; + _cooldown_marker_speed[erSupportMaterial] = allow_speed_change; + _cooldown_marker_speed[erSupportMaterialInterface] = maybe_allow_speed_change; + _cooldown_marker_speed[erWipeTower] = allow_speed_change; + _cooldown_marker_speed[erMilling] = ""; + _cooldown_marker_speed[erCustom] = maybe_allow_speed_change; + _cooldown_marker_speed[erMixed] = maybe_allow_speed_change; + } +} + + std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string &description_in, double speed) { std::string gcode; + gcode.reserve(512); std::string description{ description_in }; @@ -5730,20 +5760,10 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string std::string comment; if (m_enable_cooling_markers) { - if(path.role() == erInternalBridgeInfill) - gcode += ";_BRIDGE_INTERNAL_FAN_START\n"; - else if (is_bridge(path.role())) - gcode += ";_BRIDGE_FAN_START\n"; - else if (ExtrusionRole::erTopSolidInfill == path.role()) - gcode += ";_TOP_FAN_START\n"; - else if (ExtrusionRole::erSupportMaterialInterface == path.role()) - gcode += ";_SUPP_INTER_FAN_START\n"; - else - comment = ";_EXTRUDE_SET_SPEED"; - if (path.role() == erExternalPerimeter) - comment += ";_EXTERNAL_PERIMETER"; - if (path.role() == erThinWall) - comment += ";_EXTERNAL_PERIMETER"; + // Send the current extrusion type to Coolingbuffer + gcode += ";_EXTRUDETYPE_"; gcode += char('A' + path.role()); gcode += "\n"; + // comment to be on the same line as the speed command. + comment = GCode::_cooldown_marker_speed[path.role()]; } // F is mm per minute. // speed is mm per second @@ -5753,17 +5773,10 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string } std::string GCode::_after_extrude(const ExtrusionPath &path) { std::string gcode; - if (m_enable_cooling_markers) - if (path.role() == erInternalBridgeInfill) - gcode += ";_BRIDGE_INTERNAL_FAN_END\n"; - else if (is_bridge(path.role())) - gcode += ";_BRIDGE_FAN_END\n"; - else if (ExtrusionRole::erTopSolidInfill == path.role()) - gcode += ";_TOP_FAN_END\n"; - else if (ExtrusionRole::erSupportMaterialInterface == path.role()) - gcode += ";_SUPP_INTER_FAN_END\n"; - else - gcode += ";_EXTRUDE_END\n"; + if (m_enable_cooling_markers) { + // Notify Coolingbuffer that the current extrusion end. + gcode += ";_EXTRUDE_END\n"; + } if (path.role() != ExtrusionRole::erGapFill ) { m_last_notgapfill_extrusion_role = path.role(); diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index b7848ab3e1c..f3f9d1f5392 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -155,7 +155,9 @@ class GCode : ExtrusionVisitorConst { m_silent_time_estimator_enabled(false), m_last_obj_copy(nullptr, Point(std::numeric_limits::max(), std::numeric_limits::max())), m_last_too_small(ExtrusionRole::erNone) - {} + { + cooldown_marker_init(); + } ~GCode() = default; // throws std::runtime_exception on error, @@ -527,6 +529,11 @@ class GCode : ExtrusionVisitorConst { friend class Wipe; friend class WipeTowerIntegration; friend class PressureEqualizer; + + //utility for cooling markers + static inline std::string _cooldown_marker_speed[ExtrusionRole::erCount]; + bool cooldwon_marker_no_slowdown_section = false;; + static void cooldown_marker_init(); }; std::vector sort_object_instances_by_model_order(const Print& print); diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 5cead49efb1..274325a70b0 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -45,20 +45,17 @@ void CoolingBuffer::reset(const Vec3d &position) struct CoolingLine { enum Type : uint32_t { - TYPE_SET_TOOL = 1 << 0, - TYPE_EXTRUDE_END = 1 << 1, - TYPE_BRIDGE_FAN_START = 1 << 2, - TYPE_BRIDGE_FAN_END = 1 << 3, - TYPE_BRIDGE_INTERNAL_FAN_START = 1 << 4, - TYPE_BRIDGE_INTERNAL_FAN_END = 1 << 5, - TYPE_TOP_FAN_START = 1 << 6, - TYPE_TOP_FAN_END = 1 << 7, - TYPE_SUPP_INTER_FAN_START = 1 << 8, - TYPE_SUPP_INTER_FAN_END = 1 << 9, + //first 5 bits are for the extrusiontype (not a flag) + + TYPE_SET_TOOL = 1 << 7, + TYPE_EXTRUDE_START = 1 << 8, + TYPE_EXTRUDE_END = 1 << 9, TYPE_G0 = 1 << 10, TYPE_G1 = 1 << 11, + // if adjustable, that means that the lines after that can't have their speed modified. end after a TYPE_EXTRUDE_END TYPE_ADJUSTABLE = 1 << 12, - TYPE_EXTERNAL_PERIMETER = 1 << 13, + // TYPE_ADJUSTABLE_MAYBE = do not adjust this section if possible + TYPE_ADJUSTABLE_MAYBE = 1 << 13, // The line sets a feedrate. TYPE_HAS_F = 1 << 14, TYPE_WIPE = 1 << 15, @@ -71,8 +68,11 @@ struct CoolingLine TYPE_G3 = 1 << 21, // Would be TYPE_ADJUSTABLE, but the block of G-code lines has zero extrusion length, thus the block // cannot have its speed adjusted. This should not happen (sic!). - TYPE_ADJUSTABLE_EMPTY = 1 << 12, + TYPE_ADJUSTABLE_EMPTY = 1 << 22, }; + static inline ExtrusionRole to_extrusion_role(uint32_t type) { + return ExtrusionRole(uint8_t(type & 0x1F)); + } CoolingLine(unsigned int type, size_t line_start, size_t line_end) : type(type), line_start(line_start), line_end(line_end), @@ -80,7 +80,7 @@ struct CoolingLine bool adjustable(bool slowdown_external_perimeters) const { return (this->type & TYPE_ADJUSTABLE) && - (! (this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) && + (slowdown_external_perimeters || (!(this->type & TYPE_ADJUSTABLE_MAYBE))) && this->time < this->time_max; } @@ -330,44 +330,45 @@ std::string CoolingBuffer::process_layer(std::string &&gcode_in, size_t layer_id std::string out; if (flush) { - auto& previous_layer_time = is_support_only ? saved_layer_time_object : saved_layer_time_support; - auto my_previous_layer_time = is_support_only ? saved_layer_time_support : saved_layer_time_object; - auto& my_layer_time = is_support_only ? saved_layer_time_support : saved_layer_time_object; - std::vector per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos); - //save our layer time in case of unchync - my_layer_time.clear(); - for (PerExtruderAdjustments& adj : per_extruder_adjustments) { - my_layer_time[adj.extruder_id] = adj.elapsed_time_total(); - auto it = my_previous_layer_time.find(adj.extruder_id); - if (it != my_previous_layer_time.end()) { - my_previous_layer_time[adj.extruder_id] = (my_previous_layer_time[adj.extruder_id] + my_layer_time[adj.extruder_id]) / 2 - my_layer_time[adj.extruder_id]; - } else { - my_previous_layer_time[adj.extruder_id] = 0; - } - } - //add unsynch layer time - if (!previous_layer_time.empty()) { - for (PerExtruderAdjustments& adj : per_extruder_adjustments) { - auto it = previous_layer_time.find(adj.extruder_id); - if (it != previous_layer_time.end()) { - adj.time_support = it->second; - } - } - previous_layer_time.clear(); - } - //add half diff with previous one, to avoid suddent change in fan speed. - if (!my_previous_layer_time.empty()) { - for (PerExtruderAdjustments& adj : per_extruder_adjustments) { - auto it = my_previous_layer_time.find(adj.extruder_id); - if (it != my_previous_layer_time.end()) { - adj.time_support += it->second; - } - } - } - //compute slowdown - float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments); - //compute fans & gcode - out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments); + std::map& last_different_layer_time = is_support_only ? saved_layer_time_object : saved_layer_time_support; + // previous_layer_time is also use at temporary store for the diff between our layer_time and its. + std::map previous_layer_time = is_support_only ? saved_layer_time_support : saved_layer_time_object; + std::map& my_layer_time = previous_layer_time; + std::vector per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos); + //save our layer time in case of unchync + my_layer_time.clear(); + for (PerExtruderAdjustments& adj : per_extruder_adjustments) { + my_layer_time[adj.extruder_id] = adj.elapsed_time_total(); + auto it = previous_layer_time.find(adj.extruder_id); + if (it != previous_layer_time.end()) { + previous_layer_time[adj.extruder_id] = (previous_layer_time[adj.extruder_id] + my_layer_time[adj.extruder_id]) / 2 - my_layer_time[adj.extruder_id]; + } else { + previous_layer_time[adj.extruder_id] = 0; + } + } + //add unsynch layer time (support for object, and object for support) + if (!last_different_layer_time.empty()) { + for (PerExtruderAdjustments& adj : per_extruder_adjustments) { + auto it = last_different_layer_time.find(adj.extruder_id); + if (it != last_different_layer_time.end()) { + adj.time_support += it->second; + } + } + last_different_layer_time.clear(); + } + //add half diff with previous one, to avoid flip-flop quick change in fan speed. + if (!previous_layer_time.empty()) { + for (PerExtruderAdjustments& adj : per_extruder_adjustments) { + auto it = previous_layer_time.find(adj.extruder_id); + if (it != previous_layer_time.end()) { + adj.time_support += it->second; + } + } + } + //compute slowdown + float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments); + //compute fans & gcode + out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments); m_gcode.clear(); } return out; @@ -440,9 +441,10 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: if (axis == 4) { // Convert mm/min to mm/sec. new_pos[4] /= 60.f; - if ((line.type & CoolingLine::TYPE_G92) == 0) + if ((line.type & CoolingLine::TYPE_G92) == 0) { // This is G0 or G1 line and it sets the feedrate. This mark is used for reducing the duplicate F calls. line.type |= CoolingLine::TYPE_HAS_F; + } } else if (axis == 5 || axis == 6) { // BBS: get position of arc center new_pos[axis] += current_pos[axis - 5]; @@ -451,15 +453,15 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: // Skip this word. for (; *c != ' ' && *c != '\t' && *c != 0; ++ c); } - bool external_perimeter = boost::contains(sline, ";_EXTERNAL_PERIMETER"); bool wipe = boost::contains(sline, ";_WIPE"); - if (external_perimeter) - line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER; if (wipe) line.type |= CoolingLine::TYPE_WIPE; if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe) { line.type |= CoolingLine::TYPE_ADJUSTABLE; active_speed_modifier = adjustment->lines.size(); + std::cout << "TYPE_(not)_ADJUSTABLE!\n"; + if (boost::contains(sline, ";_EXTRUDE_SET_SPEED_MAYBE")) + line.type |= CoolingLine::TYPE_ADJUSTABLE_MAYBE; } if ((line.type & CoolingLine::TYPE_G92) == 0) { // G0 or G1. Calculate the duration. @@ -561,22 +563,9 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: BOOST_LOG_TRIVIAL(error) << "CoolingBuffer encountered an invalid toolchange, maybe from a custom gcode: " << sline; } - } else if (boost::starts_with(sline, ";_BRIDGE_FAN_START")) { - line.type = CoolingLine::TYPE_BRIDGE_FAN_START; - } else if (boost::starts_with(sline, ";_BRIDGE_FAN_END")) { - line.type = CoolingLine::TYPE_BRIDGE_FAN_END; - } else if (boost::starts_with(sline, ";_BRIDGE_INTERNAL_FAN_START")) { - line.type = CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START; - } else if (boost::starts_with(sline, ";_BRIDGE_INTERNAL_FAN_END")) { - line.type = CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_END; - } else if (boost::starts_with(sline, ";_TOP_FAN_START")) { - line.type = CoolingLine::TYPE_TOP_FAN_START; - } else if (boost::starts_with(sline, ";_TOP_FAN_END")) { - line.type = CoolingLine::TYPE_TOP_FAN_END; - } else if (boost::starts_with(sline, ";_SUPP_INTER_FAN_START")) { - line.type = CoolingLine::TYPE_SUPP_INTER_FAN_START; - } else if (boost::starts_with(sline, ";_SUPP_INTER_FAN_END")) { - line.type = CoolingLine::TYPE_SUPP_INTER_FAN_END; + } else if (boost::starts_with(sline, ";_EXTRUDETYPE_") && sline.size() > 14) { + //set the extrusiontype + line.type |= CoolingLine::Type(sline[14] - 'A') | CoolingLine::Type::TYPE_EXTRUDE_START; } else if (boost::starts_with(sline, "G4 ")) { // Parse the wait time. line.type = CoolingLine::TYPE_G4; @@ -797,6 +786,40 @@ float CoolingBuffer::calculate_layer_slowdown(std::vector etype_can_increase_fan = { + ExtrusionRole::erNone, + ExtrusionRole::erBridgeInfill, + ExtrusionRole::erInternalBridgeInfill, + //ExtrusionRole::erTopSolidInfill, + //ExtrusionRole::erIroning, + //ExtrusionRole::erSupportMaterialInterface, + //ExtrusionRole::erSupportMaterial, + ExtrusionRole::erExternalPerimeter, + ExtrusionRole::erThinWall, + ExtrusionRole::erPerimeter, + ExtrusionRole::erSolidInfill, + ExtrusionRole::erInternalInfill, + ExtrusionRole::erOverhangPerimeter, + ExtrusionRole::erGapFill }; +// list of fan that won't be reduced in the first layers by full_fan_speed_layer (after disable_fan_first_layers) +std::vector etype_can_ramp_up_fan = { + ExtrusionRole::erNone, + //ExtrusionRole::erBridgeInfill, + //ExtrusionRole::erInternalBridgeInfill, + ExtrusionRole::erTopSolidInfill, + ExtrusionRole::erIroning, + //ExtrusionRole::erSupportMaterialInterface, + ExtrusionRole::erSupportMaterial, + ExtrusionRole::erExternalPerimeter, + ExtrusionRole::erThinWall, + ExtrusionRole::erPerimeter, + ExtrusionRole::erSolidInfill, + ExtrusionRole::erInternalInfill, + //ExtrusionRole::erOverhangPerimeter, + ExtrusionRole::erGapFill }; + // Apply slow down over G-code lines stored in per_extruder_adjustments, enable fan if needed. // Returns the adjusted G-code. std::string CoolingBuffer::apply_layer_cooldown( @@ -824,75 +847,65 @@ std::string CoolingBuffer::apply_layer_cooldown( // Second generate the adjusted G-code. std::string new_gcode; new_gcode.reserve(gcode.size() * 2); - bool bridge_fan_control = false; - int bridge_fan_speed = 0; - bool bridge_internal_fan_control = false; - int bridge_internal_fan_speed = 0; - bool top_fan_control = false; - int top_fan_speed = 0; - bool supp_inter_fan_control = false; - int supp_inter_fan_speed = 0; - bool ext_peri_fan_control = false; - int ext_peri_fan_speed = 0; + bool fan_control[ExtrusionRole::erCount]; + int fan_speeds[ExtrusionRole::erCount]; + int default_fan_speed[ExtrusionRole::erCount]; #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder) + int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); + for (int i = 0; i < ExtrusionRole::erCount; i++) { + fan_control[i] = false; + fan_speeds[i] = 0; + default_fan_speed[i] = min_fan_speed; + // 0 was deprecated, replaced by 1: allow 1 to still be 0 (and it's now deprecated) + if (default_fan_speed[i] == 1) default_fan_speed[i] = 0; + } + default_fan_speed[ExtrusionRole::erBridgeInfill] = EXTRUDER_CONFIG(bridge_fan_speed); + default_fan_speed[ExtrusionRole::erInternalBridgeInfill] = EXTRUDER_CONFIG(bridge_internal_fan_speed); + default_fan_speed[ExtrusionRole::erTopSolidInfill] = EXTRUDER_CONFIG(top_fan_speed); + default_fan_speed[ExtrusionRole::erIroning] = default_fan_speed[ExtrusionRole::erTopSolidInfill]; + default_fan_speed[ExtrusionRole::erSupportMaterialInterface] = EXTRUDER_CONFIG(support_material_interface_fan_speed); + default_fan_speed[ExtrusionRole::erSupportMaterial] = EXTRUDER_CONFIG(support_material_fan_speed); + default_fan_speed[ExtrusionRole::erExternalPerimeter] = EXTRUDER_CONFIG(external_perimeter_fan_speed); + default_fan_speed[ExtrusionRole::erThinWall] = default_fan_speed[ExtrusionRole::erExternalPerimeter]; + default_fan_speed[ExtrusionRole::erPerimeter] = EXTRUDER_CONFIG(perimeter_fan_speed); + default_fan_speed[ExtrusionRole::erSolidInfill] = EXTRUDER_CONFIG(solid_infill_fan_speed); + default_fan_speed[ExtrusionRole::erInternalInfill] = EXTRUDER_CONFIG(infill_fan_speed); + default_fan_speed[ExtrusionRole::erOverhangPerimeter] = EXTRUDER_CONFIG(overhangs_fan_speed); + default_fan_speed[ExtrusionRole::erGapFill] = EXTRUDER_CONFIG(gap_fill_fan_speed); auto change_extruder_set_fan = [this, layer_id, layer_time, &new_gcode, - &bridge_fan_control, &bridge_fan_speed, &bridge_internal_fan_control, &bridge_internal_fan_speed, - &top_fan_control, &top_fan_speed, - &ext_peri_fan_control, &ext_peri_fan_speed, - &supp_inter_fan_control, &supp_inter_fan_speed]() { - int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); - bridge_fan_speed = EXTRUDER_CONFIG(bridge_fan_speed); - bridge_internal_fan_speed = EXTRUDER_CONFIG(bridge_internal_fan_speed); - top_fan_speed = EXTRUDER_CONFIG(top_fan_speed); - supp_inter_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed); - ext_peri_fan_speed = EXTRUDER_CONFIG(external_perimeter_fan_speed); - // 0 is deprecated for disable: take care of temp settings. - if (bridge_fan_speed == 0) bridge_fan_speed = -1; - if (bridge_internal_fan_speed == 0) bridge_internal_fan_speed = -1; - if (ext_peri_fan_speed == 0) ext_peri_fan_speed = -1; - if (top_fan_speed == 0) top_fan_speed = -1; - if (bridge_fan_speed == 1) bridge_fan_speed = 0; - if (bridge_internal_fan_speed == 1) bridge_internal_fan_speed = 0; - if (ext_peri_fan_speed == 1) ext_peri_fan_speed = 0; - if (top_fan_speed == 1) top_fan_speed = 0; - // end deprecation - int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0; + &fan_control, &fan_speeds, &default_fan_speed, &min_fan_speed]() + { int disable_fan_first_layers = EXTRUDER_CONFIG(disable_fan_first_layers); // Is the fan speed ramp enabled? int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer); - if (disable_fan_first_layers <= 0 && full_fan_speed_layer > 0) { - // When ramping up fan speed from disable_fan_first_layers to full_fan_speed_layer, force disable_fan_first_layers above zero, - // so there will be a zero fan speed at least at the 1st layer. - disable_fan_first_layers = 1; - } if (int(layer_id) >= disable_fan_first_layers) { int max_fan_speed = EXTRUDER_CONFIG(max_fan_speed); float slowdown_below_layer_time = float(EXTRUDER_CONFIG(slowdown_below_layer_time)); float fan_below_layer_time = float(EXTRUDER_CONFIG(fan_below_layer_time)); - //if (EXTRUDER_CONFIG(cooling)) { - if (layer_time < slowdown_below_layer_time && fan_below_layer_time > 0) { - // Layer time very short. Enable the fan to a full throttle. - fan_speed_new = std::max(max_fan_speed, fan_speed_new); - bridge_fan_speed = std::max(max_fan_speed, bridge_fan_speed); - bridge_internal_fan_speed = std::max(max_fan_speed, bridge_internal_fan_speed); - ext_peri_fan_speed = std::max(max_fan_speed, ext_peri_fan_speed); // cannot be ovveridden - //top_fan_speed = std::max(max_fan_speed, top_fan_speed); - } else if (layer_time < fan_below_layer_time) { - // Layer time quite short. Enable the fan proportionally according to the current layer time. - assert(layer_time >= slowdown_below_layer_time); - double t = (layer_time - slowdown_below_layer_time) / (fan_below_layer_time - slowdown_below_layer_time); - if (fan_speed_new < max_fan_speed) - fan_speed_new = int(floor(t * min_fan_speed + (1. - t) * max_fan_speed) + 0.5); - if (bridge_fan_speed >= 0 && bridge_fan_speed < max_fan_speed) - bridge_fan_speed = int(floor(t * bridge_fan_speed + (1. - t) * max_fan_speed) + 0.5); - if (bridge_internal_fan_speed >= 0 && bridge_internal_fan_speed < max_fan_speed) - bridge_internal_fan_speed = int(floor(t * bridge_internal_fan_speed + (1. - t) * max_fan_speed) + 0.5); - if (ext_peri_fan_speed >= 0 && ext_peri_fan_speed < max_fan_speed) - ext_peri_fan_speed = int(floor(t * ext_peri_fan_speed + (1. - t) * max_fan_speed) + 0.5); - //if (top_fan_speed >= 0 && top_fan_speed < max_fan_speed) // cannot be ovveridden - // top_fan_speed = int(floor(t * top_fan_speed + (1. - t) * max_fan_speed) + 0.5); + for (int i = 0; i < ExtrusionRole::erCount; i++) { + fan_speeds[i] = default_fan_speed[i]; + } + //if not always on, the default is "no fan" and not the min. + if (!EXTRUDER_CONFIG(fan_always_on)) { + fan_speeds[0] = 0; + } + if (layer_time < slowdown_below_layer_time && fan_below_layer_time > 0) { + // Layer time very short. Enable the fan to a full throttle. + //fan_speed_new = std::max(max_fan_speed, fan_speed_new); + for (size_t etype_idx = 0; etype_idx < etype_can_increase_fan.size(); etype_idx++) { + uint16_t idx = etype_can_increase_fan[etype_idx]; + fan_speeds[idx] = std::max(max_fan_speed, fan_speeds[idx]); } - //} + } else if (layer_time < fan_below_layer_time) { + // Layer time quite short. Enable the fan proportionally according to the current layer time. + assert(layer_time >= slowdown_below_layer_time); + double t = (layer_time - slowdown_below_layer_time) / (fan_below_layer_time - slowdown_below_layer_time); + for (size_t etype_idx = 0; etype_idx < etype_can_increase_fan.size(); etype_idx++) { + uint16_t idx = etype_can_increase_fan[etype_idx]; + if (fan_speeds[idx] < max_fan_speed) // don't reduce speed if max speed is lower. + fan_speeds[idx] = std::clamp(int(t * fan_speeds[idx] + (1. - t) * max_fan_speed + 0.5), 0, 255); + } + } // Is the fan speed ramp enabled? int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer); @@ -901,47 +914,50 @@ std::string CoolingBuffer::apply_layer_cooldown( if (int(layer_id) >= disable_fan_first_layers && int(layer_id) + 1 < full_fan_speed_layer) { // Ramp up the fan speed from disable_fan_first_layers to full_fan_speed_layer. float factor = float(int(layer_id + 1) - disable_fan_first_layers) / float(full_fan_speed_layer - disable_fan_first_layers); - fan_speed_new = std::clamp(int(float(fan_speed_new ) * factor + 0.5f), 0, 255); - if (bridge_fan_speed >= 0) - bridge_fan_speed = std::clamp(int(float(bridge_fan_speed) * factor + 0.5f), 0, 255); - if (bridge_internal_fan_speed >= 0) - bridge_internal_fan_speed = std::clamp(int(float(bridge_internal_fan_speed) * factor + 0.5f), 0, 255); + for (size_t etype_idx = 0; etype_idx < etype_can_ramp_up_fan.size(); etype_idx++) { + uint16_t idx = etype_can_ramp_up_fan[etype_idx]; + fan_speeds[idx] = std::clamp(int(float(fan_speeds[idx]) * factor + 0.01f), 0, 255); + } } - bridge_fan_control = bridge_fan_speed > fan_speed_new && bridge_fan_speed >= 0; - bridge_internal_fan_control = bridge_internal_fan_speed > fan_speed_new && bridge_internal_fan_speed >= 0; - top_fan_control = top_fan_speed != fan_speed_new && top_fan_speed >= 0; - supp_inter_fan_control = supp_inter_fan_speed != fan_speed_new && supp_inter_fan_speed >= 0; - ext_peri_fan_control = ext_peri_fan_speed != fan_speed_new && ext_peri_fan_speed >= 0; + //only activate fan control if the fan speed is higher than default + fan_control[0] = true; + for (size_t i = 1; i < ExtrusionRole::erCount; i++) { + fan_control[i] = fan_speeds[i] >= 0 && fan_speeds[i] > fan_speeds[0]; + } + // if bridge_internal_fan is disabled, it takes the value of bridge_fan_control - // if bridge_internal_fan_speed is too low, it takes the value of fan_speed_new - if (!bridge_internal_fan_control && bridge_fan_control) { - bridge_internal_fan_control = true; - if(bridge_internal_fan_speed >= 0) - bridge_internal_fan_speed = fan_speed_new; - else - bridge_internal_fan_speed = bridge_fan_speed; + if (!fan_control[ExtrusionRole::erInternalBridgeInfill] && fan_control[ExtrusionRole::erBridgeInfill]) { + fan_control[ExtrusionRole::erInternalBridgeInfill] = true; + fan_speeds[ExtrusionRole::erInternalBridgeInfill] = fan_speeds[ExtrusionRole::erBridgeInfill]; + } + + // if external_perimeter_fan is disabled, it takes the value of perimeter_fan + if (!fan_control[ExtrusionRole::erExternalPerimeter] && fan_control[ExtrusionRole::erPerimeter]) { + fan_control[ExtrusionRole::erExternalPerimeter] = true; + fan_speeds[ExtrusionRole::erExternalPerimeter] = fan_speeds[ExtrusionRole::erPerimeter]; + } + + // if top_fan is disabled, it takes the value of solid_fan + if (!fan_control[ExtrusionRole::erTopSolidInfill] && fan_control[ExtrusionRole::erSolidInfill]) { + fan_control[ExtrusionRole::erTopSolidInfill] = true; + fan_speeds[ExtrusionRole::erTopSolidInfill] = fan_speeds[ExtrusionRole::erSolidInfill]; } } else { - bridge_fan_control = false; - bridge_fan_speed = 0; - bridge_internal_fan_control = false; - bridge_internal_fan_speed = 0; - top_fan_control = false; - top_fan_speed = 0; - supp_inter_fan_control = false; - supp_inter_fan_speed = 0; - ext_peri_fan_control = false; - ext_peri_fan_speed = 0; - fan_speed_new = 0; + fan_control[0] = true; + fan_speeds[0] = 0; + for (int i = 1; i < ExtrusionRole::erCount; i++) { + fan_control[i] = false; + fan_speeds[i] = 0; + } } - if (fan_speed_new != m_fan_speed) { - m_fan_speed = fan_speed_new; + if (fan_speeds[0] != m_fan_speed) { + m_fan_speed = fan_speeds[0]; new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); } }; //set to know all fan modifiers that can be applied ( TYPE_BRIDGE_FAN_END, TYPE_TOP_FAN_START, TYPE_SUPP_INTER_FAN_START, TYPE_EXTERNAL_PERIMETER). - std::unordered_set current_fan_sections; + std::vector extrude_tree; const char *pos = gcode.c_str(); int current_feedrate = 0; int stored_fan_speed = m_fan_speed; @@ -965,57 +981,15 @@ std::string CoolingBuffer::apply_layer_cooldown( stored_fan_speed = m_fan_speed; } else if (line->type & CoolingLine::TYPE_RESTORE_AFTER_WT) { new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, stored_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - } else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_START) { - if (bridge_fan_control && current_fan_sections.find(CoolingLine::TYPE_BRIDGE_FAN_START) == current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.insert(CoolingLine::TYPE_BRIDGE_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_BRIDGE_FAN_END) { - if (bridge_fan_control || current_fan_sections.find(CoolingLine::TYPE_BRIDGE_FAN_START) != current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.erase(CoolingLine::TYPE_BRIDGE_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START) { - if (bridge_internal_fan_control && current_fan_sections.find(CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START) == current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.insert(CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_END) { - if (bridge_internal_fan_control || current_fan_sections.find(CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START) != current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.erase(CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_TOP_FAN_START) { - if (top_fan_control && current_fan_sections.find(CoolingLine::TYPE_TOP_FAN_START) == current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.insert(CoolingLine::TYPE_TOP_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_TOP_FAN_END) { - if (top_fan_control || current_fan_sections.find(CoolingLine::TYPE_TOP_FAN_START) != current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.erase(CoolingLine::TYPE_TOP_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_SUPP_INTER_FAN_START) { - if (supp_inter_fan_control && current_fan_sections.find(CoolingLine::TYPE_SUPP_INTER_FAN_START) == current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.insert(CoolingLine::TYPE_SUPP_INTER_FAN_START); - } - } else if (line->type & CoolingLine::TYPE_SUPP_INTER_FAN_END) { - if (supp_inter_fan_control || current_fan_sections.find(CoolingLine::TYPE_SUPP_INTER_FAN_START) != current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.erase(CoolingLine::TYPE_SUPP_INTER_FAN_START); - } + } else if (line->type & CoolingLine::TYPE_EXTRUDE_START) { + assert(CoolingLine::to_extrusion_role(uint32_t(line->type)) != 0); + extrude_tree.push_back(CoolingLine::to_extrusion_role(uint32_t(line->type))); + fan_need_set = true; } else if (line->type & CoolingLine::TYPE_EXTRUDE_END) { - if (ext_peri_fan_control || current_fan_sections.find(CoolingLine::TYPE_EXTERNAL_PERIMETER) != current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.erase(CoolingLine::TYPE_EXTERNAL_PERIMETER); - } - } else if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE | CoolingLine::TYPE_HAS_F)) { - //ext_peri_fan_speed - if ((line->type & CoolingLine::TYPE_EXTERNAL_PERIMETER) != 0 && ext_peri_fan_control && current_fan_sections.find(CoolingLine::TYPE_EXTERNAL_PERIMETER) == current_fan_sections.end()) { - fan_need_set = true; - current_fan_sections.insert(CoolingLine::TYPE_EXTERNAL_PERIMETER); - } + assert(extrude_tree.size() > 0); + extrude_tree.pop_back(); + fan_need_set = true; + } else if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_ADJUSTABLE_MAYBE | CoolingLine::TYPE_WIPE | CoolingLine::TYPE_HAS_F)) { // Find the start of a comment, or roll to the end of line. const char *end = line_start; @@ -1031,7 +1005,7 @@ std::string CoolingBuffer::apply_layer_cooldown( new_feedrate = line->slowdown ? int(floor(60. * line->feedrate + 0.5)) : atoi(fpos); if (new_feedrate == current_feedrate) { // No need to change the F value. - if ((line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE)) || line->length == 0.) + if ((line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_ADJUSTABLE_MAYBE | CoolingLine::TYPE_WIPE)) || line->length == 0.) // Feedrate does not change and this line does not move the print head. Skip the complete G-code line including the G-code comment. end = line_end; else @@ -1078,12 +1052,14 @@ std::string CoolingBuffer::apply_layer_cooldown( } // Process the rest of the line. if (end < line_end) { - if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE)) { - // Process comments, remove ";_EXTRUDE_SET_SPEED", ";_EXTERNAL_PERIMETER", ";_WIPE" + if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_ADJUSTABLE_EMPTY | CoolingLine::TYPE_ADJUSTABLE_MAYBE | CoolingLine::TYPE_WIPE)) { + // Process comments, remove ";_EXTRUDE_SET_SPEED", ";_EXTRUDE_SET_SPEED_MAYBE", ";_WIPE" std::string comment(end, line_end); - boost::replace_all(comment, ";_EXTRUDE_SET_SPEED", ""); - if (line->type & CoolingLine::TYPE_EXTERNAL_PERIMETER) - boost::replace_all(comment, ";_EXTERNAL_PERIMETER", ""); + if (line->type & (CoolingLine::TYPE_ADJUSTABLE_MAYBE)) { + boost::replace_all(comment, ";_EXTRUDE_SET_SPEED_MAYBE", ""); + } else { + boost::replace_all(comment, ";_EXTRUDE_SET_SPEED", ""); + } if (line->type & CoolingLine::TYPE_WIPE) boost::replace_all(comment, ";_WIPE", ""); new_gcode += comment; @@ -1096,19 +1072,19 @@ std::string CoolingBuffer::apply_layer_cooldown( new_gcode.append(line_start, line_end - line_start); } if (fan_need_set) { - //choose the speed with highest priority - if (current_fan_sections.find(CoolingLine::TYPE_BRIDGE_FAN_START) != current_fan_sections.end()) - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, bridge_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - else if (current_fan_sections.find(CoolingLine::TYPE_BRIDGE_INTERNAL_FAN_START) != current_fan_sections.end()) - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, bridge_internal_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - else if (current_fan_sections.find(CoolingLine::TYPE_TOP_FAN_START) != current_fan_sections.end()) - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, top_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - else if (current_fan_sections.find(CoolingLine::TYPE_SUPP_INTER_FAN_START) != current_fan_sections.end()) - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, supp_inter_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - else if (current_fan_sections.find(CoolingLine::TYPE_EXTERNAL_PERIMETER) != current_fan_sections.end()) - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, ext_peri_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); - else - new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); + //use the most current fan + bool fan_set = false; + for (size_t i = extrude_tree.size() - 1; i < extrude_tree.size(); --i) { + if (fan_control[extrude_tree[i]]) { + new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, fan_speeds[extrude_tree[i]], EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); + fan_set = true; + break; + } + } + if (!fan_set) { + //return to default + new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_config.gcode_comments, m_fan_speed, EXTRUDER_CONFIG(extruder_fan_offset), m_config.fan_percentage); + } fan_need_set = false; } pos = line_end; diff --git a/src/libslic3r/GCode/FanMover.cpp b/src/libslic3r/GCode/FanMover.cpp index 434a80cf61e..159d13c293e 100644 --- a/src/libslic3r/GCode/FanMover.cpp +++ b/src/libslic3r/GCode/FanMover.cpp @@ -308,7 +308,7 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode } //if kickstart - // first erase everything lower that that value + // first erase everything lower than that value _remove_slow_fan(fan_speed, m_buffer_time_size + 1); // then erase everything lower that kickstart _remove_slow_fan(fan_baseline, kickstart); @@ -341,7 +341,7 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode } m_front_buffer_fan_speed = fan_speed; } else { - // first erase everything lower that that value + // first erase everything lower than that value _remove_slow_fan(fan_speed, m_buffer_time_size + 1); // then write the fan command if (!m_buffer.empty() && (m_buffer_time_size - m_buffer.front().time * 0.1) > nb_seconds_delay) { diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 76d7d142678..4df3e377d96 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -507,10 +507,11 @@ class WipeTowerWriter WipeTowerWriter& set_fan(unsigned speed, const std::string &comment) { + assert(comment.empty() || comment[0] == ';' || (comment.size() > 1 && comment[0] == ' ' && comment[1] == ';')); if (speed == m_last_fan_speed) return *this; if (speed == 0) - m_gcode += "M107\n"; + m_gcode += "M107" + comment + "\n"; else m_gcode += "M106 S" + std::to_string(unsigned(255.0 * speed / 100.0)) + comment + "\n"; m_last_fan_speed = speed; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index fc79a051ff7..60c4ab3e0d3 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -745,21 +745,29 @@ static std::vector s_Preset_filament_options { "filament_dip_insertion_speed", "filament_dip_extraction_speed", //skinnydip params end "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", - "full_fan_speed_layer", + // cooling "fan_always_on", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "bridge_internal_fan_speed", + "external_perimeter_fan_speed", + "gap_fill_fan_speed", + "infill_fan_speed", + "overhangs_fan_speed", + "perimeter_fan_speed", + "solid_infill_fan_speed", + "support_material_fan_speed", "support_material_interface_fan_speed", "top_fan_speed", "disable_fan_first_layers", - "fan_below_layer_time", + "full_fan_speed_layer", + "fan_below_layer_time", "slowdown_below_layer_time", "max_speed_reduction", "min_print_speed", + // custom gcode "start_filament_gcode", "end_filament_gcode", - "external_perimeter_fan_speed", // 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", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 9f347976001..ecf364e8b8b 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -117,6 +117,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "first_layer_min_speed", "full_fan_speed_layer", "gap_fill_acceleration", + "gap_fill_fan_speed", "gap_fill_flow_match_perimeter", "gap_fill_speed", "gcode_comments", @@ -125,6 +126,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "gcode_precision_xyz", "gcode_precision_e", "infill_acceleration", + "infill_fan_speed", "ironing_acceleration", "layer_gcode", "max_fan_speed", @@ -146,9 +148,11 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "only_retract_when_crossing_perimeters", "output_filename_format", "overhangs_acceleration", + "overhangs_fan_speed", "perimeter_acceleration", "post_process", "gcode_substitutions", + "perimeter_fan_speed", "printer_notes", "retract_before_travel", "retract_before_wipe", @@ -167,7 +171,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver& /* ne "single_extruder_multi_material_priming", "slowdown_below_layer_time", "solid_infill_acceleration", + "solid_infill_fan_speed", "support_material_acceleration", + "support_material_fan_speed", "support_material_interface_acceleration", "support_material_interface_fan_speed", "standby_temperature_delta", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a92d62c566d..fdb04d64eab 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -729,8 +729,8 @@ void PrintConfigDef::init_fff_params() def->label = L("Bridges fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during bridges and overhangs. It won't slow down the fan if it's currently running at a higher speed." - "\nSet to -1 to disable this override." - "\nCan only be overriden by disable_fan_first_layers."); + "\nSet to -1 to disable this override (Bridge will use default fan speed)." + "\nCan be disabled by disable_fan_first_layers and increased by low layer time."); def->sidetext = L("%"); def->min = -1; def->max = 100; @@ -744,7 +744,7 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("This fan speed is enforced during all infill bridges. It won't slow down the fan if it's currently running at a higher speed." "\nSet to 1 to follow default speed." "\nSet to -1 to disable this override (internal bridges will use Bridges fan speed)." - "\nCan only be overriden by disable_fan_first_layers."); + "\nCan be disabled by disable_fan_first_layers and increased by low layer time."); def->sidetext = L("%"); def->min = -1; def->max = 100; @@ -1521,11 +1521,12 @@ void PrintConfigDef::init_fff_params() def = this->add("external_perimeter_fan_speed", coInts); def->label = L("External perimeter fan speed"); - def->tooltip = L("When set to a non-zero value this fan speed is used only for external perimeters (visible ones). " + def->tooltip = L("When set to a non-zero value this fan speed is used only for external perimeters (visible ones) and thin walls." "\nSet to 1 to disable the fan." "\nSet to -1 to use the normal fan speed on external perimeters." "External perimeters can benefit from higher fan speed to improve surface finish, " - "while internal perimeters, infill, etc. benefit from lower fan speed to improve layer adhesion."); + "while internal perimeters, infill, etc. benefit from lower fan speed to improve layer adhesion." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer and increased by low layer time."); def->sidetext = L("%"); def->min = -1; def->max = 100; @@ -2586,8 +2587,9 @@ void PrintConfigDef::init_fff_params() def->category = OptionCategory::filament; def->tooltip = L("Fan speed will be ramped up linearly from zero at layer \"disable_fan_first_layers\" " "to maximum at layer \"full_fan_speed_layer\". " - "\"full_fan_speed_layer\" will be ignored if lower than \"disable_fan_first_layers\", in which case " - "the fan will be running at maximum allowed speed at layer \"disable_fan_first_layers\" + 1."); + "\"full_fan_speed_layer\" will be ignored if equal or lower than \"disable_fan_first_layers\", in which case " + "the fan will be running at maximum allowed speed at layer \"disable_fan_first_layers\" + 1." + "\nset 0 to disable"); def->min = 0; def->max = 1000; def->mode = comExpert | comPrusa; @@ -2672,6 +2674,20 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent{ 0, false }); + def = this->add("gap_fill_fan_speed", coInts); + def->label = L("Gap Fill fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all gap fill Perimeter moves" + "\nSet to 1 to disable fan." + "\nSet to -1 to disable this override (Gap Fill will use default fan speed)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer and increased by low layer time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("gap_fill_flow_match_perimeter", coPercent); def->label = L("Cap with perimeter flow"); def->full_label = L("Gapfill: cap speed with perimeter flow"); @@ -3107,6 +3123,20 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent(100, true, false)); + def = this->add("infill_fan_speed", coInts); + def->label = L("Internal Infill fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all Internal Infill moves" + "\nSet to 1 to disable fan." + "\nSet to -1 to disable this override (Internal Infill will use default fan speed)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer and increased by low layer time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("infill_first", coBool); def->label = L("Infill before perimeters"); def->category = OptionCategory::infill; @@ -3848,6 +3878,20 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent(0,false)); + def = this->add("overhangs_fan_speed", coInts); + def->label = L("Overhang Perimeter fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all Overhang Perimeter moves" + "\nSet to 1 to disable fan." + "\nSet to -1 to disable this override (Overhang Perimeter use default fan speed)." + "\nCan be disabled by disable_fan_first_layers and increased by low layer time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("overhangs_speed", coFloatOrPercent); def->label = L("Overhangs"); def->full_label = L("Overhangs speed"); @@ -4053,6 +4097,20 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent(false, 0)); + def = this->add("perimeter_fan_speed", coInts); + def->label = L("Internal Perimeter fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all Perimeter moves" + "\nSet to 1 to disable fan." + "\nSet to -1 to disable this override (Internal Perimeter use default fan speed)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer and increased by low layer time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("perimeter_loop", coBool); def->label = L("Perimeters loop"); def->full_label = L("Perimeters loop"); @@ -4870,6 +4928,20 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvancedE | comSuSi; def->set_default_value(new ConfigOptionFloatOrPercent(100, true, false)); + def = this->add("solid_infill_fan_speed", coInts); + def->label = L("Solid Infill fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all Solid Infill moves" + "\nSet to 1 to disable fan." + "\nSet to -1 to disable this override (Solid Infill will use default fan speed)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer and increased by low layer time."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("solid_infill_speed", coFloatOrPercent); def->label = L("Solid"); def->full_label = L("Solid infill speed"); @@ -5233,6 +5305,20 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvancedE | comPrusa; def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); + def = this->add("support_material_fan_speed", coInts); + def->label = L("Support Material fan speed"); + def->category = OptionCategory::cooling; + def->tooltip = L("This fan speed is enforced during all support moves" + "\nSet to 0 to disable fan." + "\nSet to -1 to disable this override (Support will use default fan speed)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer."); + def->sidetext = L("%"); + def->min = -1; + def->max = 100; + def->mode = comAdvancedE | comSuSi; + def->is_vector_extruder = true; + def->set_default_value(new ConfigOptionInts{ -1 }); + def = this->add("support_material_interface_angle", coFloat); def->label = L("Pattern angle"); def->full_label = L("Support interface pattern angle"); @@ -5258,8 +5344,8 @@ void PrintConfigDef::init_fff_params() def->label = L("Support interface fan speed"); def->category = OptionCategory::cooling; def->tooltip = L("This fan speed is enforced during all support interfaces, to be able to weaken their bonding with a high fan speed." - "\nSet to 1 to disable the fan." - "\nSet to -1 to disable this override." + "\nSet to 0 to disable the fan." + "\nSet to -1 to disable this override (Support Interface will use Support)." "\nCan only be overriden by disable_fan_first_layers."); def->sidetext = L("%"); def->min = -1; @@ -5678,12 +5764,12 @@ void PrintConfigDef::init_fff_params() def->set_default_value(new ConfigOptionStrings("")); def = this->add("top_fan_speed", coInts); - def->label = L("Top fan speed"); + def->label = L("Top Solid fan speed"); def->category = OptionCategory::cooling; - def->tooltip = L("This fan speed is enforced during all top fills." + def->tooltip = L("This fan speed is enforced during all top fills (including ironing)." "\nSet to 1 to disable the fan." - "\nSet to -1 to disable this override." - "\nCan only be overriden by disable_fan_first_layers."); + "\nSet to -1 to disable this override (Top Solid Infill will use Solid Infill)." + "\nCan be disabled by disable_fan_first_layers, slowed down by full_fan_speed_layer."); def->sidetext = L("%"); def->min = -1; def->max = 100; @@ -7700,6 +7786,7 @@ std::unordered_set prusa_export_to_remove_keys = { "first_layer_size_compensation_layers", "gap_fill_acceleration", "gap_fill_extension", +"gap_fill_fan_speed", "gap_fill_flow_match_perimeter", "gap_fill_last", "gap_fill_infill", @@ -7719,6 +7806,7 @@ std::unordered_set prusa_export_to_remove_keys = { "infill_dense_algo", "infill_dense", "infill_extrusion_spacing", +"infill_fan_speed", "ironing_acceleration", "lift_min", "machine_max_acceleration_travel", @@ -7743,6 +7831,7 @@ std::unordered_set prusa_export_to_remove_keys = { "only_one_perimeter_first_layer", "over_bridge_flow_ratio", "overhangs_acceleration", +"overhangs_fan_speed", "overhangs_reverse_threshold", "overhangs_reverse", "overhangs_speed", @@ -7750,6 +7839,7 @@ std::unordered_set prusa_export_to_remove_keys = { "overhangs_width_speed", "perimeter_bonding", "perimeter_extrusion_spacing", +"perimeter_fan_speed", "perimeter_loop_seam", "perimeter_loop", "perimeter_overlap", @@ -7783,10 +7873,12 @@ std::unordered_set prusa_export_to_remove_keys = { "solid_fill_pattern", "solid_infill_acceleration", "solid_infill_extrusion_spacing", +"solid_infill_fan_speed", "start_gcode_manual", "support_material_angle_height", "support_material_acceleration", "support_material_contact_distance_type", +"support_material_fan_speed", "support_material_interface_acceleration", "support_material_interface_angle", "support_material_interface_angle_increment", diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 69993cd2ac0..24949305e2c 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1170,7 +1170,9 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionInts, first_layer_temperature)) ((ConfigOptionInts, full_fan_speed_layer)) ((ConfigOptionFloatOrPercent, gap_fill_acceleration)) + ((ConfigOptionInts, gap_fill_fan_speed)) ((ConfigOptionFloatOrPercent, infill_acceleration)) + ((ConfigOptionInts, infill_fan_speed)) ((ConfigOptionFloatOrPercent, ironing_acceleration)) ((ConfigOptionFloat, lift_min)) ((ConfigOptionInts, max_fan_speed)) @@ -1192,7 +1194,9 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionBool, ooze_prevention)) ((ConfigOptionString, output_filename_format)) ((ConfigOptionFloatOrPercent, overhangs_acceleration)) + ((ConfigOptionInts, overhangs_fan_speed)) ((ConfigOptionFloatOrPercent, perimeter_acceleration)) + ((ConfigOptionInts, perimeter_fan_speed)) ((ConfigOptionStrings, post_process)) ((ConfigOptionString, print_custom_variables)) ((ConfigOptionString, printer_custom_variables)) @@ -1214,8 +1218,10 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloats, slowdown_below_layer_time)) ((ConfigOptionBool, spiral_vase)) ((ConfigOptionFloatOrPercent, solid_infill_acceleration)) + ((ConfigOptionInts, solid_infill_fan_speed)) ((ConfigOptionInt, standby_temperature_delta)) ((ConfigOptionFloatOrPercent, support_material_acceleration)) + ((ConfigOptionInts, support_material_fan_speed)) ((ConfigOptionFloatOrPercent, support_material_interface_acceleration)) ((ConfigOptionInts, support_material_interface_fan_speed)) ((ConfigOptionInts, temperature))