Skip to content

Commit

Permalink
Module: Fan, Scale value for PWM fan
Browse files Browse the repository at this point in the history
Scale value for fan input based on fan's `min_power` and `max_power`.
As an example, when fan's min_power is set to `0.2`, requesting 1% of fan should translate to roughly `0.2`
This makes it possible to operate fans such as CPAP which generally need
quite high min_power (between 16-30%) operatable at 1%

This also renamed off_below to min_power

Signed-off-by: Jakub Racek <[email protected]>
  • Loading branch information
kubaracek committed Aug 5, 2023
1 parent 36be1cf commit b687d39
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 34 deletions.
6 changes: 3 additions & 3 deletions config/printer-artillery-sidewinder-x2-2022.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,15 @@ max_temp: 130

[fan]
pin: PC8
off_below: 0.1
min_power: 0.1

[heater_fan extruder]
pin: PC7
off_below: 0.2
min_power: 0.2

[controller_fan case]
pin: PC6
off_below: 0.3
min_power: 0.3
idle_speed: 0.0

[temperature_sensor mainboard]
Expand Down
2 changes: 1 addition & 1 deletion config/printer-geeetech-301-2019.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ heaters: extruder
pin: multi_pin:extruder_fans
heater: extruder
max_power: 0.8
off_below: 0.2
min_power: 0.2
shutdown_speed: 0

[mcu]
Expand Down
2 changes: 1 addition & 1 deletion config/printer-monoprice-select-mini-v2-2018.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pin: PB8
# chassis fan
[controller_fan chassis_fan]
pin: PB3
off_below: 0.25
min_power: 0.25

[mcu]
serial: /dev/ttyACM0
Expand Down
14 changes: 14 additions & 0 deletions docs/Config_Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ All dates in this document are approximate.

## Changes

20230801: The setting `fan.off_bellow` has been changed to `fan.min_power`.
However, this change will not affect users who do not utilize this setting.
With this update, a PWM scaling has been introduced between `min_power` and
`max_power`. Fans that require a higher `min_power` will now have access to
their full "safe" power curve. By properly setting `min_power`, any fan
(such as CPAP) should engage even at `M106 S1`. It's recommended to review
your slicer/macros to adjust your fan speeds. Your previously designated 20%
fan speed may no longer represent your lowest fan setting but will now
correspond to an actual 20% fan speed.
If you had previously set `max_power` to anything below 1.0 (default),
it is advisable to recalibrate `min_power` and `kick_start_time` again, with
the settings `min_power: 0` and `max_power: 1`.


