6

The fan speed control when running Ubuntu 23.10 on a Raspberry Pi 5 does not appear to be working. The fan runs at near maximum speed all the time and the cur_state in /sys/class/thermal/cooling_device0/ is stuck at the value of 4 no matter what the CPU temperature. I suspect it is related to this fault reported on Raspberry Pi OS: https://forums.raspberrypi.com/viewtopic.php?t=356881

Anyone else had any success with this?

4
  • 5 just came out. Did you mean 4b or 5? There isn't a 5b.
    – rtaft
    Commented Oct 26, 2023 at 20:20
  • 1
    Sorry,I meant 5, slip of the keyboard ;-) Commented Oct 27, 2023 at 7:55
  • 1
    Bug reports and problems specific to development version of Ubuntu should be reported on Launchpad so that developers can see, track and fix these issues.
    – stumblebee
    Commented Oct 28, 2023 at 3:47
  • Just use Kernel version 6.1.1 or whatever works. Commented Nov 5, 2023 at 23:56

4 Answers 4

3

This has since been fixed as part of a kernel update.

You can update your Ubuntu Server installation with:

sudo apt update
sudo apt upgrade

After a reboot, the fan speed will behave as expected.

2

There is now a patch to a kernel build in ppa:waveform/fan-fix (https://launchpad.net/~waveform/+archive/ubuntu/fan-fix) which should serve as a temporary fix until the next kernel release. This allows the fan speed control to work ,but there is some concern that the hysteresis is being ignored, so this may not be the final fix.

1
  • I've been looking for this for a while now; I have 2 RP4 with POE+ hats and I had to hardcode the fans state to 3, but the noise was really annoying. I also posted the question in raspberrypi.stackexchange.com but it was down-voted and deleted, Thanks @Steve Pringle for the link to the kernel patch PPA, this definitely solved the issue! Commented Dec 5, 2023 at 15:21
0

Its annoying, what I've been doing is just swapping the value until we get a new stable kernel:

sudo bash
cat > /sys/class/thermal/cooling_device0/cur_state
2
<CTRL-D>
0

I was also annoyed by this and decided to let Python do all the work. Feel free to use this https://pastebin.com/SbFb4LYE .

from subprocess import run as srun, PIPE
from time import sleep
from datetime import timedelta as td, datetime as dt
 
## Use step values to activate desired FAN value
STEP1 = 48
STEP2 = 60
STEP3 = 65
STEP4 = 72
 
SLEEP_TIMER = 1
 
TICKS = 3
DELTA_TEMP = 3
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
fanControlFile = '/sys/class/thermal/cooling_device0/cur_state'
 
def main():
    print("Running FAN control for RPI5 Ubuntu")
    t0 = dt.now()
 
    command = f'tee -a {fanControlFile} > /dev/null'
    oldSpeed = 0
    ticks = 0
 
    speed = 1
    lastTemp = 0
 
    while True:
        sleep(SLEEP_TIMER) # force 1 second timer, just to reduce polling calls
        t1 = dt.now()
        if(t1 + td(minutes=TICKS) > t0):
            t0 = t1
            
            tempOut = getOutput('vcgencmd measure_temp')
            try:
                cels = int(tempOut.split('temp=')[1][:2])
            except:
                cels = 40
 
            if STEP1 < cels < STEP2:
                speed = 1
            elif STEP2 < cels < STEP3:
                speed = 2
            elif STEP3 < cels < STEP4:
                speed = 3
            elif cels >= STEP4:
                speed = 4
 
            deltaTempNeg = lastTemp - DELTA_TEMP
            deltaTempPos = lastTemp + DELTA_TEMP
 
            if oldSpeed != speed and not(deltaTempNeg <= cels <= deltaTempPos):
                print(f'oldSpeed: {oldSpeed} | newSpeed: {speed}')
                print(f'{deltaTempNeg}ºC <= {cels}ºC <= {deltaTempPos}ºC')
                print(f'{"#"*30}\n' +
                    f'Updating fan speed!\t{t0.strftime(DATETIME_FORMAT)}\n' +
                    f'CPU TEMP: {cels}ºC\n' +
                    f'FAN speed will be set to: {speed}\n' +
                    f'{"#"*30}\n')
                
                _command = f'echo {speed} | sudo {command}'
                callShell(_command, debug=True)
                checkVal = getOutput(f'cat {fanControlFile}')
                print(f'Confirm FAN set to speed: {checkVal}')
                
                oldSpeed = speed
                lastTemp = cels
                ticks = 0
            
            # Log minor details
            ticks += 1
            if(ticks > TICKS * 3):
                ticks = 0
                print(f'Current Temp is: {cels}ºC\t{t0.strftime(DATETIME_FORMAT)}')
    
def callShell(cmd, shell=True, debug=False):
    if debug:
        print(f'Calling: [{cmd}]')
    return srun(f'''{cmd}''', stdout=PIPE, shell=shell)
 
def getOutput(cmd, shell=True):
    stdout = callShell(cmd, shell=shell).stdout
 
    try:
        stdout = stdout.decode('utf-8')
    except:
        pass
 
    return stdout
 
## RUN SCRIPT
main()

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .