diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 6815ea73a07..3dbfae25f10 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -677,12 +677,16 @@ std::string CoolingBuffer::apply_layer_cooldown( int fan_speed = -1; bool bridge_fan_control = false; int bridge_fan_speed = 0; - auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &fan_speed, &bridge_fan_control, &bridge_fan_speed ]() { + int external_perimeter_fan_speed = 0; + bool in_external_perimeter = false; + auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &fan_speed, &bridge_fan_control, &bridge_fan_speed, &external_perimeter_fan_speed, &in_external_perimeter]() { + in_external_perimeter = false; const FullPrintConfig &config = m_gcodegen.config(); #define EXTRUDER_CONFIG(OPT) config.OPT.get_at(m_current_extruder) int min_fan_speed = EXTRUDER_CONFIG(min_fan_speed); int fan_speed_new = EXTRUDER_CONFIG(fan_always_on) ? min_fan_speed : 0; if (layer_id >= (size_t)EXTRUDER_CONFIG(disable_fan_first_layers)) { + external_perimeter_fan_speed = EXTRUDER_CONFIG(external_perimeter_fan_speed); 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)); @@ -696,6 +700,9 @@ std::string CoolingBuffer::apply_layer_cooldown( double t = (layer_time - slowdown_below_layer_time) / (fan_below_layer_time - slowdown_below_layer_time); fan_speed_new = int(floor(t * min_fan_speed + (1. - t) * max_fan_speed) + 0.5); } + // Use the higher of the adjusted speeds if both external perimeter and automatic cooling are enabled. + if (external_perimeter_fan_speed && fan_speed_new > external_perimeter_fan_speed) + external_perimeter_fan_speed = fan_speed_new; } bridge_fan_speed = EXTRUDER_CONFIG(bridge_fan_speed); #undef EXTRUDER_CONFIG @@ -704,6 +711,7 @@ std::string CoolingBuffer::apply_layer_cooldown( bridge_fan_control = false; bridge_fan_speed = 0; fan_speed_new = 0; + external_perimeter_fan_speed = 0; } if (fan_speed_new != fan_speed) { fan_speed = fan_speed_new; @@ -718,6 +726,16 @@ std::string CoolingBuffer::apply_layer_cooldown( for (const CoolingLine *line : lines) { const char *line_start = gcode.c_str() + line->line_start; const char *line_end = gcode.c_str() + line->line_end; + + // Adjust the fan speed for external perimeters only when the setting is enabled and we would need to adjust the speed. + bool adjust_fan_speed_on_external_perimeter = !!external_perimeter_fan_speed && fan_speed != external_perimeter_fan_speed; + + if (adjust_fan_speed_on_external_perimeter) { + bool prev_in_external_perimeter = in_external_perimeter; + in_external_perimeter = line->type & CoolingLine::TYPE_EXTERNAL_PERIMETER; + adjust_fan_speed_on_external_perimeter = in_external_perimeter != prev_in_external_perimeter; + } + if (line_start > pos) new_gcode.append(pos, line_start - pos); if (line->type & CoolingLine::TYPE_SET_TOOL) { @@ -734,8 +752,12 @@ std::string CoolingBuffer::apply_layer_cooldown( if (bridge_fan_control) new_gcode += m_gcodegen.writer().set_fan(fan_speed, true); } else if (line->type & CoolingLine::TYPE_EXTRUDE_END) { - // Just remove this comment. + if (adjust_fan_speed_on_external_perimeter) + new_gcode += m_gcodegen.writer().set_fan(fan_speed, true); } else if (line->type & (CoolingLine::TYPE_ADJUSTABLE | CoolingLine::TYPE_EXTERNAL_PERIMETER | CoolingLine::TYPE_WIPE | CoolingLine::TYPE_HAS_F)) { + if (adjust_fan_speed_on_external_perimeter) + new_gcode += m_gcodegen.writer().set_fan(external_perimeter_fan_speed, true); + // Find the start of a comment, or roll to the end of line. const char *end = line_start; for (; end < line_end && *end != ';'; ++ end); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 421a1f39e2b..2c85373f300 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -444,7 +444,7 @@ const std::vector& Preset::filament_options() "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower", "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", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed", - "start_filament_gcode", "end_filament_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", "filament_retract_before_travel", "filament_retract_layer_change", "filament_wipe", "filament_retract_before_wipe", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 9c5c7bfb7c5..f913607c9b9 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -85,6 +85,7 @@ bool Print::invalidate_state_by_config_options(const std::vectormode = comAdvanced; def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); + 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). " + "When set to zero the normal fan speed is used 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."); + def->sidetext = L("%"); + def->min = 0; + def->max = 100; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInts { 0 }); + def = this->add("external_perimeter_speed", coFloatOrPercent); def->label = L("External perimeters"); def->category = L("Speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 99b5feb9515..1c9b67fc177 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -832,6 +832,7 @@ class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig ConfigOptionFloat default_acceleration; ConfigOptionInts disable_fan_first_layers; ConfigOptionFloat duplicate_distance; + ConfigOptionInts external_perimeter_fan_speed; ConfigOptionFloat extruder_clearance_height; ConfigOptionFloat extruder_clearance_radius; ConfigOptionStrings extruder_colour; @@ -905,6 +906,7 @@ class PrintConfig : public MachineEnvelopeConfig, public GCodeConfig OPT_PTR(default_acceleration); OPT_PTR(disable_fan_first_layers); OPT_PTR(duplicate_distance); + OPT_PTR(external_perimeter_fan_speed); OPT_PTR(extruder_clearance_height); OPT_PTR(extruder_clearance_radius); OPT_PTR(extruder_colour); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index a650a94738f..33557d21b49 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1804,6 +1804,7 @@ void TabFilament::build() line.append_option(optgroup->get_option("max_fan_speed")); optgroup->append_line(line); + optgroup->append_single_option_line("external_perimeter_fan_speed"); optgroup->append_single_option_line("bridge_fan_speed"); optgroup->append_single_option_line("disable_fan_first_layers");