diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index b56ebbb538..7b642cc355 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -532,6 +532,11 @@ //#define USE_OCR2A_AS_TOP #endif +/** + * Use one of the PWM fans as a redundant part-cooling fan + */ +//#define REDUNDANT_PART_COOLING_FAN 2 // Index of the fan to sync with FAN 0. + // @section extruder /** diff --git a/Marlin/src/gcode/temp/M106_M107.cpp b/Marlin/src/gcode/temp/M106_M107.cpp index dcb0d34ffe..3f85c53d78 100644 --- a/Marlin/src/gcode/temp/M106_M107.cpp +++ b/Marlin/src/gcode/temp/M106_M107.cpp @@ -60,39 +60,40 @@ */ void GcodeSuite::M106() { const uint8_t pfan = parser.byteval('P', _ALT_P); + if (pfan >= _CNT_P) return; + #if REDUNDANT_PART_COOLING_FAN + if (pfan == REDUNDANT_PART_COOLING_FAN) return; + #endif - if (pfan < _CNT_P) { + #if ENABLED(EXTRA_FAN_SPEED) + const uint16_t t = parser.intval('T'); + if (t > 0) return thermalManager.set_temp_fan_speed(pfan, t); + #endif - #if ENABLED(EXTRA_FAN_SPEED) - const uint16_t t = parser.intval('T'); - if (t > 0) return thermalManager.set_temp_fan_speed(pfan, t); - #endif + const uint16_t dspeed = parser.seen_test('A') ? thermalManager.fan_speed[active_extruder] : 255; - const uint16_t dspeed = parser.seen_test('A') ? thermalManager.fan_speed[active_extruder] : 255; + uint16_t speed = dspeed; - uint16_t speed = dspeed; + // Accept 'I' if temperature presets are defined + #if PREHEAT_COUNT + const bool got_preset = parser.seenval('I'); + if (got_preset) speed = ui.material_preset[_MIN(parser.value_byte(), PREHEAT_COUNT - 1)].fan_speed; + #else + constexpr bool got_preset = false; + #endif - // Accept 'I' if temperature presets are defined - #if PREHEAT_COUNT - const bool got_preset = parser.seenval('I'); - if (got_preset) speed = ui.material_preset[_MIN(parser.value_byte(), PREHEAT_COUNT - 1)].fan_speed; - #else - constexpr bool got_preset = false; - #endif + if (!got_preset && parser.seenval('S')) + speed = parser.value_ushort(); - if (!got_preset && parser.seenval('S')) - speed = parser.value_ushort(); + TERN_(FOAMCUTTER_XYUV, speed *= 2.55); // Get command in % of max heat - TERN_(FOAMCUTTER_XYUV, speed *= 2.55); // Get command in % of max heat + // Set speed, with constraint + thermalManager.set_fan_speed(pfan, speed); - // Set speed, with constraint - thermalManager.set_fan_speed(pfan, speed); + TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_FLAG_SYNC_FANS)); - TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_FLAG_SYNC_FANS)); - - if (TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())) // pfan == 0 when duplicating - thermalManager.set_fan_speed(1 - pfan, speed); - } + if (TERN0(DUAL_X_CARRIAGE, idex_is_duplicating())) // pfan == 0 when duplicating + thermalManager.set_fan_speed(1 - pfan, speed); } /** @@ -101,6 +102,9 @@ void GcodeSuite::M106() { void GcodeSuite::M107() { const uint8_t pfan = parser.byteval('P', _ALT_P); if (pfan >= _CNT_P) return; + #if REDUNDANT_PART_COOLING_FAN + if (pfan == REDUNDANT_PART_COOLING_FAN) return; + #endif thermalManager.set_fan_speed(pfan, 0); diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index ae3d639957..7a178db3aa 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -1890,6 +1890,14 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #endif #endif +#ifdef REDUNDANT_PART_COOLING_FAN + #if FAN_COUNT < 2 + #error "REDUNDANT_PART_COOLING_FAN requires a board with at least two PWM fans." + #else + static_assert(WITHIN(REDUNDANT_PART_COOLING_FAN, 1, FAN_COUNT - 1), "REDUNDANT_PART_COOLING_FAN must be between 1 and " STRINGIFY(DECREMENT(FAN_COUNT)) "."); + #endif +#endif + /** * Case Light requirements */ diff --git a/Marlin/src/lcd/menu/menu_temperature.cpp b/Marlin/src/lcd/menu/menu_temperature.cpp index 33a3d2f445..96e6ee5f8e 100644 --- a/Marlin/src/lcd/menu/menu_temperature.cpp +++ b/Marlin/src/lcd/menu/menu_temperature.cpp @@ -57,8 +57,14 @@ void Temperature::lcd_preheat(const uint8_t e, const int8_t indh, const int8_t i if (indb >= 0 && ui.material_preset[indb].bed_temp > 0) setTargetBed(ui.material_preset[indb].bed_temp); #endif #if HAS_FAN - if (indh >= 0) - set_fan_speed(active_extruder < (FAN_COUNT) ? active_extruder : 0, ui.material_preset[indh].fan_speed); + if (indh >= 0) { + const uint8_t fan_index = active_extruder < (FAN_COUNT) ? active_extruder : 0; + if (true + #if REDUNDANT_PART_COOLING_FAN + && fan_index != REDUNDANT_PART_COOLING_FAN + #endif + ) set_fan_speed(fan_index, ui.material_preset[indh].fan_speed); + } #endif ui.return_to_status(); } @@ -215,37 +221,37 @@ void menu_temperature() { #if HAS_FAN0 _FAN_EDIT_ITEMS(0,FIRST_FAN_SPEED); #endif - #if HAS_FAN1 + #if HAS_FAN1 && REDUNDANT_PART_COOLING_FAN != 1 FAN_EDIT_ITEMS(1); #elif SNFAN(1) singlenozzle_item(1); #endif - #if HAS_FAN2 + #if HAS_FAN2 && REDUNDANT_PART_COOLING_FAN != 2 FAN_EDIT_ITEMS(2); #elif SNFAN(2) singlenozzle_item(2); #endif - #if HAS_FAN3 + #if HAS_FAN3 && REDUNDANT_PART_COOLING_FAN != 3 FAN_EDIT_ITEMS(3); #elif SNFAN(3) singlenozzle_item(3); #endif - #if HAS_FAN4 + #if HAS_FAN4 && REDUNDANT_PART_COOLING_FAN != 4 FAN_EDIT_ITEMS(4); #elif SNFAN(4) singlenozzle_item(4); #endif - #if HAS_FAN5 + #if HAS_FAN5 && REDUNDANT_PART_COOLING_FAN != 5 FAN_EDIT_ITEMS(5); #elif SNFAN(5) singlenozzle_item(5); #endif - #if HAS_FAN6 + #if HAS_FAN6 && REDUNDANT_PART_COOLING_FAN != 6 FAN_EDIT_ITEMS(6); #elif SNFAN(6) singlenozzle_item(6); #endif - #if HAS_FAN7 + #if HAS_FAN7 && REDUNDANT_PART_COOLING_FAN != 7 FAN_EDIT_ITEMS(7); #elif SNFAN(7) singlenozzle_item(7); diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index e7d4ece721..9274d0631e 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -333,6 +333,9 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY, if (fan >= FAN_COUNT) return; fan_speed[fan] = speed; + #if REDUNDANT_PART_COOLING_FAN + if (fan == 0) fan_speed[REDUNDANT_PART_COOLING_FAN] = speed; + #endif TERN_(REPORT_FAN_CHANGE, report_fan_speed(fan)); } diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index 3ddb68fe88..0932388969 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -68,7 +68,8 @@ exec_test $1 $2 "Multiple runout sensors (x5) | Distinct runout states" "$3" # restore_configs opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO MIXING_STEPPERS 5 LCD_LANGUAGE ru \ - NUM_RUNOUT_SENSORS E_STEPPERS FIL_RUNOUT2_PIN 16 FIL_RUNOUT3_PIN 17 FIL_RUNOUT4_PIN 4 FIL_RUNOUT5_PIN 5 + NUM_RUNOUT_SENSORS E_STEPPERS REDUNDANT_PART_COOLING_FAN 1 \ + FIL_RUNOUT2_PIN 16 FIL_RUNOUT3_PIN 17 FIL_RUNOUT4_PIN 4 FIL_RUNOUT5_PIN 5 opt_enable MIXING_EXTRUDER GRADIENT_MIX GRADIENT_VTOOL CR10_STOCKDISPLAY \ USE_CONTROLLER_FAN CONTROLLER_FAN_EDITABLE CONTROLLER_FAN_IGNORE_Z \ FILAMENT_RUNOUT_SENSOR ADVANCED_PAUSE_FEATURE NOZZLE_PARK_FEATURE