Files
radxa-hat/fan.py
2026-04-27 14:11:46 +02:00

109 lines
2.6 KiB
Python

#!/usr/bin/env python3
import os.path
import time
import traceback
import threading
import gpiod
import misc
pin = None
class Pwm:
def __init__(self, chip):
self.period_value = None
try:
int(chip)
chip = f'pwmchip{chip}'
except ValueError:
pass
self.filepath = f"/sys/class/pwm/{chip}/pwm0/"
try:
with open(f"/sys/class/pwm/{chip}/export", 'w') as f:
f.write('0')
except OSError:
print("Waring: init pwm error")
traceback.print_exc()
def period(self, ns: int):
self.period_value = ns
with open(os.path.join(self.filepath, 'period'), 'w') as f:
f.write(str(ns))
def period_us(self, us: int):
self.period(us * 1000)
def enable(self, t: bool):
with open(os.path.join(self.filepath, 'enable'), 'w') as f:
f.write(f"{int(t)}")
def write(self, duty: float):
assert self.period_value, "The Period is not set."
with open(os.path.join(self.filepath, 'duty_cycle'), 'w') as f:
f.write(f"{int(self.period_value * duty)}")
class Gpio:
def tr(self):
while True:
self.line.set_value(1)
time.sleep(self.value[0])
self.line.set_value(0)
time.sleep(self.value[1])
def __init__(self, period_s):
self.line = gpiod.Chip(os.environ['FAN_CHIP']).get_line(int(os.environ['FAN_LINE']))
self.line.request(consumer='fan', type=gpiod.LINE_REQ_DIR_OUT)
self.value = [period_s / 2, period_s / 2]
self.period_s = period_s
self.thread = threading.Thread(target=self.tr, daemon=True)
self.thread.start()
def write(self, duty):
self.value[1] = duty * self.period_s
self.value[0] = self.period_s - self.value[1]
def read_temp():
with open('/sys/class/thermal/thermal_zone0/temp') as f:
t = int(f.read().strip()) / 1000.0
return t
def get_dc(cache={}):
if misc.conf['run'].value == 0:
return 0.999
if time.time() - cache.get('time', 0) > 60:
cache['time'] = time.time()
cache['dc'] = misc.fan_temp2dc(read_temp())
return cache['dc']
def change_dc(dc, cache={}):
if dc != cache.get('dc'):
cache['dc'] = dc
pin.write(dc)
def running():
global pin
if os.environ['HARDWARE_PWM'] == '1':
chip = os.environ['PWMCHIP']
pin = Pwm(chip)
pin.period_us(40)
pin.enable(True)
else:
pin = Gpio(0.025)
while True:
change_dc(get_dc())
time.sleep(1)
if __name__ == '__main__':
running()