diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 6d672e3b8c..17d5efc6eb 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -989,7 +989,7 @@ void Marlin::stop() { print_job_timer.stop(); #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) - thermalManager.set_fans_paused(false); // Un-pause fans for safety + Fan::all_pause(false); // Un-pause fans for safety #endif if (!isStopped()) { diff --git a/Marlin/src/feature/controllerfan.cpp b/Marlin/src/feature/controllerfan.cpp index 0636402136..b31640be2f 100644 --- a/Marlin/src/feature/controllerfan.cpp +++ b/Marlin/src/feature/controllerfan.cpp @@ -71,98 +71,99 @@ void ControllerFan::setup() { init(); } -void ControllerFan::set_fan_speed(const uint8_t s) { - speed = s < (CONTROLLERFAN_SPEED_MIN) ? 0 : s; // Fan OFF below minimum -} - void ControllerFan::update() { - static millis_t lastComponentOn = 0, // Last time a stepper, heater, etc. was turned on - nextFanCheck = 0; // Last time the state was checked const millis_t ms = millis(); - if (ELAPSED(ms, nextFanCheck)) { - nextFanCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s - /** - * If any triggers for the controller fan are true... - * - At least one stepper driver is enabled - * - The heated bed (MOSFET) is enabled - * - TEMP_SENSOR_BOARD is reporting >= CONTROLLER_FAN_MIN_BOARD_TEMP - * - TEMP_SENSOR_SOC is reporting >= CONTROLLER_FAN_MIN_SOC_TEMP - */ - const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), (ena_mask_t)~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS))); - if ( (stepper.axis_enabled.bits & axis_mask) - #if ALL(HAS_HEATED_BED, CONTROLLER_FAN_BED_HEATING) - || thermalManager.temp_bed.soft_pwm_amount > 0 - #endif - #ifdef CONTROLLER_FAN_MIN_BOARD_TEMP - || thermalManager.wholeDegBoard() >= CONTROLLER_FAN_MIN_BOARD_TEMP - #endif - #ifdef CONTROLLER_FAN_MIN_SOC_TEMP - || thermalManager.wholeDegSoc() >= CONTROLLER_FAN_MIN_SOC_TEMP - #endif - ) lastComponentOn = ms; //... set time to NOW so the fan will turn on + static millis_t nextFanCheck = 0; // Last time the state was checked + if (PENDING(ms, nextFanCheck)) return; + nextFanCheck = ms + 2500UL; // Not a time critical function, so only check every 2.5s - /** - * Fan Settings. Set fan > 0: - * - If AutoMode is on and hot components have been powered for CONTROLLERFAN_IDLE_TIME seconds. - * - If System is on idle and idle fan speed settings is activated. - */ - set_fan_speed( - settings.auto_mode && lastComponentOn && PENDING(ms, lastComponentOn, SEC_TO_MS(settings.duration)) - ? settings.active_speed : settings.idle_speed - ); - - speed = CALC_FAN_SPEED(speed); - - #if FAN_KICKSTART_TIME - static millis_t fan_kick_end = 0; - if (speed > FAN_OFF_PWM) { - if (!fan_kick_end) { - fan_kick_end = ms + FAN_KICKSTART_TIME; // May be longer based on slow update interval for controller fn check. Sets minimum - speed = FAN_KICKSTART_POWER; - } - else if (PENDING(ms, fan_kick_end)) - speed = FAN_KICKSTART_POWER; - } - else - fan_kick_end = 0; + /** + * If any triggers for the controller fan are true... + * - At least one stepper driver is enabled + * - The heated bed (MOSFET) is enabled + * - TEMP_SENSOR_BOARD is reporting >= CONTROLLER_FAN_MIN_BOARD_TEMP + * - TEMP_SENSOR_SOC is reporting >= CONTROLLER_FAN_MIN_SOC_TEMP + */ + static millis_t lastComponentOn = 0; // Last time a stepper, heater, etc. was turned on + const ena_mask_t axis_mask = TERN(CONTROLLER_FAN_USE_Z_ONLY, _BV(Z_AXIS), (ena_mask_t)~TERN0(CONTROLLER_FAN_IGNORE_Z, _BV(Z_AXIS))); + if ( (stepper.axis_enabled.bits & axis_mask) + #if ALL(HAS_HEATED_BED, CONTROLLER_FAN_BED_HEATING) + || thermalManager.temp_bed.soft_pwm_amount > 0 #endif + #ifdef CONTROLLER_FAN_MIN_BOARD_TEMP + || thermalManager.wholeDegBoard() >= CONTROLLER_FAN_MIN_BOARD_TEMP + #endif + #ifdef CONTROLLER_FAN_MIN_SOC_TEMP + || thermalManager.wholeDegSoc() >= CONTROLLER_FAN_MIN_SOC_TEMP + #endif + ) lastComponentOn = ms; //... set time to NOW so the fan will turn on + + /** + * Fan Settings. Set fan > 0: + * - If AutoMode is on and hot components have been powered for CONTROLLERFAN_IDLE_TIME seconds. + * - If System is on idle and idle fan speed settings is activated. + */ + uint8_t s = settings.auto_mode && lastComponentOn && PENDING(ms, lastComponentOn, SEC_TO_MS(settings.duration)) + ? settings.active_speed + : settings.idle_speed; + + // Convert 1-255 to the MIN-MAX PWM range + s = CALC_FAN_SPEED(s); + + // When the fan first starts up it can run at high power for a short period + #if FAN_KICKSTART_TIME + + static millis_t kick_end_ms = 0; + + if (s > FAN_OFF_PWM) { // Is the fan turned on? + if (!kick_end_ms) { // No kickstart yet? + kick_end_ms = ms + FAN_KICKSTART_TIME; // Set a future time at which to stop + s = FAN_KICKSTART_POWER; // Override the power + } + else if (PENDING(ms, kick_end_ms)) // Still waiting for end of kickstart time? + s = FAN_KICKSTART_POWER; // Override the power + } + else + kick_end_ms = 0; // Reset kick_end_ms for kickstart on next enable + + #endif // FAN_KICKSTART_TIME + + #if ENABLED(FAN_SOFT_PWM) + soft_pwm_speed = speed >> 1; // Controller Fan Soft PWM uses 0-127 as 0-100% so cut the 0-255 range in half. + #else #define SET_CONTROLLER_FAN(N) do { \ if (PWM_PIN(CONTROLLER_FAN##N##_PIN)) hal.set_pwm_duty(pin_t(CONTROLLER_FAN##N##_PIN), speed); \ else WRITE(CONTROLLER_FAN##N##_PIN, speed > 0);\ } while (0) - #if ENABLED(FAN_SOFT_PWM) - soft_pwm_speed = speed >> 1; // Controller Fan Soft PWM uses 0-127 as 0-100% so cut the 0-255 range in half. - #else - SET_CONTROLLER_FAN(); - #if PIN_EXISTS(CONTROLLER_FAN2) - SET_CONTROLLER_FAN(2); - #endif - #if PIN_EXISTS(CONTROLLER_FAN3) - SET_CONTROLLER_FAN(3); - #endif - #if PIN_EXISTS(CONTROLLER_FAN4) - SET_CONTROLLER_FAN(4); - #endif - #if PIN_EXISTS(CONTROLLER_FAN5) - SET_CONTROLLER_FAN(5); - #endif - #if PIN_EXISTS(CONTROLLER_FAN6) - SET_CONTROLLER_FAN(6); - #endif - #if PIN_EXISTS(CONTROLLER_FAN7) - SET_CONTROLLER_FAN(7); - #endif - #if PIN_EXISTS(CONTROLLER_FAN8) - SET_CONTROLLER_FAN(8); - #endif - #if PIN_EXISTS(CONTROLLER_FAN9) - SET_CONTROLLER_FAN(9); - #endif + SET_CONTROLLER_FAN(); + #if PIN_EXISTS(CONTROLLER_FAN2) + SET_CONTROLLER_FAN(2); #endif - } + #if PIN_EXISTS(CONTROLLER_FAN3) + SET_CONTROLLER_FAN(3); + #endif + #if PIN_EXISTS(CONTROLLER_FAN4) + SET_CONTROLLER_FAN(4); + #endif + #if PIN_EXISTS(CONTROLLER_FAN5) + SET_CONTROLLER_FAN(5); + #endif + #if PIN_EXISTS(CONTROLLER_FAN6) + SET_CONTROLLER_FAN(6); + #endif + #if PIN_EXISTS(CONTROLLER_FAN7) + SET_CONTROLLER_FAN(7); + #endif + #if PIN_EXISTS(CONTROLLER_FAN8) + SET_CONTROLLER_FAN(8); + #endif + #if PIN_EXISTS(CONTROLLER_FAN9) + SET_CONTROLLER_FAN(9); + #endif + #endif } #endif // USE_CONTROLLER_FAN diff --git a/Marlin/src/feature/controllerfan.h b/Marlin/src/feature/controllerfan.h index 68502afa66..ac422f015f 100644 --- a/Marlin/src/feature/controllerfan.h +++ b/Marlin/src/feature/controllerfan.h @@ -52,7 +52,8 @@ static constexpr controllerFan_settings_t controllerFan_defaults = { class ControllerFan { private: static uint8_t speed; - static void set_fan_speed(const uint8_t s); + static uint8_t limited_fan_speed(const uint8_t s) { return s < (CONTROLLERFAN_SPEED_MIN) ? 0 : s; } // Fan OFF below minimum + static void set_fan_speed(const uint8_t s) { speed = limited_fan_speed(s); } public: #if ENABLED(CONTROLLER_FAN_EDITABLE) diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 025bcb8383..db237dada0 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -462,7 +462,7 @@ bool pause_print(const float retract, const xyz_pos_t &park_point, const bool sh planner.synchronize(); #if ALL(ADVANCED_PAUSE_FANS_PAUSE, HAS_FAN) - thermalManager.set_fans_paused(true); + Fan::all_pause(true); #endif // Initial retract before move to filament change position @@ -763,8 +763,8 @@ void resume_print( } #endif - #if ENABLED(ADVANCED_PAUSE_FANS_PAUSE) && HAS_FAN - thermalManager.set_fans_paused(false); + #if ALL(ADVANCED_PAUSE_FANS_PAUSE, HAS_FAN) + Fan::all_pause(false); #endif TERN_(HAS_FILAMENT_SENSOR, runout.reset()); diff --git a/Marlin/src/feature/power.cpp b/Marlin/src/feature/power.cpp index 2068558fe9..b877d460ea 100644 --- a/Marlin/src/feature/power.cpp +++ b/Marlin/src/feature/power.cpp @@ -210,9 +210,8 @@ void Power::power_off() { if (marlin.printJobOngoing() || marlin.printingIsPaused()) return true; - #if ENABLED(AUTO_POWER_FANS) - FANS_LOOP(i) if (thermalManager.fan_speed[i]) return true; - #endif + // Do any fans need power? + if (TERN0(AUTO_POWER_FANS, Fan::is_power_needed())) return true; #if ENABLED(AUTO_POWER_E_FANS) HOTEND_LOOP() if (thermalManager.autofan_speed[e]) return true; diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 0dd19808bc..106e346e7c 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -246,7 +246,9 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW TERN_(HAS_HEATED_CHAMBER, info.target_temperature_chamber = thermalManager.degTargetChamber()); - TERN_(HAS_FAN, COPY(info.fan_speed, thermalManager.fan_speed)); + #if HAS_FAN + FANS_LOOP(f) info.fan_speed[f] = fans[f].speed; + #endif #if HAS_LEVELING info.flag.leveling = planner.leveling_active; diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp index 717b0695a4..fbb40ef755 100644 --- a/Marlin/src/gcode/control/M42.cpp +++ b/Marlin/src/gcode/control/M42.cpp @@ -87,7 +87,7 @@ void GcodeSuite::M42() { #if HAS_FAN switch (pin) { - #define _CASE(N) case FAN##N##_PIN: thermalManager.fan_speed[N] = pin_status; return; + #define _CASE(N) case FAN##N##_PIN: fans[N].speed = pin_status; return; REPEAT(FAN_COUNT, _CASE) } #endif diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp index a7653a4037..8fb8be8c37 100644 --- a/Marlin/src/gcode/control/M80_M81.cpp +++ b/Marlin/src/gcode/control/M80_M81.cpp @@ -84,8 +84,7 @@ void GcodeSuite::M81() { print_job_timer.stop(); #if ALL(HAS_FAN, PROBING_FANS_OFF) - thermalManager.fans_paused = false; - ZERO(thermalManager.saved_fan_speed); + Fan::power_off(); #endif TERN_(POWER_LOSS_RECOVERY, recovery.purge()); // Clear PLR on intentional shutdown diff --git a/Marlin/src/gcode/temp/M106_M107.cpp b/Marlin/src/gcode/temp/M106_M107.cpp index dc0c3d6b27..bdcbda9169 100644 --- a/Marlin/src/gcode/temp/M106_M107.cpp +++ b/Marlin/src/gcode/temp/M106_M107.cpp @@ -71,7 +71,7 @@ void GcodeSuite::M106() { } #endif - const uint16_t dspeed = parser.seen_test('A') ? thermalManager.fan_speed[active_extruder] : 255; + const uint16_t dspeed = parser.seen_test('A') ? fans[active_extruder].speed : 255; uint16_t speed = dspeed; diff --git a/Marlin/src/inc/Conditionals-5-post.h b/Marlin/src/inc/Conditionals-5-post.h index 024eb42f51..d75d77dab8 100644 --- a/Marlin/src/inc/Conditionals-5-post.h +++ b/Marlin/src/inc/Conditionals-5-post.h @@ -2973,6 +2973,9 @@ #if FAN_COUNT > 0 #define HAS_FAN 1 +#else + #undef FAN_SOFT_PWM + #undef FAN_SOFT_PWM_REQUIRED #endif #if PIN_EXISTS(FANMUX0) diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 5856723c77..34c6d8ea8b 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -981,9 +981,9 @@ static_assert(COUNT(arm) == LOGICAL_AXES, "AXIS_RELATIVE_MODES must contain " _L #if HAS_FANMUX && !HAS_FAN0 #error "FAN0_PIN must be defined to use Fan Multiplexing." #elif PIN_EXISTS(FANMUX1) && !PIN_EXISTS(FANMUX0) - #error "FANMUX0_PIN must be set before FANMUX1_PIN can be set." + #error "FANMUX0_PIN must be defined before FANMUX1_PIN can be defined." #elif PIN_EXISTS(FANMUX2) && !PINS_EXIST(FANMUX0, FANMUX1) - #error "FANMUX0_PIN and FANMUX1_PIN must be set before FANMUX2_PIN can be set." + #error "FANMUX0_PIN and FANMUX1_PIN must be defined before FANMUX2_PIN can be defined." #endif // PID Fan Scaling requires a fan diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index 81063d5e2e..482bd7df3e 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -1128,15 +1128,15 @@ void MarlinUI::draw_status_screen() { #if HAS_FAN0 if (true #if ALL(HAS_EXTRUDERS, ADAPTIVE_FAN_SLOWING) - && (blink || thermalManager.fan_speed_scaler[0] < 128) + && (blink || fans[0].speed_scaler < 128) #endif ) { - uint16_t spd = thermalManager.fan_speed[0]; + uint16_t spd = fans[0].speed; if (blink) c = 'F'; #if ENABLED(ADAPTIVE_FAN_SLOWING) - else { c = '*'; spd = thermalManager.scaledFanSpeed(0, spd); } + else { c = '*'; spd = fans[0].scaled_speed(spd); } #endif - pct = thermalManager.pwmToPercent(spd); + pct = Fan::pwmToPercent(spd); } else #endif @@ -1390,14 +1390,14 @@ void MarlinUI::draw_status_screen() { if (TERN0(HAS_HOTEND, thermalManager.degTargetHotend(0) > 0)) leds |= LED_B; #if HAS_FAN - if ( TERN0(HAS_FAN0, thermalManager.fan_speed[0]) - || TERN0(HAS_FAN1, thermalManager.fan_speed[1]) - || TERN0(HAS_FAN2, thermalManager.fan_speed[2]) - || TERN0(HAS_FAN3, thermalManager.fan_speed[3]) - || TERN0(HAS_FAN4, thermalManager.fan_speed[4]) - || TERN0(HAS_FAN5, thermalManager.fan_speed[5]) - || TERN0(HAS_FAN6, thermalManager.fan_speed[6]) - || TERN0(HAS_FAN7, thermalManager.fan_speed[7]) + if ( TERN0(HAS_FAN0, fans[0].speed) + || TERN0(HAS_FAN1, fans[1].speed) + || TERN0(HAS_FAN2, fans[2].speed) + || TERN0(HAS_FAN3, fans[3].speed) + || TERN0(HAS_FAN4, fans[4].speed) + || TERN0(HAS_FAN5, fans[5].speed) + || TERN0(HAS_FAN6, fans[6].speed) + || TERN0(HAS_FAN7, fans[7].speed) ) leds |= LED_C; #endif // HAS_FAN diff --git a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp index cdb18a74b7..10476c6cb0 100644 --- a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp +++ b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp @@ -906,11 +906,11 @@ void MarlinUI::draw_status_screen() { #endif #if HAS_FAN - uint16_t spd = thermalManager.fan_speed[0]; + uint16_t spd = fans[0].speed; #if ENABLED(ADAPTIVE_FAN_SLOWING) - if (!blink) spd = thermalManager.scaledFanSpeed(0, spd); + if (!blink) spd = fans[0].scaled_speed(spd); #endif - uint16_t per = thermalManager.pwmToPercent(spd); + const uint16_t pct = Fan::pwmToPercent(spd); #if HOTENDS < 2 #define FANX 11 @@ -920,9 +920,9 @@ void MarlinUI::draw_status_screen() { lcd_moveto(FANX, 5); lcd_put_u8str(F("FAN")); lcd_moveto(FANX + 1, 6); lcd.write('%'); lcd_moveto(FANX, 7); - lcd.print(i16tostr3rj(per)); + lcd.print(i16tostr3rj(pct)); - if (TERN0(HAS_FAN0, thermalManager.fan_speed[0]) || TERN0(HAS_FAN1, thermalManager.fan_speed[1]) || TERN0(HAS_FAN2, thermalManager.fan_speed[2])) + if (TERN0(HAS_FAN0, fans[0].speed) || TERN0(HAS_FAN1, fans[1].speed) || TERN0(HAS_FAN2, fans[2].speed)) picBits |= ICON_FAN; else picBits &= ~ICON_FAN; diff --git a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp index 7fd3052772..c8606255ec 100644 --- a/Marlin/src/lcd/dogm/status_screen_DOGM.cpp +++ b/Marlin/src/lcd/dogm/status_screen_DOGM.cpp @@ -674,7 +674,7 @@ void MarlinUI::draw_status_screen() { static uint8_t fan_frame; if (old_blink != blink) { old_blink = blink; - if (!thermalManager.fan_speed[0] || ++fan_frame >= STATUS_FAN_FRAMES) fan_frame = 0; + if (!fans[0].speed || ++fan_frame >= STATUS_FAN_FRAMES) fan_frame = 0; } #endif if (PAGE_CONTAINS(STATUS_FAN_Y, STATUS_FAN_Y + STATUS_FAN_HEIGHT - 1)) @@ -686,7 +686,7 @@ void MarlinUI::draw_status_screen() { fan_frame == 3 ? status_fan3_bmp : #endif #elif STATUS_FAN_FRAMES > 1 - blink && thermalManager.fan_speed[0] ? status_fan1_bmp : + blink && fans[0].speed ? status_fan1_bmp : #endif status_fan0_bmp ); @@ -758,15 +758,15 @@ void MarlinUI::draw_status_screen() { #if DO_DRAW_FAN if (PAGE_CONTAINS(STATUS_FAN_TEXT_Y - INFO_FONT_ASCENT, STATUS_FAN_TEXT_Y - 1)) { char c = '%'; - uint16_t spd = thermalManager.fan_speed[0]; + uint16_t spd = fans[0].speed; if (spd) { #if ENABLED(ADAPTIVE_FAN_SLOWING) - if (!blink && thermalManager.fan_speed_scaler[0] < 128) { - spd = thermalManager.scaledFanSpeed(0, spd); + if (!blink && fans[0].speed_scaler < 128) { + spd = fans[0].scaled_speed(spd); c = '*'; } #endif - lcd_put_u8str(STATUS_FAN_TEXT_X, STATUS_FAN_TEXT_Y, i16tostr3rj(thermalManager.pwmToPercent(spd))); + lcd_put_u8str(STATUS_FAN_TEXT_X, STATUS_FAN_TEXT_Y, i16tostr3rj(Fan::pwmToPercent(spd))); lcd_put_lchar(c); } } diff --git a/Marlin/src/lcd/dogm/status_screen_lite_ST7920.cpp b/Marlin/src/lcd/dogm/status_screen_lite_ST7920.cpp index ac7941f844..cc408c7136 100644 --- a/Marlin/src/lcd/dogm/status_screen_lite_ST7920.cpp +++ b/Marlin/src/lcd/dogm/status_screen_lite_ST7920.cpp @@ -637,7 +637,7 @@ bool ST7920_Lite_Status_Screen::indicators_changed() { // them only during blinks we gain a bit of stability. const bool blink = ui.get_blink(); const uint16_t feedrate_perc = feedrate_percentage; - const uint16_t fs = thermalManager.scaledFanSpeed(0); + const uint16_t fs = fans[0].scaled_speed(); const celsius_t extruder_1_target = thermalManager.degTargetHotend(0); #if HAS_MULTI_HOTEND const celsius_t extruder_2_target = thermalManager.degTargetHotend(1); @@ -819,12 +819,12 @@ void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) { TERN_(HAS_HEATED_BED, draw_bed_temp(bed_temp, bed_target, forceUpdate)); // Update the fan and bed animations - uint8_t spd = thermalManager.fan_speed[0]; + uint8_t spd = fans[0].speed; #if ENABLED(ADAPTIVE_FAN_SLOWING) - if (!blink && thermalManager.fan_speed_scaler[0] < 128) - spd = thermalManager.scaledFanSpeed(0, spd); + if (!blink && fans[0].speed_scaler < 128) + spd = fans[0].scaled_speed(spd); #endif - draw_fan_speed(thermalManager.pwmToPercent(spd)); + draw_fan_speed(Fan::pwmToPercent(spd)); if (spd) draw_fan_icon(blink); TERN_(HAS_HEATED_BED, draw_heat_icon(bed_target > 0 && blink, bed_target > 0)); diff --git a/Marlin/src/lcd/dwin/creality/dwin.cpp b/Marlin/src/lcd/dwin/creality/dwin.cpp index 875dfd5fd1..4240659af8 100644 --- a/Marlin/src/lcd/dwin/creality/dwin.cpp +++ b/Marlin/src/lcd/dwin/creality/dwin.cpp @@ -984,7 +984,7 @@ void drawTuneMenu() { #endif #if HAS_FAN drawMenuLine(TUNE_CASE_FAN, ICON_FanSpeed); - drawEditInteger3(TUNE_CASE_FAN, thermalManager.fan_speed[0]); + drawEditInteger3(TUNE_CASE_FAN, fans[0].speed); #endif #if HAS_ZOFFSET_ITEM drawMenuLine(TUNE_CASE_ZOFF, ICON_Zoffset); @@ -1713,8 +1713,8 @@ void updateVariable() { #endif #if HAS_FAN static uint8_t _fanspeed = 0; - const bool _new_fanspeed = _fanspeed != thermalManager.fan_speed[0]; - if (_new_fanspeed) _fanspeed = thermalManager.fan_speed[0]; + const bool _new_fanspeed = _fanspeed != fans[0].speed; + if (_new_fanspeed) _fanspeed = fans[0].speed; #endif if (checkkey == ID_Tune) { @@ -1775,7 +1775,7 @@ void updateVariable() { #if HAS_FAN if (_new_fanspeed) { - _fanspeed = thermalManager.fan_speed[0]; + _fanspeed = fans[0].speed; drawStatInt(195 + 2 * STAT_CHR_W, 384, _fanspeed); } #endif @@ -2026,7 +2026,7 @@ void drawStatusArea(const bool with_update) { #if HAS_FAN dwinIconShow(ICON, ICON_FanSpeed, 187, 383); - drawStatInt(195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + drawStatInt(195 + 2 * STAT_CHR_W, 384, fans[0].speed); #endif #if HAS_ZOFFSET_ITEM @@ -2278,7 +2278,7 @@ void hmiSelectFile() { // All fans on for Ender-3 v2 ? // The slicer should manage this for us. //for (uint8_t i = 0; i < FAN_COUNT; i++) - // thermalManager.fan_speed[i] = 255; + // fans[i].speed = 255; #endif _card_percent = 0; @@ -2873,7 +2873,7 @@ void drawTemperatureMenu() { #endif #if HAS_FAN _TMENU_ICON(TEMP_CASE_FAN); - drawEditInteger3(i, thermalManager.fan_speed[0]); + drawEditInteger3(i, fans[0].speed); #endif #if HAS_PREHEAT // PLA/ABS items have submenus @@ -3104,7 +3104,7 @@ void hmiTemperature() { #if HAS_FAN case TEMP_CASE_FAN: checkkey = ID_FanSpeed; - hmiValues.fanSpeed = thermalManager.fan_speed[0]; + hmiValues.fanSpeed = fans[0].speed; drawEditInteger3(3, hmiValues.fanSpeed, true); encoderRate.enabled = true; break; @@ -3831,7 +3831,7 @@ void hmiTune() { #if HAS_FAN case TUNE_CASE_FAN: // Fan speed checkkey = ID_FanSpeed; - hmiValues.fanSpeed = thermalManager.fan_speed[0]; + hmiValues.fanSpeed = fans[0].speed; drawEditInteger3(TUNE_CASE_FAN + MROWS - index_tune, hmiValues.fanSpeed, true); encoderRate.enabled = true; break; diff --git a/Marlin/src/lcd/dwin/jyersui/dwin.cpp b/Marlin/src/lcd/dwin/jyersui/dwin.cpp index d451526540..910e823d86 100644 --- a/Marlin/src/lcd/dwin/jyersui/dwin.cpp +++ b/Marlin/src/lcd/dwin/jyersui/dwin.cpp @@ -849,9 +849,9 @@ void JyersDWIN::drawStatusArea(const bool icons/*=false*/) { fan = -1; dwinIconShow(ICON, ICON_FanSpeed, 187, 383); } - if (thermalManager.fan_speed[0] != fan) { - fan = thermalManager.fan_speed[0]; - dwinDrawIntValue(true, true, 0, DWIN_FONT_STAT, getColor(eeprom_settings.status_area_text, COLOR_WHITE), COLOR_BG_BLACK, 3, 195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + if (fans[0].speed != fan) { + fan = fans[0].speed; + dwinDrawIntValue(true, true, 0, DWIN_FONT_STAT, getColor(eeprom_settings.status_area_text, COLOR_WHITE), COLOR_BG_BLACK, 3, 195 + 2 * STAT_CHR_W, 384, fans[0].speed); } #endif @@ -2012,10 +2012,10 @@ void JyersDWIN::menuItemHandler(const uint8_t menu, const uint8_t item, bool dra case TEMP_FAN: if (draw) { drawMenuItem(row, ICON_FanSpeed, GET_TEXT_F(MSG_FAN_SPEED)); - drawFloat(thermalManager.fan_speed[0], row, false, 1); + drawFloat(fans[0].speed, row, false, 1); } else - modifyValue(thermalManager.fan_speed[0], MIN_FAN_SPEED, MAX_FAN_SPEED, 1); + modifyValue(fans[0].speed, MIN_FAN_SPEED, MAX_FAN_SPEED, 1); break; #endif #if ANY(PIDTEMP, PIDTEMPBED) @@ -3877,10 +3877,10 @@ void JyersDWIN::menuItemHandler(const uint8_t menu, const uint8_t item, bool dra case TUNE_FAN: if (draw) { drawMenuItem(row, ICON_FanSpeed, GET_TEXT_F(MSG_FAN_SPEED)); - drawFloat(thermalManager.fan_speed[0], row, false, 1); + drawFloat(fans[0].speed, row, false, 1); } else - modifyValue(thermalManager.fan_speed[0], MIN_FAN_SPEED, MAX_FAN_SPEED, 1); + modifyValue(fans[0].speed, MIN_FAN_SPEED, MAX_FAN_SPEED, 1); break; #endif @@ -4606,7 +4606,7 @@ void JyersDWIN::printScreenControl() { #if HAS_EXTRUDERS queue.inject(TS(F("M109 S"), pausetemp)); #endif - TERN_(HAS_FAN, thermalManager.fan_speed[0] = pausefan); + TERN_(HAS_FAN, fans[0].speed = pausefan); planner.synchronize(); TERN_(HAS_MEDIA, queue.inject(FPSTR(M24_STR))); #endif @@ -4656,7 +4656,7 @@ void JyersDWIN::popupControl() { queue.inject(F("M25")); TERN_(HAS_HOTEND, pausetemp = thermalManager.degTargetHotend(0)); TERN_(HAS_HEATED_BED, pausebed = thermalManager.degTargetBed()); - TERN_(HAS_FAN, pausefan = thermalManager.fan_speed[0]); + TERN_(HAS_FAN, pausefan = fans[0].speed); thermalManager.cooldown(); #endif } @@ -5040,8 +5040,8 @@ void JyersDWIN::screenUpdate() { } #endif #if HAS_FAN - if (thermalManager.fan_speed[0] != fanspeed) { - fanspeed = thermalManager.fan_speed[0]; + if (fans[0].speed != fanspeed) { + fanspeed = fans[0].speed; if (scrollpos <= TEMP_FAN && TEMP_FAN <= scrollpos + MROWS) { if (process != Proc_Value || selection != TEMP_HOTEND - scrollpos) drawFloat(fanspeed, TEMP_FAN - scrollpos, false, 1); @@ -5069,8 +5069,8 @@ void JyersDWIN::screenUpdate() { } #endif #if HAS_FAN - if (thermalManager.fan_speed[0] != fanspeed) { - fanspeed = thermalManager.fan_speed[0]; + if (fans[0].speed != fanspeed) { + fanspeed = fans[0].speed; if (scrollpos <= TUNE_FAN && TUNE_FAN <= scrollpos + MROWS) { if (process != Proc_Value || selection != TEMP_HOTEND - scrollpos) drawFloat(fanspeed, TUNE_FAN - scrollpos, false, 1); diff --git a/Marlin/src/lcd/dwin/marlinui/ui_status_480x272.cpp b/Marlin/src/lcd/dwin/marlinui/ui_status_480x272.cpp index dbeb02dc67..fc55853786 100644 --- a/Marlin/src/lcd/dwin/marlinui/ui_status_480x272.cpp +++ b/Marlin/src/lcd/dwin/marlinui/ui_status_480x272.cpp @@ -149,10 +149,10 @@ void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink, // FORCE_INLINE void _draw_fan_status(const uint16_t x, const uint16_t y) { const uint16_t fanx = (4 * STATUS_CHR_WIDTH - STATUS_FAN_WIDTH) / 2; - const bool fan_on = !!thermalManager.scaledFanSpeed(0); + const bool fan_on = !!fans[0].scaled_speed(); if (fan_on) { dwinIconAnimation(0, fan_on, ICON, ICON_Fan0, ICON_Fan3, x + fanx, y, 25); - dwin_string.set(i8tostr3rj(thermalManager.scaledFanSpeedPercent(0))); + dwin_string.set(i8tostr3rj(fans[0].speed_pct_scaled())); dwin_string.add('%'); dwinDrawString(true, font14x28, COLOR_WHITE, COLOR_BG_BLACK, x, y + STATUS_FAN_HEIGHT, S(dwin_string.string())); } diff --git a/Marlin/src/lcd/dwin/proui/dwin.cpp b/Marlin/src/lcd/dwin/proui/dwin.cpp index ae94ee0025..55726cb3df 100644 --- a/Marlin/src/lcd/dwin/proui/dwin.cpp +++ b/Marlin/src/lcd/dwin/proui/dwin.cpp @@ -826,8 +826,8 @@ void updateVariable() { #if HAS_FAN static uint8_t _fanspeed = 0; - const bool _new_fanspeed = _fanspeed != thermalManager.fan_speed[0]; - if (_new_fanspeed) _fanspeed = thermalManager.fan_speed[0]; + const bool _new_fanspeed = _fanspeed != fans[0].speed; + if (_new_fanspeed) _fanspeed = fans[0].speed; #endif if (isMenu(tuneMenu) || isMenu(temperatureMenu)) { @@ -1096,7 +1096,7 @@ void dwinDrawDashboard() { #if HAS_FAN DWINUI::drawIcon(ICON_FanSpeed, 187, 383); - DWINUI::drawInt(DWIN_FONT_STAT, hmiData.colorIndicator, hmiData.colorBackground, 3, 195 + 2 * STAT_CHR_W, 384, thermalManager.fan_speed[0]); + DWINUI::drawInt(DWIN_FONT_STAT, hmiData.colorIndicator, hmiData.colorBackground, 3, 195 + 2 * STAT_CHR_W, 384, fans[0].speed); #endif #if HAS_ZOFFSET_ITEM @@ -2398,7 +2398,7 @@ void setFlow() { setPIntOnClick(FLOW_EDIT_MIN, FLOW_EDIT_MAX, []{ planner.refres #if HAS_FAN void applyFanSpeed() { thermalManager.set_fan_speed(0, menuData.value); } - void setFanSpeed() { setIntOnClick(0, 255, thermalManager.fan_speed[0], applyFanSpeed); } + void setFanSpeed() { setIntOnClick(0, 255, fans[0].speed, applyFanSpeed); } #endif #if ENABLED(NOZZLE_PARK_FEATURE) @@ -3531,7 +3531,7 @@ void drawTuneMenu() { bedTargetItem = EDIT_ITEM(ICON_BedTemp, MSG_UBL_SET_TEMP_BED, onDrawBedTemp, setBedTemp, &thermalManager.temp_bed.target); #endif #if HAS_FAN - fanSpeedItem = EDIT_ITEM(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, setFanSpeed, &thermalManager.fan_speed[0]); + fanSpeedItem = EDIT_ITEM(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, setFanSpeed, &fans[0].speed); #endif #if ALL(HAS_ZOFFSET_ITEM, HAS_BED_PROBE, BABYSTEP_ZPROBE_OFFSET, BABYSTEPPING) EDIT_ITEM(ICON_Zoffset, MSG_BABYSTEP_PROBE_Z, onDrawZOffset, setZOffset, &BABY_Z_VAR); @@ -3828,7 +3828,7 @@ void drawTemperatureMenu() { bedTargetItem = EDIT_ITEM(ICON_BedTemp, MSG_UBL_SET_TEMP_BED, onDrawBedTemp, setBedTemp, &thermalManager.temp_bed.target); #endif #if HAS_FAN - fanSpeedItem = EDIT_ITEM(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, setFanSpeed, &thermalManager.fan_speed[0]); + fanSpeedItem = EDIT_ITEM(ICON_FanSpeed, MSG_FAN_SPEED, onDrawFanSpeed, setFanSpeed, &fans[0].speed); #endif #if HAS_PREHEAT #define _ITEM_SETPREHEAT(N) MENU_ITEM(ICON_SetPreheat##N, MSG_PREHEAT_## N ##_SETTINGS, onDrawSubMenu, drawPreheat## N ##Menu); diff --git a/Marlin/src/lcd/extui/dgus/fysetc/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/dgus/fysetc/DGUSDisplayDef.cpp index 9ec98779c8..e85889e4a1 100644 --- a/Marlin/src/lcd/extui/dgus/fysetc/DGUSDisplayDef.cpp +++ b/Marlin/src/lcd/extui/dgus/fysetc/DGUSDisplayDef.cpp @@ -414,9 +414,9 @@ const struct DGUS_VP_Variable ListOfVP[] PROGMEM = { #define FAN_CONTROL 4 #endif #define FAN_VPHELPER(N) \ - VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], screen.percentageToUint8, screen.sendPercentageToDisplay), \ - VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], screen.handleFanControl, nullptr), \ - VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, screen.sendFanStatusToDisplay), + VPHELPER(VP_Fan##N##_Percentage, &fans[N].speed, screen.percentageToUint8, screen.sendPercentageToDisplay), \ + VPHELPER(VP_FAN##N##_CONTROL, &fans[N].speed, screen.handleFanControl, nullptr), \ + VPHELPER(VP_FAN##N##_STATUS, &fans[N].speed, nullptr, screen.sendFanStatusToDisplay), REPEAT(FAN_CONTROL, FAN_VPHELPER) #endif diff --git a/Marlin/src/lcd/extui/dgus/hiprecy/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/dgus/hiprecy/DGUSDisplayDef.cpp index db0ebbc903..e06edbf27d 100644 --- a/Marlin/src/lcd/extui/dgus/hiprecy/DGUSDisplayDef.cpp +++ b/Marlin/src/lcd/extui/dgus/hiprecy/DGUSDisplayDef.cpp @@ -407,9 +407,9 @@ const struct DGUS_VP_Variable ListOfVP[] PROGMEM = { #define FAN_CONTROL 2 #endif #define FAN_VPHELPER(N) \ - VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], screen.percentageToUint8, screen.sendPercentageToDisplay), \ - VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], screen.handleFanControl, nullptr), \ - VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, screen.sendFanStatusToDisplay), + VPHELPER(VP_Fan##N##_Percentage, &fans[N].speed, screen.percentageToUint8, screen.sendPercentageToDisplay), \ + VPHELPER(VP_FAN##N##_CONTROL, &fans[N].speed, screen.handleFanControl, nullptr), \ + VPHELPER(VP_FAN##N##_STATUS, &fans[N].speed, nullptr, screen.sendFanStatusToDisplay), REPEAT(FAN_CONTROL, FAN_VPHELPER) #endif diff --git a/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp index b108dab0a0..6d1e1944d1 100644 --- a/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp +++ b/Marlin/src/lcd/extui/dgus/mks/DGUSDisplayDef.cpp @@ -535,9 +535,9 @@ const struct DGUS_VP_Variable ListOfVP[] PROGMEM = { #define FAN_CONTROL 4 #endif #define FAN_VPHELPER(N) \ - VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], screen.percentageToUint8, screen.sendFanToDisplay), \ - VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], screen.handleFanControl, nullptr), \ - VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, screen.sendFanStatusToDisplay), + VPHELPER(VP_Fan##N##_Percentage, &fans[N].speed, screen.percentageToUint8, screen.sendFanToDisplay), \ + VPHELPER(VP_FAN##N##_CONTROL, &fans[N].speed, screen.handleFanControl, nullptr), \ + VPHELPER(VP_FAN##N##_STATUS, &fans[N].speed, nullptr, screen.sendFanStatusToDisplay), REPEAT(FAN_CONTROL, FAN_VPHELPER) #endif diff --git a/Marlin/src/lcd/extui/dgus/origin/DGUSDisplayDef.cpp b/Marlin/src/lcd/extui/dgus/origin/DGUSDisplayDef.cpp index 2cb7bd6f83..ac357468bd 100644 --- a/Marlin/src/lcd/extui/dgus/origin/DGUSDisplayDef.cpp +++ b/Marlin/src/lcd/extui/dgus/origin/DGUSDisplayDef.cpp @@ -215,9 +215,9 @@ const struct DGUS_VP_Variable ListOfVP[] PROGMEM = { #define FAN_CONTROL 2 #endif #define FAN_VPHELPER(N) \ - VPHELPER(VP_Fan##N##_Percentage, &thermalManager.fan_speed[N], screen.percentageToUint8, screen.sendPercentageToDisplay), \ - VPHELPER(VP_FAN##N##_CONTROL, &thermalManager.fan_speed[N], screen.handleFanControl, nullptr), \ - VPHELPER(VP_FAN##N##_STATUS, &thermalManager.fan_speed[N], nullptr, screen.sendFanStatusToDisplay), + VPHELPER(VP_Fan##N##_Percentage, &fans[N].speed, screen.percentageToUint8, screen.sendPercentageToDisplay), \ + VPHELPER(VP_FAN##N##_CONTROL, &fans[N].speed, screen.handleFanControl, nullptr), \ + VPHELPER(VP_FAN##N##_STATUS, &fans[N].speed, nullptr, screen.sendFanStatusToDisplay), REPEAT(FAN_CONTROL, FAN_VPHELPER) #endif diff --git a/Marlin/src/lcd/extui/mks_ui/draw_fan.cpp b/Marlin/src/lcd/extui/mks_ui/draw_fan.cpp index ea7469980b..4389a453ca 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_fan.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_fan.cpp @@ -47,7 +47,7 @@ enum { uint8_t fanPercent = 0; static void event_handler(lv_obj_t *obj, lv_event_t event) { if (event != LV_EVENT_RELEASED) return; - const uint8_t temp = map(thermalManager.fan_speed[0], 0, 255, 0, 100); + const uint8_t temp = map(fans[0].speed, 0, 255, 0, 100); if (abs(fanPercent - temp) > 2) fanPercent = temp; switch (obj->mks_obj_id) { case ID_F_ADD: if (fanPercent < 100) fanPercent++; break; diff --git a/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp b/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp index 5c13eeaa01..b8ae09a9e0 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_printing.cpp @@ -239,7 +239,7 @@ void disp_bed_temp() { } void disp_fan_speed() { - sprintf_P(public_buf_l, PSTR("%d%%"), (int)thermalManager.fanSpeedPercent(0)); + sprintf_P(public_buf_l, PSTR("%d%%"), (int)fans[0].speed_pct()); lv_label_set_text(labelFan, public_buf_l); } diff --git a/Marlin/src/lcd/extui/mks_ui/draw_ready_print.cpp b/Marlin/src/lcd/extui/mks_ui/draw_ready_print.cpp index a3b31e33b5..257d33a299 100644 --- a/Marlin/src/lcd/extui/mks_ui/draw_ready_print.cpp +++ b/Marlin/src/lcd/extui/mks_ui/draw_ready_print.cpp @@ -233,7 +233,7 @@ void lv_temp_refr() { lv_obj_align(labelBed, buttonBedstate, LV_ALIGN_OUT_RIGHT_MID, 0, 0); #endif #if HAS_FAN - sprintf_P(public_buf_l, PSTR("%d%%"), (int)thermalManager.fanSpeedPercent(0)); + sprintf_P(public_buf_l, PSTR("%d%%"), (int)fans[0].speed_pct()); lv_label_set_text(labelFan, public_buf_l); lv_obj_align(labelFan, buttonFanstate, LV_ALIGN_OUT_RIGHT_MID, 0, 0); #endif diff --git a/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp b/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp index c216eb7e63..5b8c33043e 100644 --- a/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp +++ b/Marlin/src/lcd/extui/mks_ui/mks_hardware.cpp @@ -261,7 +261,7 @@ void mks_hardware_test() { if (millis() % 2000 < 1000) { - thermalManager.fan_speed[0] = 255; + fans[0].speed = 255; #if HAS_X_AXIS WRITE(X_DIR_PIN, LOW); #endif @@ -288,7 +288,7 @@ #endif } else { - thermalManager.fan_speed[0] = 0; + fans[0].speed = 0; #if HAS_X_AXIS WRITE(X_DIR_PIN, HIGH); #endif diff --git a/Marlin/src/lcd/extui/ui_api.cpp b/Marlin/src/lcd/extui/ui_api.cpp index 608e632854..97084cb6f8 100644 --- a/Marlin/src/lcd/extui/ui_api.cpp +++ b/Marlin/src/lcd/extui/ui_api.cpp @@ -314,12 +314,12 @@ namespace ExtUI { // uint8_t getTargetFan_percent(const fan_t fan) { UNUSED(fan); - return TERN0(HAS_FAN, thermalManager.fanSpeedPercent(fan - FAN0)); + return TERN0(HAS_FAN, fans[fan - FAN0].speed_pct()); } uint8_t getActualFan_percent(const fan_t fan) { UNUSED(fan); - return TERN0(HAS_FAN, thermalManager.scaledFanSpeedPercent(fan - FAN0)); + return TERN0(HAS_FAN, fans[fan - FAN0].speed_pct_scaled()); } // diff --git a/Marlin/src/lcd/menu/menu_item.h b/Marlin/src/lcd/menu/menu_item.h index 8b23ab1b9c..d1931ed90f 100644 --- a/Marlin/src/lcd/menu/menu_item.h +++ b/Marlin/src/lcd/menu/menu_item.h @@ -631,9 +631,9 @@ class MenuItem_bool : public MenuEditItemBase { #endif #define _FAN_EDIT_ITEMS(F,L) do{ \ - editable.uint8 = thermalManager.fan_speed[F]; \ + editable.uint8 = fans[F].speed; \ EDIT_ITEM_FAST_N(percent, F, MSG_##L, &editable.uint8, 0, 255, on_fan_update); \ - EDIT_EXTRA_FAN_SPEED(percent, F, MSG_EXTRA_##L, &thermalManager.extra_fan_speed[F].speed, 3, 255); \ + EDIT_EXTRA_FAN_SPEED(percent, F, MSG_EXTRA_##L, &fans[F].extra.speed, 3, 255); \ }while(0) #if FAN_COUNT > 1 diff --git a/Marlin/src/lcd/tft/touch.cpp b/Marlin/src/lcd/tft/touch.cpp index 661a013323..954e7ec775 100644 --- a/Marlin/src/lcd/tft/touch.cpp +++ b/Marlin/src/lcd/tft/touch.cpp @@ -265,10 +265,11 @@ void Touch::touch(touch_control_t * const control) { case FAN: { ui.clear_for_drawing(); - static uint8_t fan, fan_speed; - fan = 0; - fan_speed = thermalManager.fan_speed[fan]; - MenuItem_percent::action(GET_TEXT_F(MSG_FIRST_FAN_SPEED), &fan_speed, 0, 255, []{ thermalManager.set_fan_speed(fan, fan_speed); TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_BIT_SYNC_FANS));}); + editable.uint8 = fans[0].speed; + MenuItem_percent::action(GET_TEXT_F(MSG_FIRST_FAN_SPEED), &editable.uint8, 0, 255, []{ + thermalManager.set_fan_speed(0, editable.uint8); + TERN_(LASER_SYNCHRONOUS_M106_M107, planner.buffer_sync_block(BLOCK_BIT_SYNC_FANS)); + }); } break; case FEEDRATE: diff --git a/Marlin/src/lcd/tft/ui_color_ui.cpp b/Marlin/src/lcd/tft/ui_color_ui.cpp index 53b3b0d068..2d2eec53ad 100644 --- a/Marlin/src/lcd/tft/ui_color_ui.cpp +++ b/Marlin/src/lcd/tft/ui_color_ui.cpp @@ -204,7 +204,7 @@ void draw_fan_status(uint16_t x, uint16_t y, const bool blink) { tft.canvas(x, y, TEMP_FAN_CONTROL_W, TEMP_FAN_CONTROL_H); tft.set_background(COLOR_BACKGROUND); - uint8_t fanSpeed = thermalManager.fan_speed[0]; + uint8_t fanSpeed = fans[0].speed; MarlinImage image; if (fanSpeed >= 127) @@ -216,7 +216,7 @@ void draw_fan_status(uint16_t x, uint16_t y, const bool blink) { tft.add_image(FAN_ICON_X, FAN_ICON_Y, image, COLOR_FAN); - tft_string.set(ui8tostr4pctrj(thermalManager.fan_speed[0])); + tft_string.set(ui8tostr4pctrj(fans[0].speed)); tft_string.trim(); tft.add_text(FAN_TEXT_X, FAN_TEXT_Y, COLOR_FAN, tft_string); } diff --git a/Marlin/src/module/fans.cpp b/Marlin/src/module/fans.cpp new file mode 100644 index 0000000000..c7cfc80e1e --- /dev/null +++ b/Marlin/src/module/fans.cpp @@ -0,0 +1,89 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * fans.cpp - Fan class + */ + +#include "../inc/MarlinConfig.h" + +#if HAS_FAN + +#include "fans.h" + +#define _FANDEF(N) Fan(N), +Fan fans[FAN_COUNT] = { REPEAT(FAN_COUNT, _FANDEF) }; + +#if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) + bool Fan::paused; // = false +#endif + +void Fan::init_pins() { + #define _INIT(N) fans[N].init(); + REPEAT(FAN_COUNT, _INIT) +} + +#if ENABLED(REPORT_FAN_CHANGE) + /** + * Report print fan speed for a target extruder + */ + void Fan::report_speed(const uint8_t fan_index) { + PORT_REDIRECT(SerialMask::All); + SERIAL_ECHOLNPGM("M106 P", fan_index, " S", speed); + } +#endif + +#if ENABLED(EXTRA_FAN_SPEED) + /** + * Handle the M106 P T command: + * T1 = Restore fan speed saved on the last T2 + * T2 = Save the fan speed, then set to the last T<3-255> value + * T<3-255> = Set the "extra fan speed" + */ + void Fan::set_temp_speed(const uint16_t command_or_speed) { + switch (command_or_speed) { + case 1: break; + case 2: extra.saved = speed; break; + default: extra.speed = _MIN(command_or_speed, 255U); break; + } + } +#endif + +#if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) + void Fan::pause(const bool p) { + if (p) { + pause_speed = speed; + speed = 0; + } + else + speed = pause_speed; + } + + void Fan::all_pause(const bool p) { + if (p != paused) { + paused = p; + FANS_LOOP(i) fans[i].pause(p); + } + } +#endif + +#endif // HAS_FAN diff --git a/Marlin/src/module/fans.h b/Marlin/src/module/fans.h new file mode 100644 index 0000000000..312d021a87 --- /dev/null +++ b/Marlin/src/module/fans.h @@ -0,0 +1,209 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2025 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#pragma once + +/** + * fans.h - Fan class + */ + +#include "../inc/MarlinConfig.h" + +#if ANY(HAS_FAN, USE_CONTROLLER_FAN) + // Init fans according to whether they're native PWM or Software PWM + #ifdef BOARD_OPENDRAIN_MOSFETS + #define _INIT_SOFT_FAN(P) OUT_WRITE_OD(P, ENABLED(FAN_INVERTING) ? LOW : HIGH) + #else + #define _INIT_SOFT_FAN(P) OUT_WRITE(P, ENABLED(FAN_INVERTING) ? LOW : HIGH) + #endif + #if ENABLED(FAN_SOFT_PWM) + #define _INIT_FAN_PIN(P) _INIT_SOFT_FAN(P) + #else + #define _INIT_FAN_PIN(P) do{ if (PWM_PIN(P)) SET_PWM(P); else _INIT_SOFT_FAN(P); }while(0) + #endif + #if ENABLED(FAST_PWM_FAN) + #define SET_FAST_PWM_FREQ(P) hal.set_pwm_frequency(pin_t(P), FAST_PWM_FAN_FREQUENCY) + #else + #define SET_FAST_PWM_FREQ(P) NOOP + #endif + #define INIT_FAN_PIN(P) do{ _INIT_FAN_PIN(P); SET_FAST_PWM_FREQ(P); }while(0) +#endif + +#if HAS_FAN + + #define PWM_MASK TERN0(SOFT_PWM_DITHER, _BV(SOFT_PWM_SCALE) - 1) + + #if ENABLED(FAN_SOFT_PWM) + + #define _SOFT_PWM(N) do{ \ + soft_pwm_count &= PWM_MASK; \ + soft_pwm_count += (soft_pwm_amount >> 1); \ + write(N, soft_pwm_count > PWM_MASK ? HIGH : LOW); \ + }while(0) + + #define _SLOW_PWM(N) do{ \ + soft_pwm_count = soft_pwm_amount >> 1; \ + write(N, soft_pwm_count > 0 ? HIGH : LOW); \ + }while(0) + + #endif + + #define FANS_LOOP(I) for (uint8_t I = 0; I < FAN_COUNT; ++I) + + class Fan; + extern Fan fans[FAN_COUNT]; + + class Fan { + public: + uint8_t index; + + Fan(const uint8_t fi) : index(fi) {} + + void init() { + #define _INIT(N) if (index == N) INIT_FAN_PIN(FAN##N##_PIN); + REPEAT(FAN_COUNT, _INIT) + #undef _INIT + } + static void init_pins(); + + static constexpr uint8_t pwmToPercent(const uint8_t spd) { return ui8_to_percent(spd); } + + #if ENABLED(FAN_SOFT_PWM) + uint8_t soft_pwm_amount, soft_pwm_count; + void soft_pwm_on() { + #define _CASE(N) if (index == N) _SOFT_PWM(N); + REPEAT(FAN_COUNT, _CASE) + #undef _CASE + } + void slow_soft_pwm() { + #define _CASE(N) if (index == N) _SLOW_PWM(N); + REPEAT(FAN_COUNT, _CASE) + #undef _CASE + } + void soft_pwm_off(const uint8_t count) { + #define _CASE(N) if (index == N) if (soft_pwm_count <= count) write(LOW); + REPEAT(FAN_COUNT, _CASE) + #undef _CASE + } + #endif + + uint8_t speed; + uint8_t speed_pct() { return pwmToPercent(speed); } + + #if ENABLED(REPORT_FAN_CHANGE) + void report_speed(const uint8_t fan_index); + #endif + + #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) + uint8_t pause_speed; + static bool paused; + static void all_pause(const bool p); + static void power_off() { paused = false; FANS_LOOP(i) fans[i].pause_speed = 0; } + void pause(const bool p); + #endif + + #if ENABLED(AUTO_POWER_FANS) + static bool is_power_needed() { + FANS_LOOP(f) if (fans[f].speed) return true; + return false; + } + #endif + + #if FAN_KICKSTART_TIME + millis_t kick_end_ms = 0; + #if ENABLED(FAN_KICKSTART_LINEAR) + uint8_t prev_fan_speed = 0; + #endif + void kickstart(const millis_t &ms) { + if (speed > FAN_OFF_PWM) { + const bool first_kick = kick_end_ms == 0 && TERN1(FAN_KICKSTART_LINEAR, speed > prev_fan_speed); + if (first_kick) + kick_end_ms = ms + MUL_TERN(FAN_KICKSTART_LINEAR, FAN_KICKSTART_TIME, (speed - prev_fan_speed) / 255); + if (first_kick || PENDING(ms, kick_end_ms)) { + speed = FAN_KICKSTART_POWER; + return; + } + } + else + kick_end_ms = 0; + TERN_(FAN_KICKSTART_LINEAR, prev_fan_speed = speed); + } + #else + void kickstart(const millis_t&) {} + #endif + + #if ENABLED(EXTRA_FAN_SPEED) + struct { uint8_t saved, speed; } extra; + void set_temp_speed(const uint16_t command_or_speed); + #endif + + #if DISABLED(LASER_SYNCHRONOUS_M106_M107) + #define HAS_TAIL_FAN_SPEED 1 + uint8_t tail_speed = 13; + #endif + + #if ENABLED(ADAPTIVE_FAN_SLOWING) + uint8_t speed_scaler = 128; + uint8_t scaled_speed(const uint8_t fs) const { return (fs * uint16_t(speed_scaler)) >> 7; } + #else + static constexpr uint8_t scaled_speed(const uint8_t fs) { return fs; } + #endif + uint8_t scaled_speed() const { return scaled_speed(speed); } + uint8_t speed_pct_scaled() const { return ui8_to_percent(scaled_speed()); } + + uint8_t pwm() { + #if FAN_MIN_PWM != 0 || FAN_MAX_PWM != 255 + return speed ? map(speed, 1, 255, FAN_MIN_PWM, FAN_MAX_PWM) : FAN_OFF_PWM; + #else + return speed ?: FAN_OFF_PWM; + #endif + } + + void sync(const millis_t &ms, const pin_t pin) { + kickstart(ms); + #if ENABLED(FAN_SOFT_PWM) + UNUSED(pin); + soft_pwm_amount = pwm(); + #else + hal.set_pwm_duty(pin, pwm()); + #endif + } + + static void sync_speeds() { + const millis_t ms = millis(); + #define FAN_SET(F) fans[F].sync(ms, pin_t(FAN##F##_PIN)); + REPEAT(FAN_COUNT, FAN_SET) + #undef FAN_SET + } + static void sync_speeds(uint8_t (&fanspeed)[FAN_COUNT]) { + FANS_LOOP(f) fans[f].speed = fanspeed[f]; + sync_speeds(); + } + + static void write(const uint8_t fi, const uint8_t state) { + #define _CASE(N) if (fi == N) WRITE(FAN ##N## _PIN, (state) ^ ENABLED(FAN_INVERTING)); + REPEAT(FAN_COUNT, _CASE) + #undef _CASE + } + void write(const uint8_t state) { write(index, state); } + }; + +#endif // HAS_FAN diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index b4e9eb5f09..c2a2d1ed5b 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1205,51 +1205,6 @@ void Planner::recalculate(const float safe_exit_speed_sqr) { recalculate_trapezoids(safe_exit_speed_sqr); } -/** - * Apply fan speeds - */ -#if HAS_FAN - - void Planner::sync_fan_speeds(uint8_t (&fan_speed)[FAN_COUNT]) { - - #if ENABLED(FAN_SOFT_PWM) - #define _FAN_SET(F) thermalManager.soft_pwm_amount_fan[F] = CALC_FAN_SPEED(fan_speed[F]); - #else - #define _FAN_SET(F) hal.set_pwm_duty(pin_t(FAN##F##_PIN), CALC_FAN_SPEED(fan_speed[F])); - #endif - #define FAN_SET(F) do{ kickstart_fan(fan_speed, ms, F); _FAN_SET(F); }while(0) - - const millis_t ms = millis(); - TERN_(HAS_FAN0, FAN_SET(0)); TERN_(HAS_FAN1, FAN_SET(1)); - TERN_(HAS_FAN2, FAN_SET(2)); TERN_(HAS_FAN3, FAN_SET(3)); - TERN_(HAS_FAN4, FAN_SET(4)); TERN_(HAS_FAN5, FAN_SET(5)); - TERN_(HAS_FAN6, FAN_SET(6)); TERN_(HAS_FAN7, FAN_SET(7)); - } - - #if FAN_KICKSTART_TIME - - void Planner::kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f) { - static millis_t fan_kick_end[FAN_COUNT] = { 0 }; - #if ENABLED(FAN_KICKSTART_LINEAR) - static uint8_t set_fan_speed[FAN_COUNT] = { 0 }; - #endif - if (fan_speed[f] > FAN_OFF_PWM) { - const bool first_kick = fan_kick_end[f] == 0 && TERN1(FAN_KICKSTART_LINEAR, fan_speed[f] > set_fan_speed[f]); - if (first_kick) - fan_kick_end[f] = ms + MUL_TERN(FAN_KICKSTART_LINEAR, FAN_KICKSTART_TIME, (fan_speed[f] - set_fan_speed[f]) / 255); - if (first_kick || PENDING(ms, fan_kick_end[f])) { - fan_speed[f] = FAN_KICKSTART_POWER; - return; - } - } - fan_kick_end[f] = 0; - TERN_(FAN_KICKSTART_LINEAR, set_fan_speed[f] = fan_speed[f]); - } - - #endif - -#endif // HAS_FAN - /** * Maintain fans, paste extruder pressure, spindle/laser power */ @@ -1259,9 +1214,7 @@ void Planner::check_axes_activity() { xyze_bool_t axis_active = { false }; #endif - #if HAS_FAN && DISABLED(LASER_SYNCHRONOUS_M106_M107) - #define HAS_TAIL_FAN_SPEED 1 - static uint8_t tail_fan_speed[FAN_COUNT] = ARRAY_N_1(FAN_COUNT, 13); + #if HAS_TAIL_FAN_SPEED bool fans_need_update = false; #endif @@ -1282,10 +1235,11 @@ void Planner::check_axes_activity() { #if HAS_TAIL_FAN_SPEED FANS_LOOP(i) { - const uint8_t spd = thermalManager.scaledFanSpeed(i, block->fan_speed[i]); - if (tail_fan_speed[i] != spd) { + Fan &fan = fans[i]; + const uint8_t spd = fan.scaled_speed(block->fan_speed[i]); + if (fan.tail_speed != spd) { + fan.tail_speed = spd; fans_need_update = true; - tail_fan_speed[i] = spd; } } #endif @@ -1319,10 +1273,11 @@ void Planner::check_axes_activity() { #if HAS_TAIL_FAN_SPEED FANS_LOOP(i) { - const uint8_t spd = thermalManager.scaledFanSpeed(i); - if (tail_fan_speed[i] != spd) { + Fan &fan = fans[i]; + const uint8_t spd = fan.scaled_speed(); + if (fan.tail_speed != spd) { fans_need_update = true; - tail_fan_speed[i] = spd; + fan.tail_speed = spd; } } #endif @@ -1355,7 +1310,7 @@ void Planner::check_axes_activity() { // Update Fan speeds // Only if synchronous M106/M107 is disabled // - TERN_(HAS_TAIL_FAN_SPEED, if (fans_need_update) sync_fan_speeds(tail_fan_speed)); + TERN_(HAS_TAIL_FAN_SPEED, if (fans_need_update) Fan::sync_speeds()); // Update hotend temperature based on extruder speed TERN_(AUTOTEMP, thermalManager.autotemp_task()); @@ -2087,7 +2042,7 @@ bool Planner::_populate_block( TERN_(MIXING_EXTRUDER, mixer.populate_block(block->b_color)); #if HAS_FAN - FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i]; + FANS_LOOP(i) block->fan_speed[i] = fans[i].speed; #endif #if ENABLED(BARICUDA) @@ -2798,7 +2753,7 @@ void Planner::buffer_sync_block(const BlockFlagBit sync_flag/*=BLOCK_BIT_SYNC_PO #endif #if ENABLED(LASER_SYNCHRONOUS_M106_M107) - FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i]; + FANS_LOOP(i) block->fan_speed[i] = fans[i].speed; #endif /** @@ -3078,7 +3033,7 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const feedRate_t fr_mm_s block->flag.reset(BLOCK_BIT_PAGE); #if HAS_FAN - FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i]; + FANS_LOOP(i) block->fan_speed[i] = fans[i].speed; #endif E_TERN_(block->extruder = extruder); diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 2838fb90c3..8d69544137 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -53,6 +53,10 @@ #include "motion.h" #include "../gcode/queue.h" +#if HAS_FAN + #include "temperature.h" +#endif + #if ENABLED(DELTA) #include "delta.h" #elif ENABLED(POLARGRAPH) @@ -298,7 +302,7 @@ typedef struct PlannerBlock { #endif #if HAS_FAN - uint8_t fan_speed[FAN_COUNT]; + uint8_t fan_speed[FAN_COUNT]; // Speeds of all fans #endif #if ENABLED(BARICUDA) @@ -684,16 +688,6 @@ class Planner { static float get_high_e_speed(); #endif - // Apply fan speeds - #if HAS_FAN - static void sync_fan_speeds(uint8_t (&fan_speed)[FAN_COUNT]); - #if FAN_KICKSTART_TIME - static void kickstart_fan(uint8_t (&fan_speed)[FAN_COUNT], const millis_t &ms, const uint8_t f); - #else - FORCE_INLINE static void kickstart_fan(uint8_t (&)[FAN_COUNT], const millis_t &, const uint8_t) {} - #endif - #endif - #if ENABLED(FILAMENT_WIDTH_SENSOR) void apply_filament_width_sensor(const int8_t encoded_ratio); diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp index 3a8bb2b6c6..98edfaba6d 100644 --- a/Marlin/src/module/probe.cpp +++ b/Marlin/src/module/probe.cpp @@ -351,7 +351,7 @@ xyz_pos_t Probe::offset; // Initialized by settings.load */ void Probe::set_devices_paused_for_probing(const bool dopause) { TERN_(PROBING_HEATERS_OFF, thermalManager.pause_heaters(dopause)); - TERN_(PROBING_FANS_OFF, thermalManager.set_fans_paused(dopause)); + TERN_(PROBING_FANS_OFF, Fan::all_pause(dopause)); TERN_(PROBING_ESTEPPERS_OFF, if (dopause) stepper.disable_e_steppers()); #if ENABLED(PROBING_STEPPERS_OFF) static main_axes_bits_t old_trusted; diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 84924b6f65..74fb761005 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -2659,7 +2659,7 @@ void Stepper::isr() { // Set "fan speeds" for a laser module #if ENABLED(LASER_SYNCHRONOUS_M106_M107) - if (current_block->is_sync_fan()) planner.sync_fan_speeds(current_block->fan_speed); + if (current_block->is_sync_fan()) Fan::sync_speeds(current_block->fan_speed); #endif // Set position diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index f0ca49ef66..c13c0c2ceb 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -410,69 +410,8 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); uint8_t Temperature::coolerfan_speed = FAN_OFF_PWM; #endif -#if ALL(FAN_SOFT_PWM, USE_CONTROLLER_FAN) - uint8_t Temperature::soft_pwm_controllerfan_speed = FAN_OFF_PWM; -#endif - -// Init fans according to whether they're native PWM or Software PWM -#ifdef BOARD_OPENDRAIN_MOSFETS - #define _INIT_SOFT_FAN(P) OUT_WRITE_OD(P, ENABLED(FAN_INVERTING) ? LOW : HIGH) -#else - #define _INIT_SOFT_FAN(P) OUT_WRITE(P, ENABLED(FAN_INVERTING) ? LOW : HIGH) -#endif -#if ENABLED(FAN_SOFT_PWM) - #define _INIT_FAN_PIN(P) _INIT_SOFT_FAN(P) -#else - #define _INIT_FAN_PIN(P) do{ if (PWM_PIN(P)) SET_PWM(P); else _INIT_SOFT_FAN(P); }while(0) -#endif -#if ENABLED(FAST_PWM_FAN) - #define SET_FAST_PWM_FREQ(P) hal.set_pwm_frequency(pin_t(P), FAST_PWM_FAN_FREQUENCY) -#else - #define SET_FAST_PWM_FREQ(P) NOOP -#endif -#define INIT_FAN_PIN(P) do{ _INIT_FAN_PIN(P); SET_FAST_PWM_FREQ(P); }while(0) - // HAS_FAN does not include CONTROLLER_FAN #if HAS_FAN - - uint8_t Temperature::fan_speed[FAN_COUNT] = ARRAY_N_1(FAN_COUNT, FAN_OFF_PWM); - - #if ENABLED(EXTRA_FAN_SPEED) - - Temperature::extra_fan_t Temperature::extra_fan_speed[FAN_COUNT] = ARRAY_N_1(FAN_COUNT, FAN_OFF_PWM); - - /** - * Handle the M106 P T command: - * T1 = Restore fan speed saved on the last T2 - * T2 = Save the fan speed, then set to the last T<3-255> value - * T<3-255> = Set the "extra fan speed" - */ - void Temperature::set_temp_fan_speed(const uint8_t fan, const uint16_t command_or_speed) { - switch (command_or_speed) { - case 1: - set_fan_speed(fan, extra_fan_speed[fan].saved); - break; - case 2: - extra_fan_speed[fan].saved = fan_speed[fan]; - set_fan_speed(fan, extra_fan_speed[fan].speed); - break; - default: - extra_fan_speed[fan].speed = _MIN(command_or_speed, 255U); - break; - } - } - - #endif - - #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) - bool Temperature::fans_paused; // = false - uint8_t Temperature::saved_fan_speed[FAN_COUNT] = ARRAY_N_1(FAN_COUNT, FAN_OFF_PWM); - #endif - - #if ENABLED(ADAPTIVE_FAN_SLOWING) - uint8_t Temperature::fan_speed_scaler[FAN_COUNT] = ARRAY_N_1(FAN_COUNT, 128); - #endif - /** * Set the print fan speed for a target extruder */ @@ -491,43 +430,46 @@ PGMSTR(str_t_heating_failed, STR_T_HEATING_FAILED); if (fan >= FAN_COUNT) return; - fan_speed[fan] = speed; + fans[fan].speed = speed; #if NUM_REDUNDANT_FANS if (fan == 0) { for (uint8_t f = REDUNDANT_PART_COOLING_FAN; f < REDUNDANT_PART_COOLING_FAN + NUM_REDUNDANT_FANS; ++f) - set_fan_speed(f, speed); + fans[f].speed = speed; } #endif TERN_(REPORT_FAN_CHANGE, report_fan_speed(fan)); } + #if ENABLED(EXTRA_FAN_SPEED) + /** + * Handle the M106 P T command: + * T1 = Restore fan speed saved on the last T2 + * T2 = Save the fan speed, then set to the last T<3-255> value + * T<3-255> = Set the "extra fan speed" + */ + void Temperature::set_temp_fan_speed(const uint8_t fan, const uint16_t command_or_speed) { + fans[fan].set_temp_speed(command_or_speed); + switch (command_or_speed) { + case 1: set_fan_speed(fan, fans[fan].extra.saved); break; + case 2: set_fan_speed(fan, fans[fan].extra.speed); break; + default: break; + } + } + + #endif + #if ENABLED(REPORT_FAN_CHANGE) /** * Report print fan speed for a target extruder */ void Temperature::report_fan_speed(const uint8_t fan) { if (fan >= FAN_COUNT) return; - PORT_REDIRECT(SerialMask::All); - SERIAL_ECHOLNPGM("M106 P", fan, " S", fan_speed[fan]); + fans[fan].report_speed(fan); } #endif - #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) - - void Temperature::set_fans_paused(const bool p) { - if (p != fans_paused) { - fans_paused = p; - if (p) - FANS_LOOP(i) { saved_fan_speed[i] = fan_speed[i]; fan_speed[i] = 0; } - else - FANS_LOOP(i) fan_speed[i] = saved_fan_speed[i]; - } - } - - #endif - #endif // HAS_FAN #if WATCH_HOTENDS @@ -657,11 +599,6 @@ volatile bool Temperature::raw_temps_ready = false; millis_t Temperature::fan_update_ms = 0; #endif -#if ENABLED(FAN_SOFT_PWM) - uint8_t Temperature::soft_pwm_amount_fan[FAN_COUNT], - Temperature::soft_pwm_count_fan[FAN_COUNT]; -#endif - #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) celsius_t Temperature::singlenozzle_temp[EXTRUDERS]; #endif @@ -1065,7 +1002,7 @@ void Temperature::factory_reset() { temp_hotend[e].soft_pwm_amount = 0; #if HAS_FAN set_fan_speed(TERN(SINGLEFAN, 0, e), 0); - planner.sync_fan_speeds(fan_speed); + Fan::sync_speeds(); #endif do_z_clearance(MPC_TUNING_END_Z, false); @@ -1219,7 +1156,7 @@ void Temperature::factory_reset() { #if HAS_FAN else if (ELAPSED(curr_time_ms, test_end_ms) && !fan0_done) { set_fan_speed(TERN(SINGLEFAN, 0, e), 255); - planner.sync_fan_speeds(fan_speed); + Fan::sync_speeds(); settle_end_ms = curr_time_ms + settle_time; test_end_ms = settle_end_ms + test_duration; fan0_done = true; @@ -1295,7 +1232,7 @@ void Temperature::factory_reset() { #if HAS_FAN zero_fan_speeds(); set_fan_speed(TERN(SINGLEFAN, 0, e), 255); - planner.sync_fan_speeds(fan_speed); + Fan::sync_speeds(); #endif do_blocking_move_to(xyz_pos_t(MPC_TUNING_POS)); @@ -1309,7 +1246,7 @@ void Temperature::factory_reset() { #if HAS_FAN set_fan_speed(TERN(SINGLEFAN, 0, e), 0); - planner.sync_fan_speeds(fan_speed); + Fan::sync_speeds(); #endif // Heat to 200 degrees @@ -1370,7 +1307,6 @@ void Temperature::factory_reset() { mpc.ambient_xfer_coeff_fan0 = tuner.get_power_fan0() / (hotend.target - tuner.get_ambient_temp()); #if HAS_FAN const float ambient_xfer_coeff_fan255 = tuner.get_power_fan255() / (hotend.target - tuner.get_ambient_temp()); - mpc.applyFanAdjustment(ambient_xfer_coeff_fan255); #endif if (tuning_type == AUTO || tuning_type == FORCE_ASYMPTOTIC) { @@ -1379,9 +1315,10 @@ void Temperature::factory_reset() { block_responsiveness = -log((t2 - asymp_temp) / (t1 - asymp_temp)) / tuner.get_sample_interval(); #if ENABLED(MPC_AUTOTUNE_DEBUG) - SERIAL_ECHOLNPGM("Refining estimates for:"); - SERIAL_ECHOLNPGM("asymp_temp ", asymp_temp); - SERIAL_ECHOLNPGM("block_responsiveness ", p_float_t(block_responsiveness, 4)); + SERIAL_ECHOLNPGM( + "Refining estimates for: asymp_temp=", asymp_temp, + " block_responsiveness=", p_float_t(block_responsiveness, 4) + ); #endif // Update analytic tuning values based on the above @@ -1434,18 +1371,19 @@ int16_t Temperature::getHeaterPower(const heater_id_t heater_id) { #define _EFANOVERLAP(I,N) ((I != N) && _FANOVERLAP(I,E##N)) + #define _INIT_FAN_PWM_PIN(P) do{ if (PWM_PIN(P)) { SET_PWM(P); SET_FAST_PWM_FREQ(P); } else SET_OUTPUT(P); }while(0) #if EXTRUDER_AUTO_FAN_SPEED != 255 - #define INIT_E_AUTO_FAN_PIN(P) do{ if (PWM_PIN(P)) { SET_PWM(P); SET_FAST_PWM_FREQ(P); } else SET_OUTPUT(P); }while(0) + #define INIT_E_AUTO_FAN_PIN(P) _INIT_FAN_PWM_PIN(P) #else #define INIT_E_AUTO_FAN_PIN(P) SET_OUTPUT(P) #endif #if CHAMBER_AUTO_FAN_SPEED != 255 - #define INIT_CHAMBER_AUTO_FAN_PIN(P) do{ if (PWM_PIN(P)) { SET_PWM(P); SET_FAST_PWM_FREQ(P); } else SET_OUTPUT(P); }while(0) + #define INIT_CHAMBER_AUTO_FAN_PIN(P) _INIT_FAN_PWM_PIN(P) #else #define INIT_CHAMBER_AUTO_FAN_PIN(P) SET_OUTPUT(P) #endif #if COOLER_AUTO_FAN_SPEED != 255 - #define INIT_COOLER_AUTO_FAN_PIN(P) do{ if (PWM_PIN(P)) { SET_PWM(P); SET_FAST_PWM_FREQ(P); } else SET_OUTPUT(P); }while(0) + #define INIT_COOLER_AUTO_FAN_PIN(P) _INIT_FAN_PWM_PIN(P) #else #define INIT_COOLER_AUTO_FAN_PIN(P) SET_OUTPUT(P) #endif @@ -1722,7 +1660,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T float out = tempinfo.pid.get_pid_output(tempinfo.target, tempinfo.celsius); #if ENABLED(PID_FAN_SCALING) - out += tempinfo.pid.get_fan_scale_output(thermalManager.fan_speed[extr]); + out += tempinfo.pid.get_fan_scale_output(fans[extr].speed); #endif #if ENABLED(PID_EXTRUSION_SCALING) @@ -1805,7 +1743,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T float ambient_xfer_coeff = mpc.ambient_xfer_coeff_fan0; #if ENABLED(MPC_INCLUDE_FAN) const uint8_t fan_index = TERN(SINGLEFAN, 0, ee); - const float fan_fraction = TERN0(MPC_FAN_0_ACTIVE_HOTEND, !this_hotend) ? 0.0f : fan_speed[fan_index] * RECIPROCAL(255); + const float fan_fraction = TERN0(MPC_FAN_0_ACTIVE_HOTEND, !this_hotend) ? 0.0f : fans[fan_index].speed * RECIPROCAL(255); ambient_xfer_coeff += fan_fraction * mpc.fan255_adjustment; #endif @@ -3110,9 +3048,7 @@ void Temperature::init() { OUT_WRITE(COOLER_PIN, ENABLED(COOLER_INVERTING)); #endif - #define _INIT_FAN(N) TERF(HAS_FAN##N, INIT_FAN_PIN)(FAN##N##_PIN); - REPEAT(FAN_COUNT, _INIT_FAN); - + TERN_(HAS_FAN, Fan::init_pins()); TERF(USE_CONTROLLER_FAN, INIT_FAN_PIN)(CONTROLLER_FAN_PIN); TERN_(HAS_MAXTC_SW_SPI, max_tc_spi.init()); @@ -3396,7 +3332,7 @@ void Temperature::init() { if (adaptive_fan_slowing && heater_id >= 0) { const int_fast8_t fan_index = _MIN(heater_id, FAN_COUNT - 1); uint8_t scale; - if (fan_speed[fan_index] == 0 || rdiff <= hysteresis_degc * 0.25f) + if (fans[fan_index].speed == 0 || rdiff <= hysteresis_degc * 0.25f) scale = 128; else if (rdiff <= hysteresis_degc * 0.3335f) scale = 96; @@ -3408,12 +3344,12 @@ void Temperature::init() { scale = 0; if (TERN0(REPORT_ADAPTIVE_FAN_SLOWING, DEBUGGING(INFO))) { - const uint8_t fss7 = fan_speed_scaler[fan_index] & 0x80; + const uint8_t fss7 = fans[fan_index].speed_scaler & 0x80; if (fss7 ^ (scale & 0x80)) serial_ternary(F("Adaptive Fan Slowing "), fss7, nullptr, F("de"), F("activated.\n")); } - fan_speed_scaler[fan_index] = scale; + fans[fan_index].speed_scaler = scale; } #endif // ADAPTIVE_FAN_SLOWING @@ -3546,8 +3482,8 @@ void Temperature::disable_all_heaters() { void Temperature::singlenozzle_change(const uint8_t old_tool, const uint8_t new_tool) { #if ENABLED(SINGLENOZZLE_STANDBY_FAN) - singlenozzle_fan_speed[old_tool] = fan_speed[0]; - fan_speed[0] = singlenozzle_fan_speed[new_tool]; + singlenozzle_fan_speed[old_tool] = fans[0].speed; + fans[0].speed = singlenozzle_fan_speed[new_tool]; #endif #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) singlenozzle_temp[old_tool] = temp_hotend[0].target; @@ -4027,12 +3963,6 @@ void Temperature::isr() { static SoftPWM soft_pwm_controllerfan; #endif - #define WRITE_FAN(n, v) WRITE(FAN##n##_PIN, (v) ^ ENABLED(FAN_INVERTING)) - - #if ENABLED(FAN_SOFT_PWM) - #define _FAN_LOW(N) if (TERN0(HAS_FAN##N, soft_pwm_count_fan[N] <= pwm_count_tmp)) { TERF(HAS_FAN##N, WRITE_FAN)(N, LOW); }; - #endif - #if DISABLED(SLOW_PWM_HEATERS) #if ANY(HAS_HOTEND, HAS_HEATED_BED, HAS_HEATED_CHAMBER, HAS_COOLER, FAN_SOFT_PWM) @@ -4050,7 +3980,7 @@ void Temperature::isr() { pwm_count_tmp -= 127; #if HAS_HOTEND - #define _PWM_MOD_E(N) _PWM_MOD(N,soft_pwm_hotend[N],temp_hotend[N]); + #define _PWM_MOD_E(N) _PWM_MOD(N, soft_pwm_hotend[N], temp_hotend[N]); REPEAT(HOTENDS, _PWM_MOD_E); #endif @@ -4064,18 +3994,11 @@ void Temperature::isr() { TERF(HAS_COOLER, _PWM_MOD)(COOLER, soft_pwm_cooler, temp_cooler); #if ENABLED(FAN_SOFT_PWM) - #if ENABLED(USE_CONTROLLER_FAN) WRITE(CONTROLLER_FAN_PIN, soft_pwm_controllerfan.add(pwm_mask, controllerFan.soft_pwm_speed)); #endif - - #define __FAN_PWM(N) do{ \ - uint8_t &spcf = soft_pwm_count_fan[N]; \ - spcf = (spcf & pwm_mask) + (soft_pwm_amount_fan[N] >> 1); \ - WRITE_FAN(N, spcf > pwm_mask ? HIGH : LOW); \ - }while(0) - #define _FAN_PWM(N) TERF(HAS_FAN##N, __FAN_PWM)(N); - REPEAT(FAN_COUNT, _FAN_PWM); + #define _SOFT_PWM_ON(N) TERN_(HAS_FAN##N, fans[N].soft_pwm_on()); + REPEAT(FAN_COUNT, _SOFT_PWM_ON) #endif } else { @@ -4090,7 +4013,8 @@ void Temperature::isr() { TERF(HAS_COOLER, _PWM_LOW)(COOLER, soft_pwm_cooler); #if ENABLED(FAN_SOFT_PWM) - REPEAT(FAN_COUNT, _FAN_LOW); + #define _SOFT_PWM_2(N) fans[N].soft_pwm_off(pwm_count_tmp); + REPEAT(FAN_COUNT, _SOFT_PWM_2) #if ENABLED(USE_CONTROLLER_FAN) if (soft_pwm_controllerfan.count <= pwm_count_tmp) WRITE(CONTROLLER_FAN_PIN, LOW); #endif @@ -4145,15 +4069,10 @@ void Temperature::isr() { #if ENABLED(FAN_SOFT_PWM) if (pwm_count_tmp >= 127) { pwm_count_tmp = 0; - #define __PWM_FAN(N) do{ \ - soft_pwm_count_fan[N] = soft_pwm_amount_fan[N] >> 1; \ - WRITE_FAN(N, soft_pwm_count_fan[N] > 0 ? HIGH : LOW); \ - }while(0) - #define _PWM_FAN(N) TERF(HAS_FAN##N, __PWM_FAN)(N); - REPEAT(FAN_COUNT, _PWM_FAN); + FANS_LOOP(f) fans[f].slow_soft_pwm(); } - REPEAT(FAN_COUNT, _FAN_LOW); - #endif // FAN_SOFT_PWM + FANS_LOOP(f) fans[f].soft_pwm_off(pwm_count_tmp); + #endif // SOFT_PWM_SCALE to frequency: // diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index f2ef4d0f6c..ee3f1b78bb 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -25,10 +25,11 @@ * temperature.h - temperature controller */ -#include "thermistor/thermistors.h" - #include "../inc/MarlinConfig.h" +#include "thermistor/thermistors.h" +#include "fans.h" + #if ENABLED(AUTO_POWER_CONTROL) #include "../feature/power.h" #endif @@ -680,15 +681,6 @@ class Temperature { static uint8_t coolerfan_speed; #endif - #if ENABLED(FAN_SOFT_PWM) - static uint8_t soft_pwm_amount_fan[FAN_COUNT], - soft_pwm_count_fan[FAN_COUNT]; - #endif - - #if ALL(FAN_SOFT_PWM, USE_CONTROLLER_FAN) - static uint8_t soft_pwm_controllerfan_speed; - #endif - #if ALL(HAS_MARLINUI_MENU, PREVENT_COLD_EXTRUSION) && E_MANUAL > 0 static bool allow_cold_extrude_override; static void set_menu_cold_override(const bool allow) { allow_cold_extrude_override = allow; } @@ -916,48 +908,13 @@ class Temperature { #endif #if HAS_FAN - - static uint8_t fan_speed[FAN_COUNT]; - #define FANS_LOOP(I) for (uint8_t I = 0; I < FAN_COUNT; ++I) - static void set_fan_speed(const uint8_t fan, const uint16_t speed); - #if ENABLED(REPORT_FAN_CHANGE) static void report_fan_speed(const uint8_t fan); #endif - - #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) - static bool fans_paused; - static uint8_t saved_fan_speed[FAN_COUNT]; - #endif - - #if ENABLED(ADAPTIVE_FAN_SLOWING) - static uint8_t fan_speed_scaler[FAN_COUNT]; - #endif - - static uint8_t scaledFanSpeed(const uint8_t fan, const uint8_t fs) { - UNUSED(fan); // Potentially unused! - return (fs * uint16_t(TERN(ADAPTIVE_FAN_SLOWING, fan_speed_scaler[fan], 128))) >> 7; - } - - static uint8_t scaledFanSpeed(const uint8_t fan) { - return scaledFanSpeed(fan, fan_speed[fan]); - } - - static constexpr inline uint8_t pwmToPercent(const uint8_t speed) { return ui8_to_percent(speed); } - static uint8_t fanSpeedPercent(const uint8_t fan) { return ui8_to_percent(fan_speed[fan]); } - static uint8_t scaledFanSpeedPercent(const uint8_t fan) { return ui8_to_percent(scaledFanSpeed(fan)); } - #if ENABLED(EXTRA_FAN_SPEED) - typedef struct { uint8_t saved, speed; } extra_fan_t; - static extra_fan_t extra_fan_speed[FAN_COUNT]; static void set_temp_fan_speed(const uint8_t fan, const uint16_t command_or_speed); #endif - - #if ANY(PROBING_FANS_OFF, ADVANCED_PAUSE_FANS_PAUSE) - void set_fans_paused(const bool p); - #endif - #endif // HAS_FAN static void zero_fan_speeds() { diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index e13d75d5c4..5111a9f616 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -912,9 +912,9 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. // Cool down with fan inline void filament_swap_cooling() { #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0 - thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed; + fans[TOOLCHANGE_FS_FAN].speed = toolchange_settings.fan_speed; gcode.dwell(SEC_TO_MS(toolchange_settings.fan_time)); - thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = FAN_OFF_PWM; + fans[TOOLCHANGE_FS_FAN].speed = FAN_OFF_PWM; #endif } @@ -1036,7 +1036,7 @@ void fast_line_to_current(const AxisEnum fr_axis) { _line_to_current(fr_axis, 0. #if HAS_FAN && TOOLCHANGE_FS_FAN >= 0 // Store and stop fan. Restored on any exit. - REMEMBER(fan, thermalManager.fan_speed[TOOLCHANGE_FS_FAN], 0); + REMEMBER(fan, fans[TOOLCHANGE_FS_FAN].speed, 0); #endif // Z raise @@ -1194,7 +1194,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { #if ALL(TOOLCHANGE_FILAMENT_SWAP, HAS_FAN) && TOOLCHANGE_FS_FAN >= 0 // Store and stop fan. Restored on any exit. - REMEMBER(fan, thermalManager.fan_speed[TOOLCHANGE_FS_FAN], 0); + REMEMBER(fan, fans[TOOLCHANGE_FS_FAN].speed, 0); #endif // Z raise before retraction diff --git a/buildroot/tests/mega2560 b/buildroot/tests/mega2560 index f90e2074ab..d1714006e3 100755 --- a/buildroot/tests/mega2560 +++ b/buildroot/tests/mega2560 @@ -69,7 +69,7 @@ opt_enable VIKI2 BOOT_MARLIN_LOGO_ANIMATED SDSUPPORT AUTO_REPORT_SD_STATUS \ EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL AUTO_REPORT_POSITION \ NO_VOLUMETRICS EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES AUTOTEMP G38_PROBE_TARGET JOYSTICK \ DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ - FILAMENT_RUNOUT_SENSOR NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE Z_SAFE_HOMING FIL_RUNOUT3_PULLUP + FILAMENT_RUNOUT_SENSOR NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE ADVANCED_PAUSE_FANS_PAUSE Z_SAFE_HOMING FIL_RUNOUT3_PULLUP exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 4 | VIKI2 | Servo Probe | Multiple runout sensors (x4)" "$3" # diff --git a/ini/features.ini b/ini/features.ini index 03a9bdbba8..0cd2487821 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -359,7 +359,7 @@ HAS_MEDIA_SUBCALLS = build_src_filter=+ + HAS_EXTRUDERS = build_src_filter=+ + HAS_HOTEND = build_src_filter=+ -HAS_FAN = build_src_filter=+ +HAS_FAN = build_src_filter=+ + HAS_HEATED_BED = build_src_filter=+ HAS_HEATED_CHAMBER = build_src_filter=+ HAS_COOLER = build_src_filter=+