20230729: The exported status for `dual_carriage` is changed. Instead of
exporting `mode` and `active_carriage`, the individual modes for each
carriage are exported as `printer.dual_carriage.carriage_0` and
Expand Down
41 changes: 18 additions & 23 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2565,15 +2565,14 @@ Print cooling fan.
pin:
# Output pin controlling the fan. This parameter must be provided.
#max_power: 1.0
# The maximum power (expressed as a value from 0.0 to 1.0) that the
# pin may be set to. The value 1.0 allows the pin to be set fully
# enabled for extended periods, while a value of 0.5 would allow the
# pin to be enabled for no more than half the time. This setting may
# be used to limit the total power output (over extended periods) to
# the fan. If this value is less than 1.0 then fan speed requests
# will be scaled between zero and max_power (for example, if
# max_power is .9 and a fan speed of 80% is requested then the fan
# power will be set to 72%). The default is 1.0.
# The maximum power (0.0 to 1.0) that the pin may be set to. A value
# of 1.0 enables the pin fully for extended periods, while 0.5 allows
# it for no more than half the time. Use it to limit total power output
# (over extended periods) to the fan. This value is combined with
# min_power to scale fan speed. With `min_power` at 0.3 and
# `max_power` at 1.0, fan speed request scales between 0.3 (min_power)
# and 1.0 (max_power). Requesting 10% fan speed results in a value of
# 0.37. Default is 1.0.
#shutdown_speed: 0
# The desired fan speed (expressed as a value from 0.0 to 1.0) if
# the micro-controller software enters an error state. The default
Expand All @@ -2593,18 +2592,14 @@ pin:
# Time (in seconds) to run the fan at full speed when either first
# enabling or increasing it by more than 50% (helps get the fan
# spinning). The default is 0.100 seconds.
#off_below: 0.0
# The minimum input speed which will power the fan (expressed as a
# value from 0.0 to 1.0). When a speed lower than off_below is
# requested the fan will instead be turned off. This setting may be
# used to prevent fan stalls and to ensure kick starts are
# effective. The default is 0.0.
#min_power: 0.0
# The minimum input power which will power the fan (expressed as a
# value from 0.0 to 1.0). The default is 0.0.
#
# This setting should be recalibrated whenever max_power is adjusted.
# To calibrate this setting, start with off_below set to 0.0 and the
# fan spinning. Gradually lower the fan speed to determine the lowest
# To calibrate this setting, start with min_power=0 and max_power=1
# Gradually lower the fan speed to determine the lowest
# input speed which reliably drives the fan without stalls. Set
# off_below to the duty cycle corresponding to this value (for
# min_power to the duty cycle corresponding to this value (for
# example, 12% -> 0.12) or slightly higher.
#tachometer_pin:
# Tachometer input pin for monitoring fan speed. A pullup is generally
Expand Down Expand Up @@ -2642,7 +2637,7 @@ a shutdown_speed equal to max_power.
#cycle_time:
#hardware_pwm:
#kick_start_time:
#off_below:
#min_power:
#tachometer_pin:
#tachometer_ppr:
#tachometer_poll_interval:
Expand Down Expand Up @@ -2679,7 +2674,7 @@ watched component.
#cycle_time:
#hardware_pwm:
#kick_start_time:
#off_below:
#min_power:
#tachometer_pin:
#tachometer_ppr:
#tachometer_poll_interval:
Expand Down Expand Up @@ -2725,7 +2720,7 @@ information.
#cycle_time:
#hardware_pwm:
#kick_start_time:
#off_below:
#min_power:
#tachometer_pin:
#tachometer_ppr:
#tachometer_poll_interval:
Expand Down Expand Up @@ -2783,7 +2778,7 @@ with the SET_FAN_SPEED [gcode command](G-Codes.md#fan_generic).
#cycle_time:
#hardware_pwm:
#kick_start_time:
#off_below:
#min_power:
#tachometer_pin:
#tachometer_ppr:
#tachometer_poll_interval:
Expand Down
22 changes: 16 additions & 6 deletions klippy/extras/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ def __init__(self, config, default_shutdown_speed=0.):
self.last_fan_value = 0.
self.last_fan_time = 0.
# Read config
self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.)
self.kick_start_time = config.getfloat('kick_start_time', 0.1,
minval=0.)
self.off_below = config.getfloat('off_below', default=0.,
self.min_power = config.getfloat('min_power', default=0.,
minval=0., maxval=1.)
self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.)
if self.min_power > self.max_power:
raise config.error(
"min_power=%f can't be larger than max_power=%f"
% (self.min_power, self.max_power)
)

cycle_time = config.getfloat('cycle_time', 0.010, above=0.)
hardware_pwm = config.getboolean('hardware_pwm', False)
shutdown_speed = config.getfloat(
Expand Down Expand Up @@ -46,11 +52,15 @@ def __init__(self, config, default_shutdown_speed=0.):
def get_mcu(self):
return self.mcu_fan.get_mcu()
def set_speed(self, print_time, value):
if value < self.off_below:
value = 0.
value = max(0., min(self.max_power, value * self.max_power))
if value == self.last_fan_value:
return
if value > 0:
# Scale value between min_power and max_power
pwm_value =\
value * (self.max_power - self.min_power) + self.min_power
pwm_value = max(self.min_power, min(self.max_power, pwm_value))
else:
pwm_value = 0
print_time = max(self.last_fan_time + FAN_MIN_TIME, print_time)
if self.enable_pin:
if value > 0 and self.last_fan_value == 0:
Expand All @@ -62,7 +72,7 @@ def set_speed(self, print_time, value):
# Run fan at full speed for specified kick_start_time
self.mcu_fan.set_pwm(print_time, self.max_power)
print_time += self.kick_start_time
self.mcu_fan.set_pwm(print_time, value)
self.mcu_fan.set_pwm(print_time, pwm_value)
self.last_fan_time = print_time
self.last_fan_value = value
def set_speed_from_command(self, value):
Expand Down

0 comments on commit b687d39

Please sign in to comment.