From 84fc18e466df7a40a0888339c52a3c515098c833 Mon Sep 17 00:00:00 2001 From: Neo Date: Fri, 23 Jan 2026 20:51:38 +0100 Subject: [PATCH] temperature_fan: Option to invert temperature fan control Adds a config option invert_control to invert the control logic for a temperature_fan. This is useful for bed fans where you expect the fan to increase temperature instead of cooling something. This does not do exactly the same thing as inverting the output pin. Signed-off-by: Neo neoliden@gmail.com --- docs/Config_Reference.md | 3 +++ klippy/extras/temperature_fan.py | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index b01360adf..457a0661c 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -3339,6 +3339,9 @@ information. # The minimum fan speed (expressed as a value from 0.0 to 1.0) that # the fan will be set to for PID temperature fans. # The default is 0.3. +#invert_control: False +# The control output is inverted. Useful for bed fans that +# are supposed to increase temperature instead of decreasing it. #gcode_id: # If set, the temperature will be reported in M105 queries using the # given id. The default is to not report the temperature via M105. diff --git a/klippy/extras/temperature_fan.py b/klippy/extras/temperature_fan.py index a9aa4d0ba..fc6172881 100644 --- a/klippy/extras/temperature_fan.py +++ b/klippy/extras/temperature_fan.py @@ -38,6 +38,7 @@ class TemperatureFan: algos = {'watermark': ControlBangBang, 'pid': ControlPID} algo = config.getchoice('control', algos) self.control = algo(self, config) + self.invert_control = config.getboolean('invert_control', False) self.next_speed_time = 0. self.last_speed_value = 0. gcode = self.printer.lookup_object('gcode') @@ -70,6 +71,8 @@ class TemperatureFan: return self.min_speed def get_max_speed(self): return self.max_speed + def get_invert_control(self): + return self.invert_control def get_status(self, eventtime): status = self.fan.get_status(eventtime) status["temperature"] = round(self.last_temp, 2) @@ -127,7 +130,7 @@ class ControlBangBang: elif (not self.heating and temp <= target_temp-self.max_delta): self.heating = True - if self.heating: + if self.heating != self.temperature_fan.get_invert_control(): self.temperature_fan.set_tf_speed(read_time, 0.) else: self.temperature_fan.set_tf_speed( @@ -170,6 +173,9 @@ class ControlPID: temp_integ = max(0., min(self.temp_integ_max, temp_integ)) # Calculate output co = self.Kp*temp_err + self.Ki*temp_integ - self.Kd*temp_deriv + # Handle inverted control + if self.temperature_fan.get_invert_control(): + co = self.temperature_fan.get_max_speed() - co bounded_co = max(0., min(self.temperature_fan.get_max_speed(), co)) self.temperature_fan.set_tf_speed( read_time, max(self.temperature_fan.get_min_speed(),