Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
8d95e69048 | |||
772408fc6d | |||
e980293ab6 | |||
6e45b77aba | |||
6074353b95 | |||
3f96734d84 |
@@ -1,6 +1,6 @@
|
|||||||
## PyFAN
|
## PyFAN
|
||||||
|
|
||||||
This python script utilizes linux's hwmon interface and a PID controller for fan controlling. No external dependencies besides simple_pid are needed.
|
This python script utilizes linux's hwmon interface and a PID controller for fan controlling. No external dependencies besides simple_pid and PyYAML are needed.
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
loglevel: DEBUG
|
loglevel: DEBUG
|
||||||
|
interval: 1
|
||||||
|
|
||||||
thermalzones:
|
thermalzones:
|
||||||
- name: GPU+SYSTEM
|
- name: GPU+SYSTEM
|
||||||
hwmon: amdgpu
|
|
||||||
source: amdgpu/temp1_input
|
source: amdgpu/temp1_input
|
||||||
factor: 1000
|
factor: 1000
|
||||||
fan:
|
fan:
|
||||||
@@ -14,11 +14,10 @@ thermalzones:
|
|||||||
i: 1
|
i: 1
|
||||||
d: 1.5
|
d: 1.5
|
||||||
- name: CPU
|
- name: CPU
|
||||||
hwmon: it8686
|
|
||||||
source: coretemp/temp1_input
|
source: coretemp/temp1_input
|
||||||
factor: 1000
|
factor: 1000
|
||||||
fan:
|
fan:
|
||||||
- it8686/pwm1
|
- it8686/pwm1: [100, 200]
|
||||||
target: 50
|
target: 50
|
||||||
pid:
|
pid:
|
||||||
p: 1
|
p: 1
|
||||||
|
32
pyfan.py
32
pyfan.py
@@ -20,7 +20,6 @@ class ThermalZone:
|
|||||||
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.hwname = config["hwmon"]
|
|
||||||
self.hwmap = hwmon_map
|
self.hwmap = hwmon_map
|
||||||
self.alias_replace = re.compile('|'.join(self.hwmap.keys()))
|
self.alias_replace = re.compile('|'.join(self.hwmap.keys()))
|
||||||
self.setup_pwm()
|
self.setup_pwm()
|
||||||
@@ -37,14 +36,28 @@ class ThermalZone:
|
|||||||
def eval(self):
|
def eval(self):
|
||||||
if self.get_temp():
|
if self.get_temp():
|
||||||
diff = self.target - self.get_temp()
|
diff = self.target - self.get_temp()
|
||||||
val = self.pid(diff)
|
val = int(self.pid(diff))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for target_fan in self.fans:
|
for target_fan in self.fans:
|
||||||
if type(target_fan) is dict:
|
if type(target_fan) is dict:
|
||||||
self.write_sysfs(list(target_fan.keys())[0], min(int(val), list(target_fan.values())[0]))
|
fan = list(target_fan.keys())[0]
|
||||||
|
fan_val = list(target_fan.values())[0]
|
||||||
|
|
||||||
|
if type(fan_val) is list:
|
||||||
|
if len(fan_val) < 2:
|
||||||
|
logging.getLogger("pyfan").warning(
|
||||||
|
"[%s] max/min for %s was not set correctly (%s)" % (self.name, fan, fan_val))
|
||||||
|
|
||||||
|
self.write_sysfs(fan, min(fan_val[1], max(val, fan_val[0])))
|
||||||
else:
|
else:
|
||||||
self.write_sysfs(target_fan, int(val))
|
self.write_sysfs(fan, min(val, fan_val))
|
||||||
|
|
||||||
|
logging.getLogger("pyfan").debug(
|
||||||
|
"[{name}] {fan} is set at {val}%".format(name=self.name, fan=fan,
|
||||||
|
val=int(int(self.read_sysfs(fan)) / 255 * 100)))
|
||||||
|
else:
|
||||||
|
self.write_sysfs(target_fan, val)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
logging.getLogger("pyfan").warning(
|
logging.getLogger("pyfan").warning(
|
||||||
"[%s] Failed to set pwm, trying to reset it. (%s)" % (self.name, err.strerror))
|
"[%s] Failed to set pwm, trying to reset it. (%s)" % (self.name, err.strerror))
|
||||||
@@ -75,8 +88,8 @@ class ThermalZone:
|
|||||||
else:
|
else:
|
||||||
self.set_pwm_mode(target_fan, value)
|
self.set_pwm_mode(target_fan, value)
|
||||||
except FileNotFoundError as err:
|
except FileNotFoundError as err:
|
||||||
logging.getLogger("pyfan").warning("[%s] pwm not found. Not ready yet or wrong path? (%s)" % (self.name,
|
logging.getLogger("pyfan").warning("[%s] pwm not found."
|
||||||
err.strerror))
|
" Not ready yet or wrong path? (%s)" % (self.name, err.strerror))
|
||||||
|
|
||||||
def replace_alias(self, path):
|
def replace_alias(self, path):
|
||||||
replaced = self.alias_replace.sub(lambda x: self.hwmap[x.group()], path)
|
replaced = self.alias_replace.sub(lambda x: self.hwmap[x.group()], path)
|
||||||
@@ -112,6 +125,11 @@ class PyFan:
|
|||||||
self.hwmon_map = {}
|
self.hwmon_map = {}
|
||||||
self.gen_hwmon_map()
|
self.gen_hwmon_map()
|
||||||
|
|
||||||
|
if "interval" in self.config:
|
||||||
|
self.interval = self.config["interval"]
|
||||||
|
else:
|
||||||
|
self.interval = 1
|
||||||
|
|
||||||
for zone in self.config["thermalzones"]:
|
for zone in self.config["thermalzones"]:
|
||||||
self.zones.append(ThermalZone(zone, self.hwmon_map))
|
self.zones.append(ThermalZone(zone, self.hwmon_map))
|
||||||
|
|
||||||
@@ -148,6 +166,6 @@ if __name__ == "__main__":
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
pyfan.eval()
|
pyfan.eval()
|
||||||
sleep(1)
|
sleep(pyfan.interval)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
Reference in New Issue
Block a user