Enhancement: Enable separate internal bridge fan speed control (#7906)

* Separate internal bridge fan speed control

* Merge branch 'SoftFever:main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'SoftFever:main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control

* Merge remote-tracking branch 'upstream/main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control

* Merge branch 'main' into Allow-separate-internal-bridge-fan-control
This commit is contained in:
Ioannis Giannakas 2025-02-09 13:53:57 +00:00 committed by GitHub
parent 2eed82ed81
commit 4e74aaf144
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 104 additions and 20 deletions

View file

@ -1829,6 +1829,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_max_layer_z = 0.f;
m_last_width = 0.f;
m_is_overhang_fan_on = false;
m_is_internal_bridge_fan_on = false;
m_is_supp_interface_fan_on = false;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
m_last_mm3_per_mm = 0.;
@ -5489,7 +5490,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
// { "75%", Overhang_threshold_4_4 },
// { "95%", Overhang_threshold_bridge }
auto check_overhang_fan = [&overhang_fan_threshold](float overlap, ExtrusionRole role) {
if (is_bridge(role)) {
if (role == erBridgeInfill || role == erOverhangPerimeter) { // ORCA: Split out bridge infill to internal and external to apply separate fan settings
return true;
}
switch (overhang_fan_threshold) {
@ -5582,7 +5583,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
int overhang_threshold = overhang_fan_threshold == Overhang_threshold_none ? Overhang_threshold_none
: overhang_fan_threshold - 1;
if ((overhang_fan_threshold == Overhang_threshold_none && is_external_perimeter(path.role())) ||
(path.get_overhang_degree() > overhang_threshold || is_bridge(path.role()))) {
(path.get_overhang_degree() > overhang_threshold ||
(path.role() == erBridgeInfill || path.role() == erOverhangPerimeter))) { // ORCA: Add support for separate internal bridge fan speed control
if (!m_is_overhang_fan_on) {
gcode += ";_OVERHANG_FAN_START\n";
m_is_overhang_fan_on = true;
@ -5593,6 +5595,17 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
gcode += ";_OVERHANG_FAN_END\n";
}
}
if (path.role() == erInternalBridgeInfill) { // ORCA: Add support for separate internal bridge fan speed control
if (!m_is_internal_bridge_fan_on) {
gcode += ";_INTERNAL_BRIDGE_FAN_START\n";
m_is_internal_bridge_fan_on = true;
}
} else {
if (m_is_internal_bridge_fan_on) {
m_is_internal_bridge_fan_on = false;
gcode += ";_INTERNAL_BRIDGE_FAN_END\n";
}
}
}
if (supp_interface_fan_speed >= 0 && path.role() == erSupportMaterialInterface) {
if (!m_is_supp_interface_fan_on) {
@ -5728,6 +5741,9 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
if( m_enable_cooling_markers && enable_overhang_bridge_fan)
pre_fan_enabled = check_overhang_fan(new_points[0].overlap, path.role());
if(path.role() == erInternalBridgeInfill) // ORCA: Add support for separate internal bridge fan speed control
pre_fan_enabled = true;
double path_length = 0.;
for (size_t i = 1; i < new_points.size(); i++) {
std::string tempDescription = description;
@ -5750,6 +5766,19 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
}
pre_fan_enabled = cur_fan_enabled;
}
// ORCA: Add support for separate internal bridge fan speed control
if (path.role() == erInternalBridgeInfill) {
if (!m_is_internal_bridge_fan_on) {
gcode += ";_INTERNAL_BRIDGE_FAN_START\n";
m_is_internal_bridge_fan_on = true;
}
} else {
if (m_is_internal_bridge_fan_on) {
gcode += ";_INTERNAL_BRIDGE_FAN_END\n";
m_is_internal_bridge_fan_on = false;
}
}
if (supp_interface_fan_speed >= 0 && path.role() == erSupportMaterialInterface) {
if (!m_is_supp_interface_fan_on) {
gcode += ";_SUPP_INTERFACE_FAN_START\n";

View file

@ -515,6 +515,7 @@ private:
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
// Orca
bool m_is_overhang_fan_on;
bool m_is_internal_bridge_fan_on; // ORCA: Add support for separate internal bridge fan speed control
bool m_is_supp_interface_fan_on;
// Markers for the Pressure Equalizer to recognize the extrusion type.
// The Pressure Equalizer removes the markers from the final G-code.

View file

@ -65,6 +65,9 @@ struct CoolingLine
TYPE_FORCE_RESUME_FAN = 1 << 14,
TYPE_SUPPORT_INTERFACE_FAN_START = 1 << 15,
TYPE_SUPPORT_INTERFACE_FAN_END = 1 << 16,
// ORCA: Add support for separate internal bridge fan speed control
TYPE_INTERNAL_BRIDGE_FAN_START = 1 << 17,
TYPE_INTERNAL_BRIDGE_FAN_END = 1 << 18,
};
CoolingLine(unsigned int type, size_t line_start, size_t line_end) :
@ -511,6 +514,10 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
line.type = CoolingLine::TYPE_OVERHANG_FAN_START;
} else if (boost::starts_with(sline, ";_OVERHANG_FAN_END")) {
line.type = CoolingLine::TYPE_OVERHANG_FAN_END;
} else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_START")) { // ORCA: Add support for separate internal bridge fan speed control
line.type = CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START;
} else if (boost::starts_with(sline, ";_INTERNAL_BRIDGE_FAN_END")) { // ORCA: Add support for separate internal bridge fan speed control
line.type = CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_START")) {
line.type = CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START;
} else if (boost::starts_with(sline, ";_SUPP_INTERFACE_FAN_END")) {
@ -705,9 +712,11 @@ std::string CoolingBuffer::apply_layer_cooldown(
new_gcode.reserve(gcode.size() * 2);
bool overhang_fan_control= false;
int overhang_fan_speed = 0;
bool internal_bridge_fan_control= false; // ORCA: Add support for separate internal bridge fan speed control
int internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control
bool supp_interface_fan_control= false;
int supp_interface_fan_speed = 0;
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) {
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed, &internal_bridge_fan_control, &internal_bridge_fan_speed, &supp_interface_fan_control, &supp_interface_fan_speed](bool immediately_apply) {
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
float fan_min_speed = EXTRUDER_CONFIG(fan_min_speed);
float fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
@ -749,8 +758,18 @@ std::string CoolingBuffer::apply_layer_cooldown(
supp_interface_fan_speed = EXTRUDER_CONFIG(support_material_interface_fan_speed);
supp_interface_fan_control = supp_interface_fan_speed >= 0;
#undef EXTRUDER_CONFIG
overhang_fan_control = overhang_fan_speed > fan_speed_new;
// ORCA: Add support for separate internal bridge fan speed control
internal_bridge_fan_speed = EXTRUDER_CONFIG(internal_bridge_fan_speed);
internal_bridge_fan_control = internal_bridge_fan_speed >=0;
if( internal_bridge_fan_speed < 0 ) { // ORCA: Backwards compatibility setting for Orca internal bridge fan speed setting - if set at -1 (which is the default) use the overhang fan speed settings.
internal_bridge_fan_speed = overhang_fan_speed;
internal_bridge_fan_control = overhang_fan_control;
}
#undef EXTRUDER_CONFIG
} else {
overhang_fan_control = false;
overhang_fan_speed = 0;
@ -758,6 +777,8 @@ std::string CoolingBuffer::apply_layer_cooldown(
additional_fan_speed_new = 0;
supp_interface_fan_control = false;
supp_interface_fan_speed = 0;
internal_bridge_fan_control = false; // ORCA: Add support for separate internal bridge fan speed control
internal_bridge_fan_speed = 0; // ORCA: Add support for separate internal bridge fan speed control
}
if (fan_speed_new != m_fan_speed) {
m_fan_speed = fan_speed_new;
@ -780,6 +801,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
// Orca: Reduce set fan commands by deferring the GCodeWriter::set_fan calls. Inspired by SuperSlicer
// define fan_speed_change_requests and initialize it with all possible types fan speed change requests
std::unordered_map<int, bool> fan_speed_change_requests = {{CoolingLine::TYPE_OVERHANG_FAN_START, false},
{CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START, false}, // ORCA: Add support for separate internal bridge fan speed control
{CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START, false},
{CoolingLine::TYPE_FORCE_RESUME_FAN, false}};
bool need_set_fan = false;
@ -809,6 +831,16 @@ std::string CoolingBuffer::apply_layer_cooldown(
fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START] = false;
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START) { // ORCA: Add support for separate internal bridge fan speed control
if (internal_bridge_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) {
need_set_fan = true;
fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = true;
}
} else if (line->type & CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_END) { // ORCA: Add support for separate internal bridge fan speed control
if (internal_bridge_fan_control && fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START] = false;
}
need_set_fan = true;
} else if (line->type & CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START) {
if (supp_interface_fan_control && !fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]) {
fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START] = true;
@ -917,6 +949,9 @@ std::string CoolingBuffer::apply_layer_cooldown(
if (fan_speed_change_requests[CoolingLine::TYPE_OVERHANG_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, overhang_fan_speed);
m_current_fan_speed = overhang_fan_speed;
} else if (fan_speed_change_requests[CoolingLine::TYPE_INTERNAL_BRIDGE_FAN_START]){ // ORCA: Add support for separate internal bridge fan speed control
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, internal_bridge_fan_speed);
m_current_fan_speed = internal_bridge_fan_speed;
}
else if (fan_speed_change_requests[CoolingLine::TYPE_SUPPORT_INTERFACE_FAN_START]){
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, supp_interface_fan_speed);

View file

@ -860,7 +860,7 @@ static std::vector<std::string> s_Preset_filament_options {
"filament_wipe_distance", "additional_cooling_fan_speed",
"nozzle_temperature_range_low", "nozzle_temperature_range_high",
//SoftFever
"enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink","filament_shrinkage_compensation_z", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
"enable_pressure_advance", "pressure_advance","adaptive_pressure_advance","adaptive_pressure_advance_model","adaptive_pressure_advance_overhangs", "adaptive_pressure_advance_bridges","chamber_temperature", "filament_shrink","filament_shrinkage_compensation_z", "support_material_interface_fan_speed","internal_bridge_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
"filament_loading_speed", "filament_loading_speed_start",
"filament_unloading_speed", "filament_unloading_speed_start", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance",
"filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",

View file

@ -193,6 +193,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"gcode_label_objects",
"exclude_object",
"support_material_interface_fan_speed",
"internal_bridge_fan_speed", // ORCA: Add support for separate internal bridge fan speed control
"single_extruder_multi_material_priming",
"activate_air_filtration",
"during_print_exhaust_fan_speed",

View file

@ -908,15 +908,19 @@ void PrintConfigDef::init_fff_params()
def = this->add("enable_overhang_bridge_fan", coBools);
def->label = L("Force cooling for overhang and bridge");
def->tooltip = L("Enable this option to optimize part cooling fan speed for overhang and bridge to get better cooling");
def->label = L("Force cooling for overhangs and bridges");
def->tooltip = L("Enable this option to allow adjustment of the part cooling fan speed for specifically for overhangs, internal and external "
"bridges. Setting the fan speed specifically for these features can improve overall print quality and reduce warping.");
def->mode = comSimple;
def->set_default_value(new ConfigOptionBools{ true });
def = this->add("overhang_fan_speed", coInts);
def->label = L("Fan speed for overhang");
def->tooltip = L("Force part cooling fan to be this speed when printing bridge or overhang wall which has large overhang degree. "
"Forcing cooling for overhang and bridge can get better quality for these part");
def->label = L("Overhangs and external bridges fan speed");
def->tooltip = L("Use this part cooling fan speed when printing bridges or overhang walls with an overhang threshold that exceeds "
"the value set in the 'Overhangs cooling threshold' parameter above. Increasing the cooling specifically for overhangs "
"and bridges can improve the overall print quality of these features.\n\n"
"Please note, this fan speed is clamped on the lower end by the minimum fan speed threshold set above. It is also adjusted "
"upwards up to the maximum fan speed threshold when the minimum layer time threshold is not met.");
def->sidetext = L("%");
def->min = 0;
def->max = 100;
@ -924,10 +928,10 @@ void PrintConfigDef::init_fff_params()
def->set_default_value(new ConfigOptionInts { 100 });
def = this->add("overhang_fan_threshold", coEnums);
def->label = L("Cooling overhang threshold");
def->tooltip = L("Force cooling fan to be specific speed when overhang degree of printed part exceeds this value. "
"Expressed as percentage which indicates how much width of the line without support from lower layer. "
"0% means forcing cooling for all outer wall no matter how much overhang degree");
def->label = L("Overhang cooling activation threshold");
def->tooltip = L("When the overhang exceeds this specified threshold, force the cooling fan to run at the 'Overhang Fan Speed' set below. "
"This threshold is expressed as a percentage, indicating the portion of each line's width that is unsupported by the layer "
"beneath it. Setting this value to 0% forces the cooling fan to run for all outer walls, regardless of the overhang degree.");
def->sidetext = "";
def->enum_keys_map = &ConfigOptionEnum<OverhangFanThreshold>::get_enum_values();
def->mode = comAdvanced;
@ -2586,15 +2590,27 @@ void PrintConfigDef::init_fff_params()
def = this->add("support_material_interface_fan_speed", coInts);
def->label = L("Support interface fan speed");
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 this override."
"\nCan only be overridden by disable_fan_first_layers.");
def->tooltip = L("This part cooling fan speed is applied when printing support interfaces. Setting this parameter to a higher than regular speed "
" reduces the layer binding strength between supports and the supported part, making them easier to separate."
"\nSet to -1 to disable it."
"\nThis setting is overridden by disable_fan_first_layers.");
def->sidetext = L("%");
def->min = -1;
def->max = 100;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInts{ -1 });
// ORCA: Add support for separate internal bridge fan speed control
def = this->add("internal_bridge_fan_speed", coInts);
def->label = L("Internal bridges fan speed");
def->tooltip = L("The part cooling fan speed used for all internal bridges. Set to -1 to use the overhang fan speed settings instead.\n\n"
"Reducing the internal bridges fan speed, compared to your regular fan speed, can help reduce part warping due to excessive "
"cooling applied over a large surface for a prolonged period of time.");
def->sidetext = L("%");
def->min = -1;
def->max = 100;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInts{ -1 });
def = this->add("fuzzy_skin", coEnum);
def->label = L("Fuzzy Skin");

View file

@ -1331,6 +1331,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionBool, gcode_comments))
((ConfigOptionInt, slow_down_layers))
((ConfigOptionInts, support_material_interface_fan_speed))
((ConfigOptionInts, internal_bridge_fan_speed)) // ORCA: Add support for separate internal bridge fan speed control
// Orca: notes for profiles from PrusaSlicer
((ConfigOptionStrings, filament_notes))
((ConfigOptionString, notes))

View file

@ -3445,6 +3445,7 @@ void TabFilament::build()
optgroup->append_single_option_line("enable_overhang_bridge_fan", "auto-cooling");
optgroup->append_single_option_line("overhang_fan_threshold", "auto-cooling");
optgroup->append_single_option_line("overhang_fan_speed", "auto-cooling");
optgroup->append_single_option_line("internal_bridge_fan_speed"); // ORCA: Add support for separate internal bridge fan speed control
optgroup->append_single_option_line("support_material_interface_fan_speed");
optgroup = page->new_optgroup(L("Auxiliary part cooling fan"), L"param_cooling_aux_fan");
@ -3605,7 +3606,7 @@ void TabFilament::toggle_options()
auto cfg = m_preset_bundle->printers.get_edited_preset().config;
if (m_active_page->title() == L("Cooling")) {
bool has_enable_overhang_bridge_fan = m_config->opt_bool("enable_overhang_bridge_fan", 0);
for (auto el : {"overhang_fan_speed", "overhang_fan_threshold"})
for (auto el : {"overhang_fan_speed", "overhang_fan_threshold", "internal_bridge_fan_speed"}) // ORCA: Add support for separate internal bridge fan speed control
toggle_option(el, has_enable_overhang_bridge_fan);
toggle_option("additional_cooling_fan_speed", cfg.opt_bool("auxiliary_fan"));