Files
gpu-fan-ctrl/scripts/gpu_fan_ctrl.sh
T
2026-10-11 17:22:33 +03:00

99 lines
2.6 KiB
Bash

#!/bin/bash
# GPU Fan Controller — Delta QFR1212GHE
# Режимы: 2=STANDBY(<25), 3=LOW(<30), 4=MED(<35), 5=HIGH(<40), 6=FULL(>45 или burst)
# Режим 1 (STOP) — не используется, фан всегда крутится минимум на standby.
# Порог burst: temp > 45°C ИЛИ рост >= 3°C за 2 секунды.
LOG=/root/gpu_fan.log
DEV=/dev/ttyUSB0
stty -F "$DEV" 115200
exec 3>"$DEV"
exec 1>>"$LOG" 2>&1
# Пороги
TH_COLD=25
TH_LOW=30
TH_MED=35
TH_HIGH=40
TH_BURST=45
TH_BURST_ROISE=3
BURST_WINDOW=2
BURST_DURATION=120
# Хистерезис (мёртвая зона 2°)
HYST=2
prevTemp=0
prevTime=0
burstTimer=0
lastMode=0
noDataCount=0
echo "[START] $(date) GPU Fan Ctrl PID=$$"
while true; do
TEMP=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader -i 0 | tr -cd '0-9')
now=$(date +%s)
if [ -z "$TEMP" ] || ! [ "$TEMP" -gt 0 ] 2>/dev/null; then
noDataCount=$((noDataCount + 1))
if [ $noDataCount -ge 10 ]; then
echo "[ERROR] nvidia-smi failed 10+ times, aborting"
exit 1
fi
sleep 1; continue
fi
noDataCount=0
# Burst: temp rose TH_BURST_ROISE in BURST_WINDOW
if [ $prevTemp -gt 0 ] && [ $((prevTime != 0 ? now - prevTime : 99999)) -le $BURST_WINDOW ]; then
rise=$((TEMP - prevTemp))
if [ $rise -ge $TH_BURST_ROISE ]; then
burstTimer=$BURST_DURATION
echo "[BURST-rise] rise=$rise°C in $((now-prevTime))s → mode 6"
fi
fi
# Если в burst-режиме — держим режим 6
if [ $burstTimer -gt 0 ]; then
burstTimer=$((burstTimer - 1))
if [ $lastMode -ne 6 ]; then
echo "[MODE 6] full speed (burst, ${burstTimer}s remain)"
lastMode=6
echo "6" >&3
fi
prevTemp=$TEMP; prevTime=$now
sleep 1; continue
fi
# Если burst истёк И temp >= TH_BURST — новый burst
if [ $TEMP -ge $TH_BURST ]; then
burstTimer=$BURST_DURATION
echo "[MODE 6] full speed (re-burst: $TEMP°C)"
lastMode=6; prevTemp=$TEMP; prevTime=$now
echo "6" >&3
sleep 1; continue
fi
# Обычная логика с хистерезисом
newMode=5 # default: HIGH (35-39)
if [ $TEMP -lt $((TH_COLD - HYST)) ]; then
newMode=2 # STANDBY (< 23)
elif [ $TEMP -lt $((TH_LOW - HYST)) ]; then
newMode=3 # LOW (< 28)
elif [ $TEMP -lt $((TH_MED - HYST)) ]; then
newMode=4 # MED (< 33)
fi
# Отправляем только если режим изменился
if [ $newMode -ne $lastMode ]; then
echo "[MODE $newMode] temp=$TEMP°C (hysteresis: no-change zone)"
lastMode=$newMode
echo "$newMode" >&3
fi
prevTemp=$TEMP; prevTime=$now
sleep 1
done