5

I have a Raspberry Pi 5 with the official cooler/fan. The firmware enables it from 50°C and up in different steps. I'd like to control it manually, which is possible by writing the steps to /sys/class/thermal/cooling_device0/cur_state:

echo '4' | sudo tee -a /sys/class/thermal/cooling_device0/cur_state

0 disables the fan, while 1 is the first 50°C step (30% speed), 2 the second (50%) and so on. 4 is the last one, which leads to 100% fan speed. This works, but only for 1-2 seconds. It seems that the firmware is resetting my custom changes.

What doesn't work

I tried to disable the fan in the /boot/config.txt:

$ grep cooling /boot/config.txt 
dtparam=cooling_fan=off

Using pinctrl it's possible to set some changes, which are not overwritten by the firmware:

# Disabling the fan
pinctrl FAN_PWM op dh
# 100% fan speed
pinctrl FAN_PWM op dl
# Letting the firmware automatically control the fan again
pinctrl FAN_PWM a0

This works until the next reboot. But I'm very limited, since I can only choose between 0% (fan disabled) and 100% fan speed.

My question

How can we disable the automatic firmware, so that the 4 steps (+1 to disable) in /sys/class/thermal/cooling_device0/cur_state are kept longer (at least to the next reboot) instead of just for 1-2 seconds?

2
  • Have you tried combining those? Ie., disable it with pinctrl, then use the sysfs interface to set the speed.
    – goldilocks
    Commented Jan 1 at 21:55
  • @goldilocks Yes, it seems that pinctrl FAN_PWM op dh disables /sys/class/thermal/cooling_device0/cur_state because echo '4' | sudo tee -a /sys/class/thermal/cooling_device0/cur_state doesn't have any effect any more. And the file keeps 4 even after several seconds, so no firmware touch it, but it seems also not to be used.
    – Lion
    Commented Jan 1 at 22:11

2 Answers 2

4

I also searched for a few days and didn't find what I was looking for.

So for me (with the official Raspbian) and without any modifications it actually works amazingly easy.

I use the official case with integrated fan.

I don't know if I'm allowed to post the link where I found the solution.


So just for your information:

  • Disable the fan:
    pinctrl FAN_PWM op dh

  • 100% fan speed:
    pinctrl FAN_PWM op dl

  • Let the firmware automatically control the fan again:
    pinctrl FAN_PWM a0


To change the fan control, you must edit the file /boot/firmware/config.txt.

Information about the settings, from /boot/firmware/overlays/README:

  • fan_temp0: Temperature threshold (in millicelcius) for 1st cooling level (default 50000). Pi5 only.

  • fan_temp0_hyst: Temperature hysteresis (in millicelcius) for 1st cooling level (default 5000). Pi5 only.

  • fan_temp0_speed: Fan PWM setting for 1st cooling level (0-255, default 75). Pi5 only.

  • fan_temp1: Temperature threshold (in millicelcius) for 2nd cooling level (default 60000). Pi5 only.

  • fan_temp1_hyst: Temperature hysteresis (in millicelcius) for 2nd cooling level (default 5000). Pi5 only.

  • fan_temp1_speed: Fan PWM setting for 2nd cooling level (0-255, default 125). Pi5 only.

  • fan_temp2: Temperature threshold (in millicelcius) for 3rd cooling level (default 67500). Pi5 only.

  • fan_temp2_hyst: Temperature hysteresis (in millicelcius) for 3rd cooling level (default 5000). Pi5 only.

  • fan_temp2_speed: Fan PWM setting for 3rd cooling level (0-255, default 175). Pi5 only.

  • fan_temp3: Temperature threshold (in millicelcius) for 4th cooling level (default 75000). Pi5 only.

  • fan_temp3_hyst: Temperature hysteresis (in millicelcius) for 4th cooling level (default 5000). Pi5 only.

  • fan_temp3_speed: Fan PWM setting for 4th cooling level (0-255, default 250). Pi5 only.


Simply insert the following at the end.

dtparam=fan_temp0=47000
dtparam=fan_temp0_hyst=6000
dtparam=fan_temp0_speed=165

You have to set all 4 (changing the number from 0 to 1/2/3 and your speeds and timings.

Sorry, I would just like to write the text here as normal and send my config. However, this editor is completely buggy. With the above description text I could copy-paste and with my config now again not without always having everything in an extra paragraph.

Unfortunately, I cannot simply use every single line of the editor. Quite strange. But this is also my first time here. I registered to answer this question.

1
  • My setting is this: dtparam=fan_temp0=47000 dtparam=fan_temp0_hyst=6000 dtparam=fan_temp0_speed=165 dtparam=fan_temp1=52000 dtparam=fan_temp1_hyst=6000 dtparam=fan_temp1_speed=190 dtparam=fan_temp2=57000 dtparam=fan_temp2_hyst=6000 dtparam=fan_temp2_speed=215 dtparam=fan_temp3=61000 dtparam=fan_temp3_hyst=6000 dtparam=fan_temp3_speed=255 Getting temperatures with low usage at 46°C and with 100% at 62°C
    – H-OS
    Commented Feb 4 at 0:46
0

TLDR: I created a little bash script to manually take control of the fan here

Details

You can provide fixed control by manually setting the pwm config for the respective PWM controller. To do so, you have to first unload the pwm_fan driver

$ rmmod pwm_fan

You can then export and activate the pwm channel and manually set the fan speed. First you have to identify the correct controller and channel. Here its PWM1_CHAN3.

$ pinctrl FAN_PWM
45: a0    pd | hi // FAN_PWM/GPIO45 = PWM1_CHAN3

You then export the channel for usage via sysfs

$ cd /sys/class/pwm/pwmchip0
$ echo 3 > export

You should now see /sys/class/pwm/pwmchip0/pwm3

$ ls /sys/class/pwm/pwmchip0/pwm3/
capture  duty_cycle  enable  period  polarity  power  uevent

Finally, you need to enable the channel and set a duty_cycle

$ echo 1 > enable
$ echo 10000 > duty_cycle

The fan should now spin at a low rate, where higher values written to duty_cycle mean higher RPM. The common settings 1-4 available via echo '4' | sudo tee -a /sys/class/thermal/cooling_device0/cur_state correspond roughly to 10000, 20000, 30000 and 40000, respectively. See the period below, for the maximum legal value.

Notes

  • I am using Ubuntu Server 23.10 64bit on my Pi5. So yours may be slightly different if using another OS.

  • I would assume there is an easier way to achieve this, but I haven't found it yet.

  • It seems that after unloading the pwm_fan driver, there is no way of monitoring the actual fan speed.

  • The specific numbers (e.g. number of the pwm channel, period for the pwm channel, etc. may be different on your device.

  • A more detailed explanation of the sysfs interface for pwm can be found here

  • My final configuration for a non-audible fan looks like this

    $ tail -n +1 enable polarity period duty_cycle
    ==> enable <==
    1
    
    ==> polarity <==
    inversed
    
    ==> period <==
    41566
    
    ==> duty_cycle <==
    15000
    

    where duty_cycle and period are numbers in nanoseconds and duty_cycle configures the fan speed, meaning the fan spins at 100% if duty_cycle is set to 41566. In my case, the fan starts spinning around a duty cycle of roughly 5000 (yours may be different).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.