Controlling fanspeeds in Linux on PWM motherboards, Thinkpads and ASUS Eee PC

Introduction
In Windows I controlled the fanspeed on my stationary computer by using a ASUS program that read the temperatures. I wanted the same temperature/fanspeed scaling in Linux, so I decided to setup fancontrol, which is a small script that monitors temperatures and fanspeeds and sets the fan at the minimum required level to insure low noise levels.

The following should work on most Linux distributions and with most modern motherboards. For the record I did this on a Ubuntu 8.04 installation with a setup consisting of a ASUS P5W DH Deluxe Digital Home Series motherboard, Gigabyte Triton GZ-XX1CA-SNS casing and a Core 2 Duo E6600 2.4 GHz with a Noctua NH-U12P CPU cooler, see (Hvilke elementer jeg valgte til min nye computer [tjansson.dk]) for more details.

Controlling the speed using PWM
Pulse width modulation (PWM) can be used to control the fan speed on modern motherboards. My ASUS P5W DH is such a motherboard. The PWM values goes from 0 to 255 and can be controlled quite easily:

root@bohr:~# cat /sys/class/hwmon/hwmon0/device/fan1_input
1054
root@bohr:~# echo "50" >  /sys/class/hwmon/hwmon0/device/pwm1
root@bohr:~# cat /sys/class/hwmon/hwmon0/device/fan1_input
390
root@bohr:~# echo "255" >  /sys/class/hwmon/hwmon0/device/pwm1
root@bohr:~# cat /sys/class/hwmon/hwmon0/device/fan1_input
1054

But this solution is a bit to basic. I wish to be able to do this automatically depending on the temperature. This is where fancontrol comes into the picture. fancontrol and the related pwmconfig is a part of the lm_sensors program which is quite easy to install under Ubuntu:

root@bohr:~# aptitude install lm-sensors

The first thing todo is see whether or not the lm_sensors detects anything:

tjansson@bohr:~$ sensors
w83627dhg-isa-0290
Adapter: ISA adapter
VCore:       +1.47 V  (min =  +0.00 V, max =  +1.74 V)
in1:        +12.09 V  (min =  +5.17 V, max =  +3.80 V)   ALARM
AVCC:        +3.25 V  (min =  +0.32 V, max =  +0.51 V)   ALARM
3VCC:        +3.25 V  (min =  +2.21 V, max =  +0.77 V)   ALARM
in4:         +1.37 V  (min =  +0.51 V, max =  +0.80 V)   ALARM
in5:         +1.58 V  (min =  +0.34 V, max =  +0.02 V)   ALARM
in6:         +4.17 V  (min =  +3.30 V, max =  +3.28 V)   ALARM
VSB:         +3.25 V  (min =  +0.00 V, max =  +0.56 V)   ALARM
VBAT:        +3.23 V  (min =  +1.02 V, max =  +0.00 V)   ALARM
Case Fan:   1054 RPM  (min = 5273 RPM, div = 128)  ALARM
CPU Fan:    1054 RPM  (min = 5273 RPM, div = 128)  ALARM
Aux Fan:    1506 RPM  (min =  105 RPM, div = 128)
fan4:       1318 RPM  (min = 10546 RPM, div = 128)  ALARM
fan5:          0 RPM  (min =  215 RPM, div = 128)  ALARM
Sys Temp:    +49.0°C  (high = +92.0°C, hyst = +32.0°C)  sensor = thermistor
CPU Temp:    +47.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = diode
AUX Temp:   +119.0°C  (high = +80.0°C, hyst = +75.0°C)  ALARM  sensor = thermistor

which it clearly did in my case even though it has some funny alarms. To setup fancontrol the first thing to do is run pwmconfig to find the relations between devices in /sys/class/hwmon/hwmon0/device/ and fanspeed. pwmconfig is described as:

This program will search your sensors for pulse width modulation (pwm) controls, and test each one to see if it controls a fan on your motherboard.

To start the config run

root@bohr:~# pwmconfig

And remember to write the information to the file /etc/fancontrol when asked. This is how my file looks (DO NOT COPY-PASTE. SYSTEM SPECIFIC):

root@bohr:~# cat /etc/fancontrol
INTERVAL=5
 
