Bananapi r3 mini Fan control Script

Creat a script in /bin/

vim /bin/fan_control
#!/bin/ash

# Temperature sensor path
TEMP_PATH="/sys/class/thermal/thermal_zone0/temp"

# Trip Points for Fan Speed Control
TRIP_0="/sys/class/thermal/thermal_zone0/trip_point_0_temp"
TRIP_1="/sys/class/thermal/thermal_zone0/trip_point_1_temp"
TRIP_2="/sys/class/thermal/thermal_zone0/trip_point_2_temp"
TRIP_3="/sys/class/thermal/thermal_zone0/trip_point_3_temp"
TRIP_4="/sys/class/thermal/thermal_zone0/trip_point_4_temp"

# Temperature thresholds (in millidegrees Celsius)
LOW_TEMP=30000
MEDIUM_TEMP=42000
HIGH_TEMP=49000

VERY_HIGH_TEMP=70000
CRITICAL_TEMP=80000

HYSTERESIS=4000

# Previous fan level (-1 means uninitialized)
PREV_LEVEL=-1

log_message() {
    logger -t fan_control "$1"
}

set_trip_points() {
    local level=$1

    case $level in
        0)  # Fan OFF (stop spinning)
            echo $VERY_HIGH_TEMP > $TRIP_4
            echo $VERY_HIGH_TEMP > $TRIP_3
            echo $VERY_HIGH_TEMP > $TRIP_2
            ;;
        1)  # Low speed
            echo 0 > $TRIP_4
            echo $VERY_HIGH_TEMP > $TRIP_3
            echo $VERY_HIGH_TEMP > $TRIP_2
            ;;
        2)  # Medium speed
            echo 0 > $TRIP_4
            echo 0 > $TRIP_3
            echo $VERY_HIGH_TEMP > $TRIP_2
            ;;
        3)  # High speed
            echo 0 > $TRIP_4
            echo 0 > $TRIP_3
            echo 0 > $TRIP_2
            ;;
    esac

    PREV_LEVEL=$level
}

# Set emergency shutdown temperature
echo $VERY_HIGH_TEMP > $TRIP_1
echo $CRITICAL_TEMP > $TRIP_0

while true; do
    # Read current temperature
    if [ -f "$TEMP_PATH" ]; then
        TEMP=$(cat "$TEMP_PATH")
    else
        log_message "Error: Unable to read temperature from $TEMP_PATH"
        exit 1
    fi

    # Determine fan speed level based on hysteresis control
    case $PREV_LEVEL in
        0)
            if [ "$TEMP" -ge "$LOW_TEMP" ]; then
                LEVEL=1
            else
                LEVEL=0
            fi
            ;;
        1)
            if [ "$TEMP" -ge "$MEDIUM_TEMP" ]; then
                LEVEL=2
            elif [ "$TEMP" -le "$((LOW_TEMP - HYSTERESIS))" ]; then
                LEVEL=0
            else
                LEVEL=1
            fi
            ;;
        2)
            if [ "$TEMP" -ge "$HIGH_TEMP" ]; then
                LEVEL=3
            elif [ "$TEMP" -le "$((MEDIUM_TEMP - HYSTERESIS))" ]; then
                LEVEL=1
            else
                LEVEL=2
            fi
            ;;
        3)
            if [ "$TEMP" -le "$((HIGH_TEMP - HYSTERESIS))" ]; then
                LEVEL=2
            else
                LEVEL=3
            fi
            ;;
        *)
            LEVEL=0  # Default to fan OFF
            ;;
    esac

    # Update fan speed only if the level changes
    if [ "$LEVEL" -ne "$PREV_LEVEL" ]; then
	log_message "Fan speed changed: Level $LEVEL"
        set_trip_points "$LEVEL"
    fi

    sleep 2
done

Add exectuable permission

chmod +x /bin/fan_control

Add service in /etc/init.d

vim /etc/init.d/fan_control
#!/bin/sh /etc/rc.common
# OpenWrt init script for fan_control

USE_PROCD=1
START=99
STOP=10

start_service() {
    procd_open_instance
    procd_set_param command fan_control
    procd_set_param respawn 3600 5 5
    procd_close_instance
}

Add exectuable permission

chmod +x /etc/init.d/fan_control

Start service

/etc/init.d/fan_control enable
/etc/init.d/fan_control start

Now, you can notice the fan is running smoothly, and you can check the status by logread

root@OpenWrt:~# lodread -e fan_control

Sun Mar 30 10:42:41 2025 user.notice fan_control: Fan speed changed: Level 0
Sun Mar 30 10:42:43 2025 user.notice fan_control: Fan speed changed: Level 1
Sun Mar 30 10:42:45 2025 user.notice fan_control: Fan speed changed: Level 2
Sun Mar 30 10:44:07 2025 user.notice fan_control: Fan speed changed: Level 3