From 81d81da08c935544d07764aec02a86d67ca74a5d Mon Sep 17 00:00:00 2001 From: Misterff1 Date: Wed, 22 Apr 2026 17:28:18 +0200 Subject: [PATCH] Add more granular control over exhaust fan speed during print and on completion (#13228) # Description This commit adds the enhancement of https://github.com/OrcaSlicer/OrcaSlicer/issues/13116 - Adds checkboxes to enable or disable the fan speed override during print or after printing is completed. This allows users to, for example, only override the fan speed during printing whilst leaving the fan speed as is set in the machine gcode at the end. - Two new flags are added for this: `activate_air_filtration_during_print[extruder]` and `activate_air_filtration_on_completion[extruder]`. These can be used to more finely control machine gcode - Current filament settings remain as they are: `activate_air_filtration[extruder]` settings are unaffected and by default both new flags are set to true, ensuring the same set behavior as before. # Screenshots/Recordings/Graphs Screenshot From 2026-04-09 18-57-14 As you can see there are now checkboxes left of the fan speeds. They have their own tooltip too, which also helps identify the correct flags for users who want to adjust their machine gcode. ## Tests I have thoroughly tested this on my own computer (CachyOS) and on my printer. I have also carefully checked the gcode in every possible state this is in and ensured that the unsaved changes dialog properly displays the labels for these settings. Flags are set properly, sliced files properly use the flags if you check for them in machine gcode and default behavior is unaffected for those who have already changed settings for air filtration. From what I can see, this does exactly what it should be doing without any issues. --- src/libslic3r/GCode.cpp | 24 ++++++++++++++---------- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 2 ++ src/libslic3r/PrintConfig.cpp | 20 +++++++++++++++++++- src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/Tab.cpp | 14 +++++++++++--- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 3658070fdb..c67d8b6695 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3099,15 +3099,16 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato this->_print_first_layer_extruder_temperatures(file, print, machine_start_gcode, initial_extruder_id, true); } // Orca: when activate_air_filtration is set on any extruder, find and set the highest during_print_exhaust_fan_speed - bool activate_air_filtration = false; + bool activate_air_filtration_during_print = false; int during_print_exhaust_fan_speed = 0; for (const auto &extruder : m_writer.extruders()) { - activate_air_filtration |= m_config.activate_air_filtration.get_at(extruder.id()); - if (m_config.activate_air_filtration.get_at(extruder.id())) + if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_during_print.get_at(extruder.id())) { + activate_air_filtration_during_print = true; during_print_exhaust_fan_speed = std::max(during_print_exhaust_fan_speed, m_config.during_print_exhaust_fan_speed.get_at(extruder.id())); + } } - if (activate_air_filtration) + if (activate_air_filtration_during_print) file.write(m_writer.set_exhaust_fan(during_print_exhaust_fan_speed, true)); print.throw_if_canceled(); @@ -3407,13 +3408,16 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato if (activate_chamber_temp_control && max_chamber_temp > 0) file.write(m_writer.set_chamber_temperature(0, false)); //close chamber_temperature - if (activate_air_filtration) { - int complete_print_exhaust_fan_speed = 0; - for (const auto& extruder : m_writer.extruders()) - if (m_config.activate_air_filtration.get_at(extruder.id())) - complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id())); - file.write(m_writer.set_exhaust_fan(complete_print_exhaust_fan_speed, true)); + bool activate_air_filtration_on_completion = false; + int complete_print_exhaust_fan_speed = 0; + for (const auto& extruder : m_writer.extruders()) { + if (m_config.activate_air_filtration.get_at(extruder.id()) && m_config.activate_air_filtration_on_completion.get_at(extruder.id())) { + activate_air_filtration_on_completion = true; + complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id())); + } } + if (activate_air_filtration_on_completion) + file.write(m_writer.set_exhaust_fan(complete_print_exhaust_fan_speed, true)); // adds tags for time estimators file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str()); file.write_format("; EXECUTABLE_BLOCK_END\n\n"); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 65397d11e1..9e2437ae0a 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -972,7 +972,7 @@ static std::vector s_Preset_filament_options {/*"filament_colour", "fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed", "filament_start_gcode", "filament_end_gcode", //exhaust fan control - "activate_air_filtration","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed", + "activate_air_filtration","activate_air_filtration_during_print","activate_air_filtration_on_completion","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed", // Retract overrides "filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel", "filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b9e8842b0b..ad6e279cd4 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -219,6 +219,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "ironing_fan_speed", "single_extruder_multi_material_priming", "activate_air_filtration", + "activate_air_filtration_during_print", + "activate_air_filtration_on_completion", "during_print_exhaust_fan_speed", "complete_print_exhaust_fan_speed", "activate_chamber_temp_control", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 72fb71ceab..7139341e47 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1740,6 +1740,19 @@ void PrintConfigDef::init_fff_params() def->tooltip = L("Activate for better air filtration. G-code command: M106 P3 S(0-255)"); def->mode = comSimple; def->set_default_value(new ConfigOptionBools{false}); + + + def = this->add("activate_air_filtration_during_print", coBools); + def->full_label = L("During print"); + def->tooltip=L("Enable this to override the fan speed set in custom G-code during print."); + def->mode = comSimple; + def->set_default_value(new ConfigOptionBools{true}); + + def = this->add("activate_air_filtration_on_completion", coBools); + def->full_label = L("On completion"); + def->tooltip=L("Enable this to override the fan speed set in custom G-code after print completion."); + def->mode = comSimple; + def->set_default_value(new ConfigOptionBools{true}); def = this->add("during_print_exhaust_fan_speed", coInts); def->label = L("Fan speed"); @@ -7862,7 +7875,12 @@ std::set filament_options_with_variant = { "filament_ironing_flow", "filament_ironing_spacing", "filament_ironing_inset", - "filament_ironing_speed" + "filament_ironing_speed", + "activate_air_filtration", + "activate_air_filtration_during_print", + "activate_air_filtration_on_completion", + "during_print_exhaust_fan_speed", + "complete_print_exhaust_fan_speed" }; // Parameters that are the same as the number of extruders diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 0acd1747a6..60aff4f0e9 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1457,6 +1457,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionBools, dont_slow_down_outer_wall)) ((ConfigOptionFloats, fan_cooling_layer_time)) ((ConfigOptionBools, activate_air_filtration)) + ((ConfigOptionBools, activate_air_filtration_during_print)) + ((ConfigOptionBools, activate_air_filtration_on_completion)) ((ConfigOptionInts, during_print_exhaust_fan_speed)) ((ConfigOptionInts, complete_print_exhaust_fan_speed)) ((ConfigOptionFloatOrPercent, initial_layer_line_width)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 9ccf458323..4c2a908cf6 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -4018,16 +4018,18 @@ void TabFilament::build() optgroup = page->new_optgroup(L("Exhaust fan"),L"param_cooling_exhaust"); - optgroup->append_single_option_line("activate_air_filtration", "material_cooling#activate-air-filtration"); + optgroup->append_single_option_line("activate_air_filtration", "material_cooling#activate-air-filtration", 0); line = {L("During print"), ""}; - line.append_option(optgroup->get_option("during_print_exhaust_fan_speed")); + line.append_option(optgroup->get_option("activate_air_filtration_during_print", 0)); + line.append_option(optgroup->get_option("during_print_exhaust_fan_speed", 0)); line.label_path = "material_cooling#during-print"; optgroup->append_line(line); line = {L("Complete print"), ""}; - line.append_option(optgroup->get_option("complete_print_exhaust_fan_speed")); + line.append_option(optgroup->get_option("activate_air_filtration_on_completion", 0)); + line.append_option(optgroup->get_option("complete_print_exhaust_fan_speed", 0)); line.label_path = "material_cooling#complete-print"; optgroup->append_line(line); //BBS @@ -4195,6 +4197,12 @@ void TabFilament::toggle_options() toggle_option("additional_cooling_fan_speed", cfg.opt_bool("auxiliary_fan")); + bool activate_air_filtration = m_config->opt_bool("activate_air_filtration", 0); + toggle_option("activate_air_filtration_during_print", activate_air_filtration, 0); + toggle_option("activate_air_filtration_on_completion", activate_air_filtration, 0); + toggle_option("during_print_exhaust_fan_speed", activate_air_filtration && m_config->opt_bool("activate_air_filtration_during_print", 0), 0); + toggle_option("complete_print_exhaust_fan_speed", activate_air_filtration && m_config->opt_bool("activate_air_filtration_on_completion", 0), 0); + // Orca: toggle dont slow down for external perimeters if bool has_slow_down_for_layer_cooling = m_config->opt_bool("slow_down_for_layer_cooling", 0); toggle_option("dont_slow_down_outer_wall", has_slow_down_for_layer_cooling);