FCTEMPS=hwmon0/device/pwm1=hwmon0/device/temp1_input hwmon0/device/pwm2=hwmon0/device/temp2_input
FCFANS=hwmon0/device/pwm1=hwmon0/device/fan1_input hwmon0/device/pwm2=hwmon0/device/fan2_input
MINTEMP=hwmon0/device/pwm1=40 hwmon0/device/pwm2=40
MAXTEMP=hwmon0/device/pwm1=52 hwmon0/device/pwm2=60
MINSTART=hwmon0/device/pwm1=50 hwmon0/device/pwm2=50
MINSTOP=hwmon0/device/pwm1=45 hwmon0/device/pwm2=100

Running fancontrol on every reboot
Now I have configured everything, so only thing left to do is to run fancontrol. To start fancontrol just write fancontrol in the console as root user (or using sudo). fancontrol will however stop when the console is closed or the computer is rebooted.

The solution to have fancontrol running on every restart is to create a init.d script. The following should be entered in to a file called /etc/init.d/fancontrol

#!/bin/sh
#
# Fancontrol start script.
#
 
set -e
 
# Defaults
DAEMON=/usr/sbin/fancontrol
PIDFILE=/var/run/fancontrol.pid
PATH=/sbin:/bin:/usr/sbin:/usr/bin
test -f $DAEMON || exit 0
. /lib/lsb/init-functions
 
case "$1" in
        start)
                log_begin_msg "Starting fancontrol daemon..."
                start-stop-daemon --start -o -q -m -b -p $PIDFILE -x $DAEMON
                log_end_msg $?
                ;;
        stop)
                log_begin_msg "Stopping fancontrol daemon..."
                start-stop-daemon --stop -o -q -p $PIDFILE
                log_end_msg $?
                ;;
        force-reload|restart)
                sh $0 stop
                sh $0 start
                ;;
        *)
                log_success_msg "Usage: /etc/init.d/fancontrol {start|stop|restart|force-reload}"
                log_success_msg "  start - starts system-wide fancontrol service"
                log_success_msg "  stop  - stops system-wide fancontrol service"
                log_success_msg "  restart, force-reload - starts a new system-wide fancontrol service"
                exit 1
                ;;
esac
 
exit 0

and then the script should be executable and added to rc.d:

root@bohr:~# chmod +x /etc/init.d/fancontrol
root@bohr:~# update-rc.d fancontrol defaults 99 01
 Adding system startup for /etc/init.d/fancontrol ...
   /etc/rc0.d/K01fancontrol -> ../init.d/fancontrol
   /etc/rc1.d/K01fancontrol -> ../init.d/fancontrol
   /etc/rc6.d/K01fancontrol -> ../init.d/fancontrol
   /etc/rc2.d/S99fancontrol -> ../init.d/fancontrol
   /etc/rc3.d/S99fancontrol -> ../init.d/fancontrol
   /etc/rc4.d/S99fancontrol -> ../init.d/fancontrol
   /etc/rc5.d/S99fancontrol -> ../init.d/fancontrol

Monitoring the temperatures
Personally I use gkrellm, see image, to monitor the temperatures and fanspeeds but there are lots of programs out there, such as xsensors.

Special cases
A friend of my Kåre H. Jensen made a special script for controlling the ASUS Eee PC

For Thinkpad owners there is nice program called tpfand which I have written about on this page Server setup [tjansson.dk] under the section called Noisy fan.

References
Fan speed control [wiki.archlinux.org]
HOWTO: Fancontrol [ubuntuforums.org]

