[BPI-R4] CPU fan setup

BPI-R4 Fan Control Script

  • Operating Environment
    OpenWrt: 24.10.2

Script

  • pwmfan
# /etc/init.d/pwmfan
cat <<'EOF' > /etc/init.d/pwmfan
#!/bin/sh /etc/rc.common

START=99
PIDFILE=/var/run/pwmfan.pid

start() {
    if [ -f $PIDFILE ]; then
        PID=$(cat $PIDFILE 2>/dev/null)
        if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
            echo "Already running"
            return 1
        else
            rm -f $PIDFILE
        fi
    fi
    /usr/bin/pwmfan-loop &
    echo $! > $PIDFILE
}

stop() {
    if [ -f $PIDFILE ]; then
        PID=$(cat $PIDFILE 2>/dev/null)
        if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
            kill $PID
        fi
        rm -f $PIDFILE
    fi
}

restart() {
    stop
    sleep 1
    start
}
EOF

chmod 755 /etc/init.d/pwmfan

# /usr/bin/pwmfan-loop
cat <<'EOF' > /usr/bin/pwmfan-loop
#!/bin/sh

CONFIG=pwmfan
SECTION="pwmfan"

get_temp() {
    local temp
    temp=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)
    [ -z "$temp" ] && temp=0
    echo $((temp / 1000))
}

set_pwm() {
    local pwm="$1"
    echo 1 > /sys/class/hwmon/hwmon1/pwm1_enable
    echo $pwm > /sys/class/hwmon/hwmon1/pwm1
}

read_config() {
    INTERVAL=$(uci get ${CONFIG}.@${SECTION}[0].interval 2>/dev/null)
    [ -z "$INTERVAL" ] && INTERVAL=30
    TRIP_TEMP=$(uci get ${CONFIG}.@${SECTION}[0].trip_temp 2>/dev/null)
    TRIP_PWM=$(uci get ${CONFIG}.@${SECTION}[0].trip_pwm 2>/dev/null)
    MINPWM=$(uci get ${CONFIG}.@${SECTION}[0].minpwm 2>/dev/null)
    [ -z "$MINPWM" ] && MINPWM=100
    MAXPWM=$(uci get ${CONFIG}.@${SECTION}[0].maxpwm 2>/dev/null)
    [ -z "$MAXPWM" ] && MAXPWM=255

    if [ -z "$TRIP_TEMP" ] || [ -z "$TRIP_PWM" ]; then
        exit 1
    fi
    case "$INTERVAL" in
        ''|*[!0-9]*) INTERVAL=30 ;;
    esac
}

main_loop() {
    read_config
    local temp pwm i t p last_pwm=0
    set -- $TRIP_TEMP
    local trip_count=$#
    while true; do
        temp=$(get_temp)
        pwm=$MINPWM
        set -- $TRIP_TEMP
        local j=1
        for t in $@; do
            set -- $TRIP_PWM
            p=$(eval "echo \$$j")
            [ -z "$p" ] && p=$MINPWM
            [ "$temp" -ge "$t" ] && pwm=$p
            j=$((j+1))
        done
        [ "$pwm" -lt "$MINPWM" ] && pwm=$MINPWM
        [ "$pwm" -gt "$MAXPWM" ] && pwm=$MAXPWM
        if [ "$pwm" != "$last_pwm" ]; then
            set_pwm "$pwm"
            last_pwm=$pwm
        fi
        sleep "$INTERVAL"
    done
}

main_loop
EOF

chmod 755 /usr/bin/pwmfan-loop

touch /etc/config/pwmfan
uci -q delete pwmfan.@pwmfan[0]
uci -q commit pwmfan
uci -q add pwmfan pwmfan
uci -q set pwmfan.@pwmfan[-1].interval='20'
uci -q set pwmfan.@pwmfan[-1].minpwm='80'
uci -q set pwmfan.@pwmfan[-1].maxpwm='255'
uci -q set pwmfan.@pwmfan[-1].trip_temp='60 70'
uci -q set pwmfan.@pwmfan[-1].trip_pwm='128 255'
uci -q commit pwmfan
/etc/init.d/pwmfan enable
/etc/init.d/pwmfan restart

# /usr/bin/fan-status
cat <<'EOF' > /usr/bin/fan-status
#!/bin/sh

TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null)
TEMP_C=$(awk "BEGIN {printf \"%.1f\", $TEMP_RAW/1000}")
PWM=$(cat /sys/class/hwmon/hwmon1/pwm1 2>/dev/null)
PWM_PERCENT=$((PWM * 100 / 255))
echo "========================="
echo " Fan & Temperature Status"
echo "-------------------------"
echo " Temperature : ${TEMP_C} °C"
echo " Fan PWM     : ${PWM} (${PWM_PERCENT} %)"
echo "========================="
EOF

chmod 755 /usr/bin/fan-status
fan-status