Skip to content

Commit

Permalink
temperature_fan: allow curve control to decrease fan pwm (#373)
Browse files Browse the repository at this point in the history
* Updated Temperature fan curve Control

Curve Control can now also decrease fan pwm with increasing temperature, target_temp is now ignored

* fixed a float division error and improved code readability
  • Loading branch information
Zeanon authored Oct 23, 2024
1 parent f4671d2 commit 748670b
Showing 1 changed file with 31 additions and 36 deletions.
67 changes: 31 additions & 36 deletions klippy/extras/temperature_fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def __init__(self, temperature_fan, config, controlled_fan=None):
self.controlled_fan = (
temperature_fan if controlled_fan is None else controlled_fan
)
self.points = []
self.curve_table = []
points = config.getlists(
"points", seps=(",", "\n"), parser=float, count=2
)
Expand All @@ -266,40 +266,34 @@ def __init__(self, temperature_fan, config, controlled_fan=None):
"Point needs to have exactly one temperature and one speed "
"value."
)
if current_point[0] > temperature_fan.target_temp:
if temp > temperature_fan.target_temp:
raise temperature_fan.printer.config_error(
"Temperature in point can not exceed target temperature."
"Temperature in point can not exceed max_temp."
)
if current_point[0] < temperature_fan.min_temp:
if temp < temperature_fan.min_temp:
raise temperature_fan.printer.config_error(
"Temperature in point can not fall below min_temp."
)
if current_point[1] > temperature_fan.get_max_speed():
if pwm > temperature_fan.get_max_speed():
raise temperature_fan.printer.config_error(
"Speed in point can not exceed max_speed."
)
if current_point[1] < temperature_fan.get_min_speed():
if pwm < temperature_fan.get_min_speed():
raise temperature_fan.printer.config_error(
"Speed in point can not fall below min_speed."
)
self.points.append(current_point)
self.points.append(
[temperature_fan.target_temp, temperature_fan.get_max_speed()]
)
if len(self.points) < 2:
for _temp, _pwm in self.curve_table:
if _temp == temp:
raise temperature_fan.printer.config_error(
"Temperature can not exist twice in curve table."
)
self.curve_table.append(current_point)
if len(self.curve_table) < 2:
raise temperature_fan.printer.config_error(
"At least two points need to be defined for curve in "
"temperature_fan."
)
self.points.sort(key=lambda p: p[0])
last_point = [temperature_fan.min_temp, temperature_fan.get_min_speed()]
for point in self.points:
if point[1] < last_point[1]:
raise temperature_fan.printer.config_error(
"Points with higher temperatures have to have higher or "
"equal speed than points with lower temperatures."
)
last_point = point
self.curve_table.sort(key=lambda p: p[0])
self.cooling_hysteresis = config.getfloat("cooling_hysteresis", 0.0)
self.heating_hysteresis = config.getfloat("heating_hysteresis", 0.0)
self.smooth_readings = config.getint("smooth_readings", 10, minval=1)
Expand All @@ -309,36 +303,37 @@ def __init__(self, temperature_fan, config, controlled_fan=None):
self.last_temp = 0.0

def temperature_callback(self, read_time, temp):
current_temp, target_temp = self.temperature_fan.get_temp(read_time)
temp = self.smooth_temps(temp)
if temp >= target_temp:
self.temperature_fan.set_speed(
read_time, self.temperature_fan.get_max_speed()
def _interpolate(sbelow, above, temp):
return ((below[1] * (above[0] - temp)) + (above[1] * (temp - below[0]))) / (
above[0] - below[0]
)

temp = self.smooth_temps(temp)
if temp <= self.curve_table[0][0]:
self.controlled_fan.set_speed(read_time, self.curve_table[0][1])
return
if temp >= self.curve_table[-1][0]:
self.controlled_fan.set_speed(read_time, self.curve_table[-1][1])
return

below = [
self.temperature_fan.min_temp,
self.temperature_fan.get_min_speed(),
self.curve_table[0][0],
self.curve_table[0][1],
]
above = [
self.temperature_fan.max_temp,
self.temperature_fan.get_max_speed(),
self.curve_table[-1][0],
self.curve_table[-1][1],
]
for config_temp in self.points:
for config_temp in self.curve_table:
if config_temp[0] < temp:
below = config_temp
else:
above = config_temp
break
self.controlled_fan.set_speed(
read_time, self.interpolate(below, above, temp)
read_time, _interpolate(below, above, temp)
)

def interpolate(self, below, above, temp):
return (
(below[1] * (above[0] - temp)) + (above[1] * (temp - below[0]))
) / (above[0] - below[0])

def smooth_temps(self, current_temp):
if (
self.last_temp - self.cooling_hysteresis
Expand Down

0 comments on commit 748670b

Please sign in to comment.