Only registered users can comment.

  1. Hey nice tutorial but I have a question –
    Are these fans connected to your mother board?

    Case Fan: 1054 RPM (min = 5273 RPM, div = 128) ALARM
    Aux Fan: 1506 RPM (min = 105 RPM, div = 128)

    Because I am working on a system which has a separate panel which has these fans connected to it and that panel doesnt have a sensor hence I aint getting any RPM values for it.

    Do you know any application which manages USB fans?

    Thanks
    Vik

  2. Hi,

    I have the same mobo (and the same Noctua NH-U12P CPU cooler too :-). I was wandering if you know what is the “AUX temp” 119 °C on your mobo and 127 °C on mine. Is that normal ?

    thanks

  3. No – I haven’t really figured that out. I am quite sure nothing is above 100 degrees inside my computer so I think it is unused or uncalibrated sensor?

  4. Here’s a script I wrote for running my fan on a dell laptop (note: it depends on i8kutils, including loading the i8k module into the kernel at boot time):
    #!/bin/bash
    #Author Jay DeYoung
    #You may find my temperatures overly conservative- I like my laptop cool
    #All in celcius.
    #i8k has three speeds, off, 1, and 2.
    fan0=25 #need to incorporate this
    fan1=30 #temperature to turn fan on to 1
    fan2=43 #temperature to turn fan on to 2
    fanBack1=35 #turn fan back to 1
    fanBack0=25

    #currently not used.
    minFan2=30 #minium time for fan to be spinning on mode two (seconds)
    minFan1=0 #minimum time for fan to be spinning on mode one (seconds)
    while true; do
    i=`i8kctl temp`
    if [ “$i” -ge “$fan1” ] ; then
    while [ “$i” -ge “$fanBack0” ] ; do
    if [ “$i” -ge “$fan2” ] ; then
    while [ “$i” -ge “$fanBack1” ] ; do
    echo “$i”
    i8kfan 2 2 >> /dev/null
    sleep 2s
    i=`i8kctl temp`
    done
    fi
    echo “$i”
    i8kfan 1 1 >> /dev/null
    sleep 2s
    i=`i8kctl temp`
    done
    i8kfan 0 0 >> /dev / null
    sleep 2 s
    fi
    done

  5. I know this is and old entry, but let’s see if I’m lucky. I have a problem related with the beginning of this entry:

    I have a NAS running with Debian:

    Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1 (2015-05-24) x86_64 GNU/Linux

    I wan’t to control the FAN speed depending of the highest temperature of the HDDs. To do it, I use a python script that reads temperatures and then writes the right value to /sys/class/hwmon/hwmon1/device/pwm3 using cron.

    The script works, it is able to write the right value to pwm3 and the speed of the fan changes. The problem is another unknown program in the computer is changing back the power value to 80.

    Before I was using fancontrol and after running the configuration program pwmconfig, my script worked fine, the right power values were applied to pwm3 and they remain there. But everytime I rebooted I had to run again pwmconfig.

    Thinking that maybe fancontrol was controlling the fan speed even though I didn’t have any configuration saved, I totally purged fancontrol (so I cannot run pwmconfig anymore), but the problem persists. Every time I change the value of pwm3, it returns back to 80 after ~0.5 secs.

  6. Hey, suddenly my fan was scratching smth. inside and was very noisy ( as shit ). So, that was a mechanism’s problem. You should just fix it by putting some oil inside its axis. That helped me ..

    HAPPY NEW YEAR )))

  7. Hi! I have a few commands failing after an apt-get upgrade in ubuntu 14.02. My new kernel is 3.13.0-125-generic, and my fan speed control script is using the following commands:
    $ echo 1 > /sys/class/hwmon/hwmon0/device/pwm4_enable
    $ echo 180 > /sys/class/hwmon/hwmon0/device/pwm4

    But both commands are telling “file not found”. I can see radical changes in device control directory:
    $ ls /sys/class/hwmon/hwmon0/device/
    driver/ subsystem/ temp2_max temp3_max
    hwmon/ temp2_crit temp3_crit uevent
    modalias temp2_crit_alarm temp3_crit_alarm
    name temp2_input temp3_input
    power/ temp2_label temp3_label

    Where could I read about this changes? Do you know something about them?

    Thanx in advance.

    1. Hi Pepe

      I have not looked much at fan speeds for the last 5 years, so I am not aware of any changes and cannot help you.

      It might very well be that the naming have changes in recent kernels. My article was based on Ubuntu 8.04, so your version is 6 years newer and things have probably changed. The newest long support version of Ubuntu is 16.04.2, so that is also a couple of years newer.

      1. Thanx for your response.

        It seems the conflict was caused by Virtualbox. I’ve upgraded its version too and voila! All is under control right now.

        Thanx again.

  8. Hello Thomas, i’ve read your article and it’s good, however i need to have a better control of the chassis fan since i have to relate its speed to the nvidia gpu temperature, and here i’d like to know a little bit more about what i’m trying to solve.
    Basically i started using this script: http://dan.bodar.com/2016/03/03/linking-nvidia-gpu-temperature-with-a-motherboard-pwm-fan-in-linux/ and i modified it setting the right path to the pwm controlled fan and i used and for the function temperature i used nvidia-smi in order to get the temp of my gpu.

    One of the problems i’m facing is i get : trap: SIGHUP: bad trap launching: sh nameofthescript even if i set #!/usr/bin/env bash on the top of the script.

    i’m running Debian 9.3 stretch 4.9.0-4-amd64

    if i comment the line with SIGHUP i get :gpu_fancontrol: 36:gpu_fancontrol: Syntax error: “(” unexpected

    it’s like the shebang line is not working and i’m still using dash…

Leave a Reply