How to Tune CPU FAN Speed With PWM on Armbian (cooling-levels based on Temperature)

Written by
Table of Contents
- 1) Confirm you have PWM fan control in Armbian
- 2) Dump the running device tree and locate the fan node
- 3) Understand what you’re editing
- cooling-levels
- rockchip,temp-trips
- 4) Create a Device Tree Overlay to set your fan curve
- A) Choose your fan node path
- B) Write the overlay source (.dtso)
- 5) Compile the overlay to .dtbo
- 6) Enable the overlay in Armbian
- 7) Verify the overlay applied
- 8) Watch PWM change in real time
Armbian images for many SBCs expose a PWM-controlled fan through the Linux thermal framework and a pwm-fan device tree node. If you want the fan to spin up earlier, run quieter, or use your own temperature→PWM mapping without a userspace script, the clean approach is to create a Device Tree Overlay that modifies:
cooling-levels— PWM values (0–255)rockchip,temp-trips— temperature thresholds mapped to those levels (on many Rockchip-based boards)
This post shows a practical, repeatable way to create, install, and enable an overlay on Armbian.
Note: Not every Armbian board uses
rockchip,temp-trips. This guide applies to systems where you can findcooling-levelsandrockchip,temp-tripsunder thepwm-fannode in the running device tree.
1) Confirm you have PWM fan control in Armbian
Check sysfs for PWM control:
ls -R /sys/class/pwm 2>/dev/null
grep -R . /sys/class/hwmon/hwmon*/name 2>/dev/null
ls /sys/class/hwmon/hwmon*/pwm* 2>/dev/null
If you see a pwm1 file under an hwmon device (often named pwmfan), the kernel exposes PWM control.
2) Dump the running device tree and locate the fan node
Install the device tree compiler:
sudo apt update
sudo apt install -y device-tree-compiler
Dump the live device tree (best source of truth because it reflects overlays already applied):
sudo dtc -I fs -O dts -o /tmp/running.dts /proc/device-tree
Search for the fan node and curve properties:
grep -nEi 'pwm-fan|pwmfan|cooling-levels|rockchip,temp-trips|temp-trips' /tmp/running.dts | head -120
You’re looking for something like:
pwm-fan { ... }cooling-levels = <...>;rockchip,temp-trips = <...>;
Also identify the node path for the fan. On many systems it’s /pwm-fan, but don’t assume—verify in running.dts.
3) Understand what you’re editing
cooling-levels
A list of PWM duty values (0–255). Example:
<0 50 100 150 200 255>
Each entry is a cooling “state”.
rockchip,temp-trips
Pairs of:
- temperature (millidegrees C) and
- cooling level index (usually 1..N, where 0 would be off)
Example:
<40000 1 42000 2 45000 3>
Meaning:
- at 40°C use cooling level 1
- at 42°C use cooling level 2
- at 45°C use cooling level 3
Temperatures are in millidegrees C:
45000= 45°C.
4) Create a Device Tree Overlay to set your fan curve
A) Choose your fan node path
From /tmp/running.dts, determine the correct path for the fan node. In the example below we use:
/pwm-fan
If your fan node path differs, update target-path = "/pwm-fan"; accordingly.
B) Write the overlay source (.dtso)
This example sets the curve:
- 40°C → PWM 200
- 42°C → PWM 225
- 45°C+ → PWM 255
sudo tee /root/fan-curve.dtso >/dev/null <<'EOF'
/dts-v1/;
/plugin/;
&{/} {
fragment@0 {
target-path = "/pwm-fan";
__overlay__ {
/*
* Fan PWM steps (0..255):
* level 0 = off
* level 1 = 200
* level 2 = 225
* level 3 = 255
*/
cooling-levels = <0 200 225 255>;
/*
* Temp (milli°C) -> cooling level index
* 40°C -> level 1 (200)
* 42°C -> level 2 (225)
* 45°C -> level 3 (255)
*/
rockchip,temp-trips = <40000 1 42000 2 45000 3>;
};
};
};
EOF
5) Compile the overlay to .dtbo
Armbian typically supports user overlays in /boot/overlay-user/:
sudo mkdir -p /boot/overlay-user
sudo dtc -@ -I dts -O dtb -o /boot/overlay-user/fan-curve.dtbo /root/fan-curve.dtso
Verify the file exists:
ls -l /boot/overlay-user/fan-curve.dtbo
6) Enable the overlay in Armbian
Edit Armbian’s boot environment file:
sudo nano /boot/armbianEnv.txt
Add or update:
user_overlays=fan-curve
If you already have overlays enabled, append it space-separated:
user_overlays=existing-overlay another-overlay fan-curve
Save the file and reboot:
sudo reboot
7) Verify the overlay applied
After reboot, dump the live device tree again:
sudo dtc -I fs -O dts -o /tmp/running2.dts /proc/device-tree
grep -n "cooling-levels" /tmp/running2.dts | head -40
grep -n "rockchip,temp-trips" /tmp/running2.dts | head -40
You should see your updated values (sometimes displayed in hex).
8) Watch PWM change in real time
Find your PWM hwmon device:
for d in /sys/class/hwmon/hwmon*; do
n=$(cat "$d/name" 2>/dev/null)
if echo "$n" | grep -qi pwm; then
echo "$d -> $n"
ls "$d"/pwm* 2>/dev/null
fi
done
Then watch a thermal zone temperature and the PWM value together (adjust paths for your system):
watch -n 1 'cat /sys/class/thermal/thermal_zone0/temp; cat /sys/class/hwmon/hwmon8/pwm1'