Banana Pi BPI-R3 Mini, 5G module, heatsink and fan

Hi guys,

i need some suggestions… I’m currently creating my own 5G router using the R3-Mini with a Quectel RM502Q-GL. This module inside the board is very “hot”, normally sitting at 65°C (registered to 5G but in idle), and can hit 85°C while in use.

So I want to put a little heatsink on top of it, but the problem can be the FAN. How many mm space are avaliable between latest M.2 slot and the FAN? The most thin heatsink i’ve found is 5mm

Any suggestion on how to configure FAN PWN? I’ve tried this configuration but the fan start and stop all the time, not so much useful

echo 35000 > /sys/class/thermal/thermal_zone0/trip_point_4_temp
echo 45000 > /sys/class/thermal/thermal_zone0/trip_point_3_temp
echo 55000 > /sys/class/thermal/thermal_zone0/trip_point_2_temp

Thanks in advance!

I noticed that r3mini inside the vendor case is really hot when touching the case…i have “only” 45-50°C but case is nearly same temperature…too much imho.

So i used these settings

root@bpi-r3-mini:~# echo 45000 > /sys/class/thermal/thermal_zone0/trip_point_3_temp
root@bpi-r3-mini:~# echo 55000 > /sys/class/thermal/thermal_zone0/trip_point_2_temp

With similar result…case is touchable,but fan goes on and off in ~ 5sec steps…maybe we can do something with the other config points in sysfs.

currently i’m using this one to keep FAN always-on at medium level

echo 35000 > /sys/class/thermal/thermal_zone0/trip_point_3_temp

5G module can go up to 75°C, while the other part of the unit is touchable… anyway there is no space for 5mm heatsink on the 5G module, so I think fan should be on to avoid overheat :frowning:

Here’s how I control the fan

Creat /bin/fan_control

#!/bin/bash

# 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          # 30C
MEDIUM_TEMP=42000       # 42C
HIGH_TEMP=54000         # 54C

VERY_HIGH_TEMP=70000    # 70C
CRITICAL_TEMP=80000     # 80C

HYSTERESIS=5000         # 5C (to prevent frequent fan speed changes)

# Previous fan level (-1 means uninitialized)
PREV_LEVEL=-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
        echo "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
        set_trip_points "$LEVEL"
    fi

    sleep 2
done

chmod +x /bin/fan_control

Then add ‘fan_control &’ to /etc/rc.local, also you can add this to Luci > System > Startup

cwxiaos,

I followed your instructions above, but don’t hear or see the fan start on my Banana Pi R3 mini.

I created a file under /bin called “fan_control” by typing the command “vi fan_control”. I pasted your code in to this file and then saved and exited the file by typing “:wq”. At the command prompt I typed chmod +x /bin/fan_control.

Under SYSTEM->Startup->Local Startup i added fan_control & to the etc/rc.local.

Not sure why the fan doesn’t turn on? What should I check?

Thanks.

Eric

Hi Eric,

First check the temp of your router

cat /sys/class/thermal/thermal_zone0/temp

Which looks like this:

root@OpenWrt:~# cat /sys/class/thermal/thermal_zone0/temp
44650

In my script, the fan will only work when temp is greater than each level. And in level 1 and level 2, there almost has no noise, you can use your finger to check if there is actually a wind(very small).

To activate max speed of the fan, the temp need to greater than 54000, you can run iperf or something else the make the cpu get a higher temp.

Or you can simply modify the script, to see if its actually work:

# Temperature thresholds (in millidegrees Celsius)
LOW_TEMP=10000          # 30C
MEDIUM_TEMP=10000       # 42C
HIGH_TEMP=10000         # 54C

and get the fan trip zero config:

cat /sys/class/thermal/thermal_zone0/trip_point_0_temp
cat /sys/class/thermal/thermal_zone0/trip_point_1_temp
cat /sys/class/thermal/thermal_zone0/trip_point_2_temp
cat /sys/class/thermal/thermal_zone0/trip_point_3_temp
cat /sys/class/thermal/thermal_zone0/trip_point_4_temp
cat /sys/class/thermal/thermal_zone0/temp

in my router, it looks like this:

root@OpenWrt:~# bash get_fan.sh 
80000
70000
70000
0
0
47217
root@OpenWrt:~# 

which means: current temp is 47217, fan speed level is 2.

And another thing important is rc.local, you need to add the command before ‘exit 0’:

Cwxiaos,

Thanks for the detailed reply. I ran the cat commands and see the following:

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_0_temp

125000

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_1_temp

120000

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_2_temp

