added fan interval per thermalzone and pid interval global
This commit is contained in:
@@ -6,8 +6,10 @@
|
|||||||
# otherwise INFO is a good value.
|
# otherwise INFO is a good value.
|
||||||
loglevel: DEBUG
|
loglevel: DEBUG
|
||||||
|
|
||||||
# Set interval (seconds) in which PyFan is checking your temp sources and adjusts PWM values.
|
# Frequency in seconds of feeding sensors values into PID. Higher frequency (lower value) means PID can react faster.
|
||||||
interval: 1
|
# Fans only get set every thermalzones->interval seconds, regardless of this value.
|
||||||
|
# Must be lower then your lowest thermalzone interval.
|
||||||
|
pid_interval: 0.2
|
||||||
|
|
||||||
thermalzones:
|
thermalzones:
|
||||||
- name: GPU+SYSTEM
|
- name: GPU+SYSTEM
|
||||||
@@ -19,6 +21,11 @@ thermalzones:
|
|||||||
# If not, check what you sensor is outputting if you try to read from it.
|
# If not, check what you sensor is outputting if you try to read from it.
|
||||||
factor: 1000
|
factor: 1000
|
||||||
|
|
||||||
|
# Frequency in which fan speed should be adjusted in seconds.
|
||||||
|
# PyFan reads sensors values from hwmon every pid_interval, but only sets fan speeds in this interval.
|
||||||
|
# Can't be lower then pid_interval.
|
||||||
|
interval: 3
|
||||||
|
|
||||||
# Define all fans that this thermal zone is going to control.
|
# Define all fans that this thermal zone is going to control.
|
||||||
# There is no limit to how many fans one thermal zone can control.
|
# There is no limit to how many fans one thermal zone can control.
|
||||||
# You can have different limitations on your fans, for example:
|
# You can have different limitations on your fans, for example:
|
||||||
@@ -50,6 +57,7 @@ thermalzones:
|
|||||||
- coretemp/temp1_input
|
- coretemp/temp1_input
|
||||||
- amdgpu/temp1_input
|
- amdgpu/temp1_input
|
||||||
factor: 1000
|
factor: 1000
|
||||||
|
interval: 3
|
||||||
fan:
|
fan:
|
||||||
- it8686/pwm1: [ 100, 200 ]
|
- it8686/pwm1: [ 100, 200 ]
|
||||||
target: 50
|
target: 50
|
||||||
|
44
pyfan.py
44
pyfan.py
@@ -15,17 +15,25 @@ class ThermalZone:
|
|||||||
def __init__(self, config, pyfan_parent) -> None:
|
def __init__(self, config, pyfan_parent) -> None:
|
||||||
self.fans = config["fan"]
|
self.fans = config["fan"]
|
||||||
self.temp_source = config["source"]
|
self.temp_source = config["source"]
|
||||||
self.pid = PID(config["pid"]["p"], config["pid"]["i"], config["pid"]["d"], setpoint=0)
|
|
||||||
self.pid.output_limits = (0, 255)
|
|
||||||
self.factor = 1 / config["factor"]
|
self.factor = 1 / config["factor"]
|
||||||
self.name = config["name"]
|
self.name = config["name"]
|
||||||
self.target = config["target"]
|
self.target = config["target"]
|
||||||
self.hwmap = pyfan_parent.hwmap
|
|
||||||
self.pyfan = pyfan_parent
|
self.pyfan = pyfan_parent
|
||||||
|
self.hwmap = self.pyfan.hwmap
|
||||||
self.alias_replace = re.compile("|".join(self.hwmap.keys()))
|
self.alias_replace = re.compile("|".join(self.hwmap.keys()))
|
||||||
|
|
||||||
|
if "interval" not in config:
|
||||||
|
config["interval"] = 3
|
||||||
|
logging.getLogger("pyfan").warning(
|
||||||
|
"[%s] No interval specified, using default. This is deprecated since 1.6 and may be removed in future "
|
||||||
|
"versions. See example config for reference.", self.name)
|
||||||
|
|
||||||
|
self.pid = PID(config["pid"]["p"], config["pid"]["i"], config["pid"]["d"], setpoint=0,
|
||||||
|
sample_time=config["interval"])
|
||||||
|
self.pid.output_limits = (0, 255)
|
||||||
self.setup_pwm()
|
self.setup_pwm()
|
||||||
|
|
||||||
logging.getLogger("pyfan").info("[%s] Source=%s Fans=%s Factor=%d PID=%s", self.name, self.temp_source,
|
logging.getLogger("pyfan").info("[%s] Source=%s Fans=%s Factor=%f %s", self.name, self.temp_source,
|
||||||
self.fans, self.factor, self.pid)
|
self.fans, self.factor, self.pid)
|
||||||
|
|
||||||
def eval(self):
|
def eval(self):
|
||||||
@@ -44,20 +52,21 @@ class ThermalZone:
|
|||||||
logging.getLogger("pyfan").warning(
|
logging.getLogger("pyfan").warning(
|
||||||
"[%s] max/min for %s was not set correctly (%s)", self.name, fan, fan_val)
|
"[%s] max/min for %s was not set correctly (%s)", self.name, fan, fan_val)
|
||||||
|
|
||||||
|
if self.read_sysfs(fan) != min(fan_val[1], max(val, fan_val[0])):
|
||||||
self.write_sysfs(fan, min(fan_val[1], max(val, fan_val[0])))
|
self.write_sysfs(fan, min(fan_val[1], max(val, fan_val[0])))
|
||||||
else:
|
elif self.read_sysfs(fan) != min(val, fan_val):
|
||||||
self.write_sysfs(fan, min(val, fan_val))
|
self.write_sysfs(fan, min(val, fan_val))
|
||||||
|
|
||||||
logging.getLogger("pyfan").debug("[%s] %s=%i%%", self.name, fan,
|
logging.getLogger("pyfan").debug("[%s] %s=%i%%", self.name, fan,
|
||||||
int(int(self.read_sysfs(fan)) / 255 * 100))
|
int(int(self.read_sysfs(fan)) / 255 * 100))
|
||||||
else:
|
elif self.read_sysfs(target_fan) != val:
|
||||||
self.write_sysfs(target_fan, val)
|
self.write_sysfs(target_fan, val)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
logging.getLogger("pyfan").warning("[%s] Failed to set pwm, trying to reset it. (%s)", self.name,
|
logging.getLogger("pyfan").warning("[%s] Failed to set pwm, trying to reset it. (%s)", self.name,
|
||||||
err.strerror)
|
err.strerror)
|
||||||
self.setup_pwm(1)
|
self.setup_pwm(1)
|
||||||
|
|
||||||
logging.getLogger("pyfan").debug("[%s] %i%% D:%iC T:%iC pid:%s", self.name, int(val / 255 * 100), diff,
|
logging.getLogger("pyfan").debug("[%s] %i%% D:%iC T:%iC %s", self.name, int(val / 255 * 100), diff,
|
||||||
self.get_temp(), self.pid)
|
self.get_temp(), self.pid)
|
||||||
|
|
||||||
def get_temp(self):
|
def get_temp(self):
|
||||||
@@ -118,18 +127,19 @@ class PyFan:
|
|||||||
self.config = self.__load_config(config)
|
self.config = self.__load_config(config)
|
||||||
logging.basicConfig(level=logging.getLevelName(self.config["loglevel"]))
|
logging.basicConfig(level=logging.getLevelName(self.config["loglevel"]))
|
||||||
self.zones = []
|
self.zones = []
|
||||||
self._hwmon_map = {}
|
if "pid_interval" not in self.config:
|
||||||
|
self.interval = 0.2
|
||||||
if "interval" in self.config:
|
logging.getLogger("pyfan").warning(
|
||||||
self.interval = self.config["interval"]
|
"No pid_interval specified, using default. This is deprecated since 1.6 and may be removed in future "
|
||||||
|
"versions. See example config for reference.")
|
||||||
else:
|
else:
|
||||||
self.interval = 1
|
self.interval = self.config["pid_interval"]
|
||||||
|
|
||||||
for zone in self.config["thermalzones"]:
|
for zone in self.config["thermalzones"]:
|
||||||
self.zones.append(ThermalZone(zone, self))
|
self.zones.append(ThermalZone(zone, self))
|
||||||
|
|
||||||
logging.getLogger("pyfan").info(
|
logging.getLogger("pyfan").info(
|
||||||
"Finished creating %d thermal zones, checking all %d seconds", len(self.zones), self.interval)
|
"Created %d thermal zones, pid_interval=%f.", len(self.zones), self.interval)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
@@ -144,16 +154,16 @@ class PyFan:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def hwmap(self):
|
def hwmap(self):
|
||||||
self._hwmon_map.clear()
|
hwmon_map = {}
|
||||||
|
|
||||||
names = glob.glob(SYSFS_HWMON_BASE + "hwmon*/name")
|
names = glob.glob(SYSFS_HWMON_BASE + "hwmon*/name")
|
||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
hwmon = name.split("/")[-2]
|
hwmon = name.split("/")[-2]
|
||||||
with open(name) as file:
|
with open(name) as file:
|
||||||
hwname = file.read().strip()
|
hw_name = file.read().strip()
|
||||||
self._hwmon_map[hwname] = hwmon
|
hwmon_map[hw_name] = hwmon
|
||||||
return self._hwmon_map
|
return hwmon_map
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def __load_config(path):
|
def __load_config(path):
|
||||||
|
Reference in New Issue
Block a user