Skip to content

Commit

Permalink
Set fan speeds relative to PWM_F.
Browse files Browse the repository at this point in the history
- Add a `_full_speed_lsb` member variable which represents the (smallest) LSB
  value corresponding to a 100% fan setting.
- Add a `_calculate_full_speed()` method that computes it.
- Use `_full_speed_lsb` when converting percentages to fan speed settings and back.

Fixes #19.
  • Loading branch information
stoklund committed Oct 30, 2021
1 parent 42ad160 commit 92921bf
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 4 deletions.
24 changes: 21 additions & 3 deletions adafruit_emc2101/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,15 @@ def __init__(self, i2c_bus):
if not self._part_id in [0x16, 0x28] or self._mfg_id != 0x5D:
raise AttributeError("Cannot find a EMC2101")

self._full_speed_lsb = None # See _calculate_full_speed().
self.initialize()

def initialize(self):
"""Reset the controller to an initial default configuration"""
self._tach_mode_enable = True
self._enabled_forced_temp = False
self._spin_tach_limit = False
self._calculate_full_speed()

@property
def internal_temperature(self):
Expand All @@ -257,18 +259,34 @@ def fan_speed(self):
val |= self._tach_read_msb << 8
return _FAN_RPM_DIVISOR / val

# pylint: disable=no-self-use
def _calculate_full_speed(self, pwm_f=None, dac=None):
"""Determine the LSB value for a 100% fan setting"""
if dac is None:
dac = self.dac_output_enabled

if dac:
# DAC mode is independent of PWM_F.
self._full_speed_lsb = float(MAX_LUT_SPEED)
return

# PWM mode reaches 100% duty cycle at a 2*PWM_F setting.
if pwm_f is None:
pwm_f = self._pwm_freq

# PWM_F=0 behaves like PWM_F=1.
self._full_speed_lsb = 2.0 * max(1, pwm_f)

def _speed_to_lsb(self, percentage):
"""Convert a fan speed percentage to a Fan Setting byte value"""
return round((percentage / 100.0) * MAX_LUT_SPEED)
return round((percentage / 100.0) * self._full_speed_lsb)

@property
def manual_fan_speed(self):
"""The fan speed used while the LUT is being updated and is unavailable. The speed is
given as the fan's PWM duty cycle represented as a float percentage.
The value roughly approximates the percentage of the fan's maximum speed"""
raw_setting = self._fan_setting & MAX_LUT_SPEED
return (raw_setting / MAX_LUT_SPEED) * 100
return (raw_setting / self._full_speed_lsb) * 100

@manual_fan_speed.setter
def manual_fan_speed(self, fan_speed):
Expand Down
1 change: 1 addition & 0 deletions adafruit_emc2101/emc2101_lut.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ def pwm_frequency(self, value):
if value < 0 or value > 0x1F:
raise AttributeError("pwm_frequency must be from 0-31")
self._pwm_freq = value
self._calculate_full_speed(pwm_f=value)

@property
def pwm_frequency_divisor(self):
Expand Down
4 changes: 3 additions & 1 deletion examples/emc2101_set_pwm_freq.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
emc = EMC2101(i2c)
emc.set_pwm_clock(use_preset=False)
# Datasheet recommends using the maximum value of 31 (0x1F)
# to provide the highest effective resolution
# to provide the highest effective resolution.
# The PWM frequency must be set before changing `manual_fan_speed` or LUT entries.
# Otherwise the PWM duty cycle won't be configured correctly.
emc.pwm_frequency = 14

# This divides the pwm frequency down to a smaller number
Expand Down

0 comments on commit 92921bf

Please sign in to comment.