115000

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_3_temp

85000

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_4_temp

60000

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/temp

47338

I’ll modify the script to lower temperatures to see if the fan is working. I used a flashlight to look through the case to see if the fan was turning. I might also manually edit the trip points.

I’m running the Golden Orb/Rooter firmware on my R3 mini.

Thanks.

Eric

I modified the script to the values you suggested but the fan is still not turning on. I think the problem is trip_point_x_temp values are too high.

I’m going to try to edit them to see if that has any effect on the fan.

Thanks.

Eric

I just modified the trip_point_x_temp values to match yours and the fan is working. Excellent!!!

Thank you.

Eric

The script absolutely not started, you can start the script manually by just run it:

root@OpenWrt:~# fan_control 


At least, trip_4 is 0:

root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_4_temp

60000

# It shoud like this
root@Bretzel:~# cat /sys/class/thermal/thermal_zone0/trip_point_4_temp

0

No, its just spining, not auto adjust speed.

Make sure your rc.local like this:

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

fan_control &

exit 0

Hmmmm…restarted the R3 mini and the trip_point_x_temp values reset to the 125000; 120000; 115000; 85000; 60000?

When I type in fan_control at the command prompt it aays not found:

root@Bretzel:~# fan_control

-ash: fan_control: not found

root@Bretzel:~#

Can you excute:

ls /bin

Yes,

My rc.local looks like this:


# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

fan_control &

exit 0

Yes, I see the fan_control file under /bin:

root@Bretzel:/bin# ls -lrt
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 zcat -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 vi -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 uname -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 umount -> busybox
-rwxr-xr-x    1 root     root         65564 Dec 26 11:24 uclient-fetch
-rwxr-xr-x    1 root     root         65552 Dec 26 11:24 ubus
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 true -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 traceroute6 -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 traceroute -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 touch -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 tar -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 sync -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 sleep -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 sh -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 sed -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 rmdir -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 rm -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 pwd -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ps -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ping6 -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ping -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 pidof -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 passwd -> busybox
-rwxr-xr-x    1 root     root        200187 Dec 26 11:24 opkg
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 nice -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 netstat -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 netmsg -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 mv -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 mount -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 mktemp -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 mknod -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 mkdir -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ls -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 login -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 lock -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ln -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 kill -> busybox
-rwxrwxr-x    1 root     root          2953 Dec 26 11:24 ipcalc.sh
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 gzip -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 gunzip -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 grep -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 fsync -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 fgrep -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 false -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 egrep -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 echo -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 dmesg -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 df -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 dd -> busybox
lrwxrwxrwx    1 root     root            27 Dec 26 11:24 date -> /usr/libexec/date-coreutils
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 cp -> busybox
-rwxrwxr-x    1 root     root         11952 Dec 26 11:24 config_generate
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 chown -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 chmod -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 chgrp -> busybox
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 cat -> busybox
-rwxr-xr-x    1 root     root        458773 Dec 26 11:24 busybox
-rwxrwxr-x    1 root     root           205 Dec 26 11:24 board_detect
lrwxrwxrwx    1 root     root             7 Dec 26 11:24 ash -> busybox
-rwxr-xr-x    1 root     root          2911 Mar 26 10:03 fan_control

You need to install bash

opkg update
opkg install bash

I’ll have to recompile the Golden Orb/Rooter firmware to include bash. I’ll do that this afternoon. Thanks!

Eric

You can ask gpt to port that script to ash, can you test this:

#!/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=40000
MEDIUM_TEMP=47000
HIGH_TEMP=54000
VERY_HIGH_TEMP=70000
CRITICAL_TEMP=80000

HYSTERESIS=4000

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

set_trip_points() {
    level=$1

    case "$level" in
        0)  # Fan OFF
            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
        echo "Error: Unable to read temperature from $TEMP_PATH"
        exit 1
    fi

    # Determine fan speed level based on hysteresis control
    case "$PREV_LEVEL" in
        0)
            [ "$TEMP" -ge "$LOW_TEMP" ] && LEVEL=1 || LEVEL=0
            ;;
        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)
            [ "$TEMP" -le "$((HIGH_TEMP - HYSTERESIS))" ] && LEVEL=2 || LEVEL=3
            ;;
        *)
            LEVEL=0  # Default to fan OFF
            ;;
    esac

    # Update fan speed only if the level changes
    [ "$LEVEL" -ne "$PREV_LEVEL" ] && set_trip_points "$LEVEL"

    sleep 2
done

cwxiaos,

Changing to #!/bin/ash worked. Thanks!!

Eric