|
|
(55 intermediate revisions by 17 users not shown) |
Line 5: |
Line 5: |
| | | |
| {{WARN|These scripts rely on undocumented hardware features and override nominal hardware behavior. They may thus cause arbitrary damage to your laptop or data. Watch your temperatures!}} | | {{WARN|These scripts rely on undocumented hardware features and override nominal hardware behavior. They may thus cause arbitrary damage to your laptop or data. Watch your temperatures!}} |
| + | {{NOTE|Closed-loop fan control requires a thermal sensor sweep, which is an expensive operation. The firmware doesn't update the sensors more than once every 2s, so care should be taken not to waste resources by reading them too often.}} |
| |} | | |} |
| | | |
Line 11: |
Line 12: |
| | | |
| ===Comprehensive <tt>bash</tt> script with fine control over fan speed=== | | ===Comprehensive <tt>bash</tt> script with fine control over fan speed=== |
− | The following requires only [[ibm-acpi]] 0.11 or higher (e.g., as found in kernel 2.6.14 and higher) with the <tt>experimental=1</tt> module parameter. It supports (optional) daemon mode and logging to syslog.
| + | This script works with any recent Linux kernel (2.6.14 and higher). It requires the [[ibm-acpi]] module to be loaded with the <tt>experimental=1</tt> module parameter (e.g., {{cmdroot|1=modprobe ibm_acpi experimental=1}}). |
| | | |
− | This scripts uses a different temperature range for each [[thermal sensors|thermal sensor]], since they have different specs and thermal systems. For each sensor, a fan level is chosen based on the minimum and maximum temperatures configured for that sensor; then the actual fan level is set to the slowest that will satisfy all sensors. There are also some hysteresis features - see the script for the details. The method of controlling fan speed is documented [[How to control fan speed|here]].
| + | In Linux 2.6.22 and higher you need to additionally pass fan_control=1 to the module thinkpad_acpi (e.g., {{cmdroot|1=modprobe thinkpad-acpi experimental=1 fan_control=1}}) |
| | | |
− | Current options:
| + | On Ubuntu > 10.04 or from kernel 2.6.32 onwards: To make the kernel module settings permanent and to make them be executed at boot run below command and reboot afterwards: |
| | | |
− | Usage: ./tp-fancontrol [OPTION]...
| + | {{cmdroot|1=sudo echo "options thinkpad_acpi experimental=1 fan_control=1" >/etc/modprobe.d/thinkpad_acpi.conf}} |
− |
| |
− | Available options:
| |
− | -s N shift up temperature thresholds by N degrees
| |
− | (positive for quieter, negative for cooler)
| |
− | -t test mode
| |
− | -q quiet mode
| |
− | -d daemon mode, go into background (implies -q)
| |
− | -l log to syslog
| |
− | -k kill already-running daemon
| |
− | -u tell already-running daemon that the system is being suspended
| |
− | -p pid file location for daemon mode, default: $PID_FILE
| |
− | {{WARN|The list of temperature ranges used below is much more liberal than the rules used by the embedded controller firmware, and is derived mostly from anecdotal evidence, hunches and wishful thinking. It is also model-specific - see [[thermal sensors]].}} | |
| | | |
− | ====The comprehensive script====
| |
| | | |
− | <pre>
| + | The code lets you define a temperature range for each [[thermal sensors|thermal sensor]]. The script computes the fan level needed by each sensor based on the configured range, and then sets the the actual fan level to the slowest that will satisfy all sensors (plus some hysteresis to avoid fluctiations). It also includes a workaround for the [[Problem with fan noise|pulsing noise]] problem. The script provides an (optional) daemon mode and logging to syslog. The method of controlling fan speed is documented [[How to control fan speed|here]]. |
− | #!/bin/bash
| |
| | | |
− | # tp-fancontrol 0.2.9 (http://thinkwiki.org/wiki/ACPI_fan_control_script)
| + | The system hard disk temperature is monitored as well, using the hard disk's internal sensor. This works only on certain Hitachi disks and requires kernel >= 2.6.19-rc1 or the ide driver, since it uses a [[Thermal Sensors#Hitachi_harddisks_SENSE_CONDITION_temperature_sensor|non-standard method]] for reading the temperature without causing a head unload or spinup. |
− | # Provided under the GNU General Public License version 2 or later or
| |
− | # the GNU Free Documentation License version 1.2 or later, at your option.
| |
− | # See http://www.gnu.org/copyleft/gpl.html for the Warranty Disclaimer. | |
| | | |
− | # This script dynamically controls fan speed on some ThinkPad models
| + | The code: |
− | # according to user-defined temperature thresholds. It implements its
| + | * {{CodeRef|tp-fancontrol}} |
− | # own decision algorithm, overriding the ThinkPad embedded
| |
− | # controller. It also implements a workaround for the fan noise pulse
| |
− | # experienced every few seconds on some ThinkPads.
| |
− | #
| |
− | # Run 'tp-fancontrol --help' for options.
| |
− | #
| |
− | # For optimal fan behavior during suspend and resume, invoke
| |
− | # "tp-fancontrol -u" during the suspend process.
| |
− | #
| |
− | # WARNING: This script relies on undocumented hardware features and
| |
− | # overrides nominal hardware behavior. It may thus cause arbitrary
| |
− | # damage to your laptop or data. Watch your temperatures!
| |
− | #
| |
− | # WARNING: The list of temperature ranges used below is much more liberal
| |
− | # than the rules used by the embedded controller firmware, and is
| |
− | # derived mostly from anecdotal evidence, hunches and wishful thinking.
| |
− | # It is also model-specific (see http://thinkwiki.org/wiki/Thermal_sensors).
| |
| | | |
− | # Temperature ranges, per sensor:
| + | {{WARN|There is a bug in the code which causes the script to exit immediately after start with bash version is 4.1.0(7)-release. The problem line is line 356 which returns zero and cause the script to exit if set -e is called, which is unfortunately true. A simple solution is to append a true expression after the command.}} |
− | # (min temperature: when to step up from 0-th fan level,
| |
− | # max temperature: when to step up to maximum fan level)
| |
− | THRESHOLDS=( # Sensor ThinkPad model
| |
− | # R51 T41/2 Z60t 43-26xx
| |
− | # min max # ---------- ------- ----- ----- ---------------------------
| |
− | 50 70 # EC 0x78 CPU CPU ? CPU
| |
− | 47 60 # EC 0x79 miniPCI ? ? Between CPU and PCMCIA slot
| |
− | 43 55 # EC 0x7A HDD ? ? PCMCIA slot
| |
− | 49 68 # EC 0x7B GPU GPU ? GPU
| |
− | 40 50 # EC 0x7C BAT BAT BAT Sys BAT (front left of battery)
| |
− | 45 55 # EC 0x7D n/a n/a n/a UltraBay BAT
| |
− | 37 47 # EC 0x7E BAT BAT BAT Sys BAT (rear right of battery)
| |
− | 45 55 # EC 0x7F n/a n/a n/a UltraBay BAT
| |
− | 45 60 # EC 0xC0 ? n/a ? Between northbridge and DRAM
| |
− | 48 62 # EC 0xC1 ? n/a ? Southbridge (under miniPCI)
| |
− | 50 65 # EC 0xC2 ? n/a ? Power circuitry (under CDC)
| |
− | 47 60 # HDAPS HDAPS HDAPS HDAPS HDAPS readout (same as EC 0x79)
| |
− | )
| |
| | | |
| + | Current options: |
| | | |
− | LEVELS=( 0 2 4 7) # Fan speed levels
| + | Usage: ./tp-fancontrol [OPTION]... |
− | ANTIPULSE=( 0 1 1 0) # Prevent fan pulsing noise at this level
| + | |
− | # (reduces frequency of fan RPM updates)
| + | Available options: |
− | | + | -s N Shift up the min temperature thresholds by N degrees |
− | OFF_THRESH_DELTA=3 # when gets this much cooler than 'min' above, may turn off fan
| + | (positive for quieter, negative for cooler). |
− | MIN_THRESH_SHIFT=0 # increase min thresholds by this much
| + | Max temperature thresholds are not affected. |
− | MIN_WAIT=180 # minimum time (seconds) to spend in a given level before stepping down
| + | -S N Shift up the max temperature thresholds by N degrees |
− | | + | (positive for quieter, negative for cooler). DANGEROUS. |
− | IBM_ACPI=/proc/acpi/ibm
| + | -t Test mode |
− | HDAPS_TEMP=/sys/bus/platform/drivers/hdaps/hdaps/temp1
| + | -q Quiet mode |
− | LOGGER=/usr/bin/logger
| + | -d Daemon mode, go into background (implies -q) |
− | INTERVAL=3 # sample+refresh interval
| + | -l Log to syslog |
− | SETTLE_TIME=6 # wait this many seconds long before applying anti-pulsing
| + | -k Kill already-running daemon |
− | RESETTLE_TIME=600 # briefly disable anti-pulsing at every N seconds
| + | -u Tell already-running daemon that the system is being suspended |
− | SUSPEND_TIME=5 # seconds to sleep when receiving SIGUSR1
| + | -p Pid file location for daemon mode |
− | | + | {{WARN|The list of temperature ranges used in this script is much more liberal than the rules used by the embedded controller firmware, and is derived mostly from anecdotal evidence, hunches and wishful thinking. It is also model-specific - see [[thermal sensors]].}} |
− | PID_FILE=/var/run/tp-fancontrol.pid
| |
− | QUIET=false
| |
− | DRY_RUN=false
| |
− | DAEMONIZE=false
| |
− | AM_DAEMON=false
| |
− | KILL_DAEMON=false
| |
− | SUSPEND_DAEMON=false
| |
− | SYSLOG=false
| |
− | | |
− | usage() {
| |
− | echo "
| |
− | Usage: $0 [OPTION]...
| |
− | | |
− | Available options: | |
− | -s N shift up temperature thresholds by N degrees | |
− | (positive for quieter, negative for cooler) | |
− | -t test mode | |
− | -q quiet mode | |
− | -d daemon mode, go into background (implies -q) | |
− | -l log to syslog | |
− | -k kill already-running daemon | |
− | -u tell already-running daemon that the system is being suspended | |
− | -p pid file location for daemon mode, default: $PID_FILE | |
− | "
| |
− | exit 1;
| |
− | }
| |
− | | |
− | while getopts 's:qtdlp:kuh' OPT; do
| |
− | case "$OPT" in
| |
− | s) # shift thresholds
| |
− | MIN_THRESH_SHIFT="$OPTARG"
| |
− | ;;
| |
− | t) # test mode
| |
− | DRY_RUN=true
| |
− | ;;
| |
− | q) # quiet mode
| |
− | QUIET=true
| |
− | ;;
| |
− | d) # go into background and daemonize
| |
− | DAEMONIZE=true
| |
− | ;;
| |
− | l) # log to syslog
| |
− | SYSLOG=true
| |
− | ;;
| |
− | p) # different pidfile
| |
− | PID_FILE="$OPTARG"
| |
− | ;;
| |
− | k) # kill daemon
| |
− | KILL_DAEMON=true
| |
− | ;;
| |
− | u) # suspend daemon
| |
− | SUSPEND_DAEMON=true
| |
− | ;;
| |
− | h) # short help
| |
− | usage
| |
− | ;;
| |
− | \?) # error
| |
− | usage
| |
− | ;;
| |
− | esac
| |
− | done
| |
− | [ $OPTIND -gt $# ] || usage # no non-option args
| |
− | | |
− | # no logger found, no syslog capabilities
| |
− | $SYSLOG && [ ! -x $LOGGER ] && SYSLOG=false || :
| |
− | | |
− | if $DRY_RUN; then
| |
− | echo "$0: Dry run, will not change fan state."
| |
− | QUIET=false
| |
− | DAEMONIZE=false
| |
− | fi
| |
− | | |
− | thermometer() { # output list of temperatures
| |
− | # Base temperatures from ibm-acpi:
| |
− | [ -r $IBM_ACPI/thermal ] || { echo "$0: Cannot read $IBM_ACPI/thermal" 2>&1 ; exit 1; }
| |
− | read X Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Z < $IBM_ACPI/thermal
| |
− | Y="$Y1 $Y2 $Y3 $Y4 $Y5 $Y6 $Y7 $Y8"
| |
− | [ "$X" == "temperatures:" ] || { echo "$0: Bad temperatures: $X $Y $Z" >&2; exit 1; }
| |
− | echo -n "$Y ";
| |
− | if [[ "$Z" == *\ *\ * ]]; then # ibm_acpi provided the 3 extra sensors from at EC offsets 0xC0 to 0xC2?
| |
− | echo -n "$Z "
| |
− | else
| |
− | [ -r $IBM_ACPI/ecdump ] || { echo "$0: Cannot read $IBM_ACPI/ecdump" 2>&1; exit 1; }
| |
− | perl -e 'm/^EC 0xc0: .(..) .(..) .(..) / and print hex($1)." ".hex($2)." ".hex($3)." " and exit 0 while <>; exit 1' < $IBM_ACPI/ecdump
| |
− | fi
| |
− | # HDAPS temperature (optional):
| |
− | if [ -r $HDAPS_TEMP ]; then
| |
− | Y="`cat $HDAPS_TEMP`"
| |
− | (( "$Y" > 100 )) || echo -n "$Y " # the HDAPS readouts are nonsensical right after resume
| |
− | fi
| |
− | return 0
| |
− | }
| |
− | | |
− | speedometer() { # output fan speed RPM
| |
− | sed -n 's/^speed:[ \t]*//p' $IBM_ACPI/fan
| |
− | }
| |
− | | |
− | setlevel() { # set fan speed level
| |
− | $DRY_RUN || echo 0x2F $1 > $IBM_ACPI/ecdump
| |
− | }
| |
− | | |
− | getlevel() { # get fan speed level
| |
− | perl -e 'm/^EC 0x20: .* .(..)$/ and print $1 and exit 0 while <>; exit 1' < $IBM_ACPI/ecdump
| |
− | }
| |
− | | |
− | log() {
| |
− | $QUIET || echo "> $*"
| |
− | ! $SYSLOG || $LOGGER -t "`basename $0`[$$]" "$*"
| |
− | }
| |
− | | |
− | cleanup() { # clean up after work
| |
− | $AM_DAEMON && rm -f "$PID_FILE" 2> /dev/null
| |
− | log "Shutting down, switching to automatic fan control"
| |
− | $DRY_RUN || echo enable > $IBM_ACPI/fan
| |
− | }
| |
− | | |
− | floor_div() {
| |
− | echo $(( (($1)+1000*($2))/($2) - 1000 ))
| |
− | }
| |
− | | |
− | init_state() {
| |
− | IDX=0
| |
− | NEW_IDX=0
| |
− | START_TIME=0
| |
− | MAX_IDX=$(( ${#LEVELS[@]} - 1 ))
| |
− | SETTLE_LEFT=0
| |
− | RESETTLE_LEFT=0
| |
− | FIRST=true
| |
− | RESTART=false
| |
− | }
| |
− | | |
− | control_fan() {
| |
− | # Enable the fan in default mode if anything goes wrong:
| |
− | set -e -E -u
| |
− | trap "cleanup; exit 2" HUP INT ABRT QUIT SEGV TERM
| |
− | trap "cleanup" EXIT
| |
− | trap "log 'Got SIGUSR1'; setlevel 0; RESTART=true; sleep $SUSPEND_TIME" USR1
| |
− | | |
− | init_state
| |
− | log "Starting dynamic fan control"
| |
− | | |
− | # Control loop:
| |
− | while true; do
| |
− | TEMPS=`thermometer`
| |
− | $QUIET || SPEED=`speedometer`
| |
− | $QUIET || ECLEVEL=`getlevel`
| |
− | NOW=`date +%s`
| |
− | | |
− | # Calculate new level index by placing temperatures into Z-regions:
| |
− | # Z >= 2*I means "must be at index I or higher"
| |
− | # Z = 2*I+1 is hysteresis: "don't step down if currently at I+1"
| |
− | # hence the Z-regions are, for d=(MAX-MIN)/(2*MAX_IDX-1) :
| |
− | # Z=0:{-infty..MIN-d) Z=1:{MIN-d..MIN) Z=2:{MIN..MIN+d} Z=3:{MIN+d..MIN+2d} ... Z=2*MAX_IDX:{MAX-d, MAX}
| |
− | | |
− | MAX_Z=$(( IDX>0 ? ( NOW>START_TIME+MIN_WAIT ? 2*(IDX-1) : 2*IDX ) : 0 ))
| |
− | SENSOR=0
| |
− | Z_STR="$MAX_Z+"
| |
− | TEMP_STR="";
| |
− | for TEMP in $TEMPS; do
| |
− | [ $((2*SENSOR+2)) -le ${#THRESHOLDS[@]} ] ||
| |
− | { echo "Too many sensors, not enough values in THRESHOLDS" 2>&1; exit 1; }
| |
− | if [ $TEMP == -128 ]; then
| |
− | Z='_'; TEMP='_' # inactive sensor
| |
− | else
| |
− | MIN=$((THRESHOLDS[SENSOR*2] + MIN_THRESH_SHIFT));
| |
− | MAX=$((THRESHOLDS[SENSOR*2+1]))
| |
− | if (( TEMP < MIN - OFF_THRESH_DELTA )); then
| |
− | Z=0
| |
− | else
| |
− | Z=$(( `floor_div $(( (TEMP-MIN)*(2*MAX_IDX-2) )) $((MAX-MIN))` + 2 ))
| |
− | fi
| |
− | [ $MAX_Z -gt $Z ] || MAX_Z=$Z
| |
− | fi
| |
− | Z_STR="${Z_STR}${Z}"
| |
− | TEMP_STR="${TEMP_STR}${TEMP} "
| |
− | (( ++SENSOR ))
| |
− | done
| |
− | [ $SENSOR -gt 0 ] || { echo "No temperatures read" >&2; exit 1; }
| |
− | | |
− | (( (MAX_Z == 2*IDX-1) && ++MAX_Z )) # hysteresis
| |
− | NEW_IDX=$(( MAX_Z/2 ))
| |
− | [ $NEW_IDX -le $MAX_IDX ] || NEW_IDX=$MAX_IDX
| |
− | | |
− | # Interrupted by a signal?
| |
− | if $RESTART; then
| |
− | init_state
| |
− | log "Resetting state"
| |
− | continue
| |
− | fi
| |
− | | |
− | # Transition
| |
− | $FIRST && OLDLEVEL='?' || OLDLEVEL=${LEVELS[$IDX]}
| |
− | NEWLEVEL=${LEVELS[$NEW_IDX]}
| |
− | $QUIET || echo "L=$OLDLEVEL->$NEWLEVEL EC=$ECLEVEL RPM=`printf %4s $SPEED` T=($TEMP_STR) Z=$Z_STR"
| |
− | if [ "$OLDLEVEL" != "$NEWLEVEL" ]; then
| |
− | START_TIME=$NOW
| |
− | log "Changing fan level: $OLDLEVEL->$NEWLEVEL (temps: $TEMP_STR)"
| |
− | fi
| |
− | | |
− | setlevel $NEWLEVEL
| |
− | | |
− | sleep $INTERVAL
| |
− | | |
− | # If needed, apply anti-pulsing hack after a settle-down period (and occasionally re-settle):
| |
− | if [ ${ANTIPULSE[${NEW_IDX}]} == 1 ]; then
| |
− | if [ $NEWLEVEL != $OLDLEVEL -o $RESETTLE_LEFT -le 0 ]; then # start settling?
| |
− | SETTLE_LEFT=$SETTLE_TIME
| |
− | RESETTLE_LEFT=$RESETTLE_TIME
| |
− | fi
| |
− | if [ $SETTLE_LEFT -ge 0 ]; then
| |
− | SETTLE_LEFT=$((SETTLE_LEFT-INTERVAL))
| |
− | else
| |
− | setlevel 0x40 # disengage briefly to fool embedded controller
| |
− | sleep 0.5
| |
− | RESETTLE_LEFT=$((RESETTLE_LEFT-INTERVAL))
| |
− | fi
| |
− | fi
| |
− | | |
− | IDX=$NEW_IDX
| |
− | FIRST=false
| |
− | done
| |
− | }
| |
− | | |
− | if $KILL_DAEMON || $SUSPEND_DAEMON; then
| |
− | if [ -f "$PID_FILE" ]; then
| |
− | set -e
| |
− | DPID="`cat \"$PID_FILE\"`"
| |
− | if $KILL_DAEMON; then
| |
− | kill "$DPID"
| |
− | rm "$PID_FILE"
| |
− | $QUIET || echo "Killed process $DPID"
| |
− | else # SUSPEND_DAEMON
| |
− | kill -USR1 "$DPID"
| |
− | $QUIET || echo "Sent SIGUSR1 to $DPID"
| |
− | fi
| |
− | else
| |
− | $QUIET || echo "Daemon not running."
| |
− | exit 1
| |
− | fi
| |
− | elif $DAEMONIZE ; then
| |
− | if [ -e "$PID_FILE" ]; then
| |
− | echo "$0: File $PID_FILE already exists, refusing to run."
| |
− | exit 1
| |
− | else
| |
− | AM_DAEMON=true QUIET=true control_fan 0<&- 1>&- 2>&- &
| |
− | echo $! > "$PID_FILE"
| |
− | exit 0
| |
− | fi
| |
− | else
| |
− | [ -e "$PID_FILE" ] && echo "WARNING: daemon already running"
| |
− | control_fan
| |
− | fi
| |
− | </pre>
| |
− | | |
− | The authors of the script ([[User:Thinker|Thinker]] and [[User:Spiney|Spiney]]) disclaim all warranty for this script, and make it available under the terms of the [http://www.gnu.org/copyleft/gpl.html GPL] version 2 or later, or at your option, the [http://www.gnu.org/copyleft/fdl.html GFDL].
| |
| | | |
| ====init script for the comprehensive script==== | | ====init script for the comprehensive script==== |
| | | |
− | The following init script (tested on {{Debian}}) allows you to configure some options using a config file. It requires to move the above <tt>tp-fancontrol</tt> script to {{path|/usr/bin/tp-fancontrol}}, but that can be changed easily. Written by [[User:Raigner|Raigner]].
| + | This is optional. It assumes that the above <tt>tp-fancontrol</tt> script is saved at {{path|/usr/bin/tp-fancontrol}}. |
| + | * Init script: {{CodeRef|tp-fancontrol.init}} (save as {{path|/etc/init.d/tp-fancontrol}}) |
| + | * Init script (Debian): {{CodeRef|tp-fancontrol.init.debian}} (save as {{path|/etc/init.d/tp-fancontrol}}) |
| + | * Configuration file for init script: {{CodeRef|tp-fancontrol.conf}} (save as {{path|/etc/tp-fancontrol.conf}}) |
| | | |
− | <pre> | + | ===Simple <tt>bash</tt> script with fine control over fan speed (requires kernel patch)=== |
− | #! /bin/sh
| + | The following is a simpler patch (without extra features like daemon mode and logging). It requires the [[patch for controlling fan speed]] or a recent kernel (>=2.6.19). |
− | ### BEGIN INIT INFO
| |
− | # Provides: tp-fancontrol
| |
− | # Default-Start: 2 3 4 5
| |
− | # Default-Stop: S 0 1 6
| |
− | ### END INIT INFO
| |
− | # Copyright (c) 2006 Ronald Aigner <ra3@os.inf.tu-dresden.de>
| |
| | | |
− | set -e
| + | {{CodeRef|tp-fancontrol-basic}} |
| | | |
− | DAEMON=/usr/bin/tp-fancontrol
| + | ===tp-fan: Automatic daemon with GTK+ GUI=== |
− | NAME=tp-fancontrol
| + | Provides easy setup and monitoring through graphical GTK+ interface. Temperature thresholds can be set separately for each sensor since version 0.90. |
− | DAEMONUSER=root
| |
− | PIDDIR=/var/run
| |
− | PIDFILE=$PIDDIR/tp-fancontrol.pid
| |
− | DESC="Thinkpad CPU fan control"
| |
| | | |
− | test -x $DAEMON || exit 0
| + | At the moment packages are available for Ubuntu 8.04, 8.10, and 9.04. However, porting to other distributions or manual setup should be easy. |
| | | |
− | # source config file; edit that file to configure this script
| + | * Home page: http://www.gambitchess.org/mediawiki/index.php/ThinkPad_Fan_Control |
− | TEMP_SHIFT=0
| + | http://www.gambitchess.org/moin.py/tpfan |
− | LOG_SYSLOG=1
| |
− | QUIET=1
| |
− | if [ -e /etc/tp-fancontrol.conf ]; then
| |
− | . /etc/tp-fancontrol.conf
| |
− | fi
| |
− |
| |
− | start_it()
| |
− | {
| |
− | PARAMS=-d
| |
− | if [ -e $PIDFILE ]; then
| |
− | echo "$DESC already running. Stop first."
| |
− | exit 1
| |
− | fi
| |
− | if [ "$TEMP_SHIFT" != "0" ]; then
| |
− | PARAMS=$PARAMS -s $TEMP_SHIFT
| |
− | fi
| |
− | if [ "$LOG_SYSLOG" = "1" ]; then
| |
− | PARAMS=$PARAMS" -l"
| |
− | else
| |
− | if [ "$QUIET" = "1" ]; then
| |
− | PARAMS=$PARAMS" -q"
| |
− | fi
| |
− | fi
| |
− | PARAMS=$PARAMS" -p $PIDFILE"
| |
| | | |
− | echo -n "Starting $DESC: $NAME ... "
| + | ===thinkfan: A minimalist fan control program=== |
− | $DAEMON $PARAMS
| + | Written in C to use as little CPU power as possible. Configuration is done via a simple text file, by providing (FAN_LEVEL, LOWER_LIMIT, UPPER_LIMIT) tuples. Inspired by i8kfan. Requires thinkpad_acpi with fan_control=1. Just released version 0.7, which now allows a more fine-grained control over temperature limits. |
− | if [ "$?" = "0" ]; then
| |
− | echo "Success."
| |
− | else
| |
− | echo "Error while starting: $?"
| |
− | fi
| |
− | }
| |
− |
| |
− | stop_it()
| |
− | {
| |
− | if [ -e $PIDFILE ]; then
| |
− | echo -n "Stopping $DESC ... "
| |
− | $DAEMON -k
| |
− | if [ "$?" = "0" ]; then
| |
− | echo "Success."
| |
− | else
| |
− | echo "Error while stopping: $?"
| |
− | fi
| |
− | else
| |
− | echo "$DESC not running."
| |
− | fi
| |
− | }
| |
| | | |
− | restart_it()
| + | * Download here: http://sourceforge.net/projects/thinkfan/ |
− | {
| |
− | if [ -e $PIDFILE ]; then
| |
− | stop_it
| |
− | sleep 2
| |
− | fi
| |
− | start_it
| |
− | }
| |
| | | |
− | case "$1" in
| + | ==Fan enable/disable scripts== |
− | start)
| + | The following scripts were written before it was known [[patch for controlling fan speed|how to control the fan speed]], so they only toggle between fan disabled and default (noisy) fan behavior. In some models, they also do not monitor all available [[thermal sensors]]. |
− | start_it
| |
− | ;;
| |
− | stop)
| |
− | stop_it
| |
− | ;;
| |
− | reload|force-reload|restart)
| |
− | restart_it
| |
− | ;;
| |
− | *)
| |
− | echo "Usage: /etc/init.d/$NAME {start|stop|reload|restart|force-reload}" >&2
| |
− | exit 1
| |
− | ;;
| |
− | esac
| |
| | | |
− | exit 0
| + | ===<tt>sh</tt> script example=== |
− | </pre> | + | {{CodeRef|fan-enable-basic}} |
| | | |
− | The {{path|/etc/tp-fancontrol.conf}} config script could look like this:
| + | ===<tt>sh</tt> script with more features=== |
| + | {{CodeRef|fan-enable-extended}} |
| | | |
− | <pre> | + | ===<tt>sh</tt> script with extra safety functionality=== |
− | # config file for tp-fancontrol | + | ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality: |
| + | # It catches various signals and turns the fan on before it quits. |
| + | # It turns off the fan under very strict conditions, leaving it on when unexpected errors occur. |
| | | |
− | #
| + | {{CodeRef|fan-enable-safe}} |
− | # The temparature shift will shift the trip points for different fan speeds.
| |
− | #
| |
− | # A positive value means that the trip-point is at a higher temperature and
| |
− | # thus the fan is less noisy. A negative shift lets the fan start earlier.
| |
− | # The default value is 0.
| |
− | #
| |
− | #TEMP_SHIFT=10
| |
| | | |
− | #
| + | ==Init scripts== |
− | # True if logging to syslog should be enabled. If zero no logging to syslog
| |
− | # is enabled. All output will appear on console. This option implies QUIET=1.
| |
− | # The default value is 1.
| |
− | #
| |
− | #LOG_SYSLOG=0
| |
| | | |
− | #
| + | ===Init script example=== |
− | # If no logging to syslog is on, the output will be verbose. To be less
| |
− | # verbose set QUIET to 1. The default value is 1.
| |
− | #
| |
− | #QUIET=1
| |
| | | |
− | #
| + | {{CodeRef|fan-enable.init}} |
− | # The file to store the pid of the currently running fan-control daemon in.
| |
− | # The default value is /var/run/tp-fancontrol.pid
| |
− | #
| |
− | #PIDFILE=/var/run/tp-fancontrol.pid
| |
− | </pre>
| |
| | | |
− | ===Simple <tt>bash</tt> script with fine control over fan speed (requires kernel patch)=== | + | ===Init script example for gentoo=== |
− | The following is a simpler patch (without extra features like daemon mode and logging). It requires the [[patch for controlling fan speed]].
| + | Assume one of the above control scripts is {{path|/usr/sbin/ibm-fancontrold}}, for gentoo use the following init script in /etc/init.d/ibm-fancontrol. |
| + | Copy the script to {{path|/etc/init.d/ibm-fancontrol}}, then do |
| | | |
− | <pre>
| + | # rc-update add ibm-fancontrol default |
− | #!/bin/bash | |
| | | |
− | # This script dynamically controls fan speed on some ThinkPad models
| + | This will add the init script to the default runlevel. |
− | # according to user-defined temperature thresholds. It implements its
| |
− | # own decision algorithm, overriding the ThinkPad embedded
| |
− | # controller. It also implements a workaround for the fan noise pulse
| |
− | # experienced every few seconds on some ThinkPads.
| |
− | #
| |
− | # The script requires the ibm_acpi patch at
| |
− | # http://thinkwiki.org/wiki/Patch_for_controlling_fan_speed
| |
− | #
| |
− | # WARNING: This script relies on undocumented hardware features and
| |
− | # overrides nominal hardware behavior. It may thus cause arbitrary
| |
− | # damage to your laptop or data. Watch your temperatures!
| |
− | #
| |
− | # This file is placed in the public domain and may be freely distributed.
| |
| | | |
− | LEVELS=( 0 2 4 7) # Fan speed levels
| + | {{CodeRef|ibm-fancontrol.init}} |
− | UP_TEMPS=( 52 60 68 ) # Speed increase trip points
| |
− | DOWN_TEMPS=( 48 56 64 ) # Speed decrease trip points
| |
| | | |
− | ANTIPULSE=( 0 1 0 0) # Prevent fan pulsing noise at this level
| + | ===Init script example for rh/fedora=== |
− | # (this also prevents fan speed updates)
| + | Assume one of the above control scripts is {{path|/sbin/tp-fancontrold}}, |
| + | copy the script to {{path|/etc/init.d/tp-fancontrol}}, then do |
| | | |
− | IBM_ACPI=/proc/acpi/ibm
| + | # chkconfig --add tp-fancontrol |
− | FAN=$IBM_ACPI/fan
| |
− | INTERVAL=3
| |
− | VERBOSE=true
| |
− | DRY_RUN=false
| |
| | | |
− | [[ "$1" == "-t" ]] && { DRY_RUN=true; echo "$0: Dry run, will not change fan state."; }
| + | This will add the init script to the default runlevel. |
| | | |
− | # Enable the fan in default mode if anything goes wrong:
| + | {{CodeRef|tp-fancontrol-fc.init}} |
− | set -e -E -u
| |
− | $DRY_RUN || trap "echo enable > $FAN; exit 0" EXIT HUP INT ABRT QUIT SEGV TERM
| |
| | | |
| + | You'd have to install also "kernel-module-ibm-acpi" package. |
| | | |
− | thermometer() { # output list of temperatures
| + | ==Other== |
− | read X Y < $IBM_ACPI/thermal
| |
− | [[ "$X" == "temperatures:" ]] || {
| |
− | echo "$0: Bad temperatures: $X $Y" >&2
| |
− | exit 1
| |
− | }
| |
− | echo "$Y";
| |
− | }
| |
| | | |
− | speedometer() { # output fan speed
| + | ===tpfand=== |
− | cat $FAN | sed '/^speed/!d; s/speed:[ \t]*//'
| + | This little piece of python code is only there to speed up your fan in a T400 with an ATI card cause the fglrx driver does not control the fan speed which leads to overheating while gaming or do other graphic stuff with the ati chip. This script relies on the normal bios control of the fan. If the laptop gets to hot it will speed up the fan to max speed (somehow the bios does not do this ??!!) and re-enables the bios control on a certain temperature. This was only tested on a T400 with ATI chip. |
− | }
| + | You can just run in in the background as root. It is very chatty and writes in a logfile in /tmp. It should work with any Thinkpad who has /proc/acpi/ibm/fan interface. |
| + | [http://pastebin.ca/1884323 tpfand] |
| | | |
− | IDX=0
| + | Tested on: |
− | MAX_IDX=$(( ${#LEVELS[@]} - 1 ))
| + | T400 with Radeon HD 3400 |
− | SETTLE=0
| + | Please test on other models with ATI chip. |
| | | |
− | while true; do
| + | ===fanctrld=== |
− | TEMPS=`thermometer`
| + | [http://log.does-not-exist.org/archives/2005/08/13/2043_t_43_fan_control_daemon.html fanctrld] is a daemon (written in C) that controls the Thinkpad's fan. The basic approach is to monitor both temperature and fan speed. The fan is enabled when a certain temperature is exceeded, and disabled when the BIOS slows down the fan below a certain speed. |
− | $VERBOSE && SPEED=`speedometer`
| |
| | | |
− | # Calculate new level
| + | ===ThinkPad Fan Control GTK GUI tool=== |
− | NEWIDX=$IDX
| |
− | DOWN=$(( IDX > 0 ))
| |
− | for TEMP in $TEMPS; do
| |
− | # Increase speed as much as needed
| |
− | while [[ $NEWIDX -lt $MAX_IDX ]] &&
| |
− | [[ $TEMP -ge ${UP_TEMPS[$NEWIDX]} ]]; do
| |
− | (( NEWIDX ++ ))
| |
− | DOWN=0
| |
− | done
| |
− | # Allow decrease (by one index)?
| |
− | if [[ $DOWN == 1 ]] &&
| |
− | [[ $TEMP -gt ${DOWN_TEMPS[$(( IDX - 1 ))]} ]]; then
| |
− | DOWN=0
| |
− | fi
| |
− | done
| |
− | if [[ $DOWN == 1 ]]; then
| |
− | NEWIDX=$(( IDX - 1 ))
| |
− | fi
| |
| | | |
− | # Transition
| + | [http://www.gambitchess.org/moin.py/ThinkPad_Fan_Control A GTK GUI program (packaged for Ubuntu Gutsy Gibbon 7.10)] may also help. |
− | OLDLEVEL=${LEVELS[$IDX]}
| |
− | NEWLEVEL=${LEVELS[$NEWIDX]}
| |
− | $VERBOSE && echo "tpfan: Temps: $TEMPS Fan: $SPEED Level: $OLDLEVEL->$NEWLEVEL"
| |
− | $DRY_RUN || echo level $NEWLEVEL > $FAN
| |
| | | |
− | sleep $INTERVAL
| + | For those using Ubuntu 8.10 and recent Thinkpad models (eg: X200), this is the fan control packages to use: sudo apt-get install tpfand tpfan-admin tpfand-profiles (The packages are part of the main ubuntu repository). It solves the problem of a constantly-on fan. I don't think there are yet profiles for those newer thinkpad models, but it's fairly easy to manually configure the right thresholds. For reference, this is the /etc/tpfand.conf I use for my X200: |
| | | |
− | # If needed, apply anti-pulsing hack after a settle-down period:
| |
− | if [[ ${ANTIPULSE[${NEWIDX}]} == 1 ]]; then
| |
− | if [[ $NEWLEVEL == $OLDLEVEL ]]; then
| |
− | if [[ $SETTLE -ge 0 ]]; then
| |
− | (( SETTLE -= INTERVAL ))
| |
− | else
| |
− | $DRY_RUN || echo level disengaged >> $FAN
| |
− | sleep 0.5
| |
− | fi
| |
− | else
| |
− | SETTLE=6
| |
− | fi
| |
− | fi
| |
| | | |
− | IDX=$NEWIDX
| |
− | done
| |
− | </pre>
| |
| | | |
− | The [[User:Thinker|author]] of the script disclaims all warranty for this script, and releases it to the public domain (meaning you may use it and further distribute it under any terms you wish, including incorporating it into other software).
| + | enabled = True |
| | | |
− | ==Fan enable/disable scripts== | + | override_profile = True |
− | The following scripts were written before it was known [[patch for controlling fan speed|how to control the fan speed]], so they only toggle between fan disabled and default (noisy) fan behavior. In some models, they also do not monitor all available [[thermal sensors]].
| |
| | | |
− | ===<tt>sh</tt> script example===
| |
− | #!/bin/sh
| |
− |
| |
− | MAXTEMP=50
| |
− |
| |
− | while [ 1 ];
| |
− | do
| |
− | fan=no
| |
− |
| |
− | for temp in `sed s/temperatures:// < /proc/acpi/ibm/thermal`
| |
− | do
| |
− | test $temp -gt $MAXTEMP && fan=yes
| |
− | done
| |
− |
| |
− | command='disable'
| |
− | test "$fan" = "yes" && command='enable'
| |
− | echo $command > /proc/acpi/ibm/fan
| |
− |
| |
− | sleep 20
| |
− | done
| |
| | | |
| + | 0. Sensor 0 = 0:0 50:3 58:5 67:8 |
| | | |
− | ===<tt>sh</tt> script with more features===
| + | 1. Sensor 1 = 0:0 55:3 62:5 69:8 |
− | #!/bin/sh
| |
− |
| |
− | # fan control-script
| |
− | #
| |
− | # based upon ibm-acpi 0.11 (experimental=1 !)
| |
− | #
| |
− | # eliminates anoying "fan always on" in battery mode
| |
− | # works with hysteresis (DELTA) so that always-turn-on/turn-off is avoided
| |
− | # fan acivates at MAXTEMP and cools down CPU, GPU etc. to MAXTEMP-DELTA than the fan is turned off
| |
− | # furthermore detects if AC is on and gives back fan control to default behaviour than
| |
− | #
| |
− | # one can change MAXTEMP and DELTA to individual values
| |
− | # but take care of your THINKPAD don`t melt it!
| |
− | #
| |
− | # have fun!
| |
− | # mk 05.05.05
| |
− |
| |
− | MAXTEMP=51
| |
− | DELTA=4
| |
− |
| |
− | SWITCHTEMP=$MAXTEMP
| |
− |
| |
− | #make sure the script doesn't leave the fan off on error
| |
− | trap "echo enable > /proc/acpi/ibm/fan" EXIT
| |
− |
| |
− | while [ 1 ];
| |
− | do
| |
− | for ac in `sed s/state:// < /proc/acpi/ac_adapter/AC/state`
| |
− | do
| |
− | if [ "$ac" = "off-line" ]; then
| |
− | fan=no
| |
− | for temp in `sed s/temperatures:// < /proc/acpi/ibm/thermal`
| |
− | do
| |
− | test $temp -gt $SWITCHTEMP && fan=yes
| |
− | done
| |
− |
| |
− | if [ "$fan" = "yes" ]; then
| |
− | command='enable'
| |
− | SWITCHTEMP=`expr $MAXTEMP - $DELTA`
| |
− | else
| |
− | SWITCHTEMP=$MAXTEMP
| |
− | command='disable'
| |
− | fi
| |
− |
| |
− | else # ac-adapter on -> set fan control to standard behaviour
| |
− | command='enable'
| |
− | fi
| |
− |
| |
− | echo $command > /proc/acpi/ibm/fan
| |
− | sleep 15
| |
− | done
| |
− | done
| |
| | | |
| + | 2. Sensor 2 = 0:255 |
| | | |
− | ===<tt>sh</tt> script with extra safety functionality===
| + | 3. Sensor 3 = 0:0 48:3 61:5 69:8 |
− | ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality:
| |
− | # It catches various signals and turns the fan on before it quits.
| |
− | # It turns off the fan under very strict conditions, leaving it on when unexpected errors occur.
| |
− | | |
− | #!/bin/sh
| |
− |
| |
− | # july 2005 Erik Groeneveld, erik@cq2.nl
| |
− | # It makes sure the fan is on in case of errors
| |
− | # and only turns it off when all temps are ok.
| |
− |
| |
− | IBM_ACPI=/proc/acpi/ibm
| |
− | THERMOMETER=$IBM_ACPI/thermal
| |
− | FAN=$IBM_ACPI/fan
| |
− | MAXTRIPPOINT=65
| |
− | MINTRIPPOINT=60
| |
− | TRIPPOINT=$MINTRIPPOINT
| |
− |
| |
− | echo fancontrol: Thermometer: $THERMOMETER, Fan: $FAN
| |
− | echo fancontrol: Current `cat $THERMOMETER`
| |
− | echo fancontrol: Controlling temperatures between $MINTRIPPOINT and $MAXTRIPPOINT degrees.
| |
− |
| |
− | # Make sure the fan is turned on when the script crashes or is killed
| |
− | trap "echo enable > $FAN; exit 0" HUP KILL INT ABRT STOP QUIT SEGV TERM
| |
− |
| |
− | while [ 1 ];
| |
− | do
| |
− | command=enable
| |
− | temperatures=`sed s/temperatures:// < $THERMOMETER`
| |
− | result=
| |
− | for temp in $temperatures
| |
− | do
| |
− | test $temp -le $TRIPPOINT && result=$result.Ok
| |
− | done
| |
− | if [ "$result" = ".Ok.Ok.Ok.Ok.Ok.Ok.Ok.Ok" ]; then
| |
− | command=disable
| |
− | TRIPPOINT=$MAXTRIPPOINT
| |
− | else
| |
− | command=enable
| |
− | TRIPPOINT=$MINTRIPPOINT
| |
− | fi
| |
− | echo $command > $FAN
| |
− | # Temperature ramps up quickly, so pick this not too large:
| |
− | sleep 5
| |
− | done
| |
− | | |
− | | |
− | ==Init scripts==
| |
− | | |
− | ===Init script example===
| |
− | #! /bin/sh
| |
− |
| |
− | N=/etc/init.d/fan
| |
− |
| |
− | set -e
| |
− |
| |
− | case "$1" in
| |
− | start)
| |
− | # make sure privileges don't persist across reboots
| |
− | if [ -d /var/run/fan ] && [ "x`ls /var/run/fan`" != x ]
| |
− | then
| |
− | touch -t 198501010000 /var/run/fan/*
| |
− | fi
| |
− | fan.sh & # Script from above
| |
− | ;;
| |
− | stop|reload|restart|force-reload)
| |
− | killall fan.sh
| |
− | echo enable > /proc/acpi/ibm/fan
| |
− | ;;
| |
− | *)
| |
− | echo "Usage: $N {start|stop|restart|force-reload}" >&2
| |
− | exit 1
| |
− | ;;
| |
− | esac
| |
− |
| |
− | exit 0
| |
| | | |
| + | 4. Sensor 4 = 0:0 43:3 50:8 |
| | | |
− | ===Init script example for gentoo=== | + | 5. Sensor 5 = 0:255 |
− | Assume one of the above control scripts is /usr/sbin/ibm-fancontrold, for gentoo use the following init script in /etc/init.d/ibm-fancontrol.
| |
− | Copy the script to /etc/init.d/ibm-fancontrol, then do
| |
| | | |
− | # rc-update add ibm-fancontrol default
| + | 6. Sensor 6 = 0:0 40:8 |
| | | |
− | This will add the init script to the default runlevel.
| + | 7. Sensor 7 = 0:255 |
− | | |
− | #!/sbin/runscript
| |
− | # 2005 Gilbert Tiefengruber
| |
− | # Distributed under the terms of the GNU General Public License v2
| |
− | # IBM Fancontrol init script for IBM Thinkpad laptops (tested with R50)
| |
− | # This init script was written for gentoo 2005.1, kernel 2.6.12
| |
− | # You need the ibm_acpi kernel module version 0.11 or greater
| |
− | # load the module with experimental=1 to enable the fan controls
| |
− |
| |
− | depend() {
| |
− | need localmount
| |
− | }
| |
− | checkconfig() {
| |
− | if [ ! -e /proc/acpi/ibm/fan ]; then
| |
− | eerror "The ibm_acpi module must be loaded with (experimental=1)"
| |
− | return 1
| |
− | fi
| |
− | }
| |
− | start() {
| |
− | checkconfig || return 1
| |
− | ebegin "Starting ibm-fancontrold"
| |
− | start-stop-daemon --quiet -p /var/run/ibm-fancontrold.pid -m -b --start -a /usr/sbin/ibm-fancontrold
| |
− | eend ${?}
| |
− | }
| |
− | stop() {
| |
− | ebegin "Stopping ibm-fancontrold"
| |
− | start-stop-daemon --stop --quiet -p /var/run/ibm-fancontrold.pid
| |
− | eend ${?}
| |
− | }
| |
− | | |
− | | |
− | ==Other==
| |
− | | |
− | ===fanctrld===
| |
− | [http://log.does-not-exist.org/archives/2005/08/13/2043_t_43_fan_control_daemon.html fanctrld] is a daemon (written in C) that controls the Thinkpad's fan. The basic approach is to monitor both temperature and fan speed. The fan is enabled when a certain temperature is exceeded, and disabled when the BIOS slows down the fan below a certain speed.
| |
| | | |
| ==Ideas for improvement== | | ==Ideas for improvement== |
− | * Use the [[HDAPS]] sensor to automatically lower the temperature thresholds when the laptop is moving. Prolonged movement usually happens when the laptop is on the user's lap (so [http://www.theregister.co.uk/2002/11/22/man_burns_penis_with_laptop/ better keep temperatures down]), or when in a moving vehicle where fan noise is typically overshadowed by vehicle noise. | + | * Use the [[HDAPS]] sensor to automatically lower the temperature thresholds when the laptop is moving. Prolonged movement usually happens when the laptop is on the user's lap (see [[Problem with hot surfaces]] for implications), or when in a moving vehicle where fan noise is typically overshadowed by vehicle noise. |
| * Use a [http://en.wikipedia.org/wiki/PID_controller PID controller] feedback loop instead of simple thresholds. | | * Use a [http://en.wikipedia.org/wiki/PID_controller PID controller] feedback loop instead of simple thresholds. |
| + | * Monitor the UltraBay disk temperature too. |
| | | |
| ==See also== | | ==See also== |
|
This page provides several scripts for controlling the ThinkPad's system fan according the its thermal sensors (overriding the embedded controller), in order to reduce fan noise and decrease power consumption.
ATTENTION!
These scripts rely on undocumented hardware features and override nominal hardware behavior. They may thus cause arbitrary damage to your laptop or data. Watch your temperatures!
NOTE!
Closed-loop fan control requires a thermal sensor sweep, which is an expensive operation. The firmware doesn't update the sensors more than once every 2s, so care should be taken not to waste resources by reading them too often.
|
Variable speed control scripts
The following scripts sets the fan speed according to the system's thermal sensors. In addition, they include a hack for preventing the annoying fan pulsing that occurs on some systems. Note that the fan levels, thresholds and anti-pulsing hacks are system-specific, so you may need to adjust them.
Comprehensive bash script with fine control over fan speed
This script works with any recent Linux kernel (2.6.14 and higher). It requires the ibm-acpi module to be loaded with the experimental=1 module parameter (e.g., # modprobe ibm_acpi experimental=1
).
In Linux 2.6.22 and higher you need to additionally pass fan_control=1 to the module thinkpad_acpi (e.g., # modprobe thinkpad-acpi experimental=1 fan_control=1
)
On Ubuntu > 10.04 or from kernel 2.6.32 onwards: To make the kernel module settings permanent and to make them be executed at boot run below command and reboot afterwards:
# sudo echo "options thinkpad_acpi experimental=1 fan_control=1" >/etc/modprobe.d/thinkpad_acpi.conf
The code lets you define a temperature range for each thermal sensor. The script computes the fan level needed by each sensor based on the configured range, and then sets the the actual fan level to the slowest that will satisfy all sensors (plus some hysteresis to avoid fluctiations). It also includes a workaround for the pulsing noise problem. The script provides an (optional) daemon mode and logging to syslog. The method of controlling fan speed is documented here.
The system hard disk temperature is monitored as well, using the hard disk's internal sensor. This works only on certain Hitachi disks and requires kernel >= 2.6.19-rc1 or the ide driver, since it uses a non-standard method for reading the temperature without causing a head unload or spinup.
The code:
ATTENTION!
There is a bug in the code which causes the script to exit immediately after start with bash version is 4.1.0(7)-release. The problem line is line 356 which returns zero and cause the script to exit if set -e is called, which is unfortunately true. A simple solution is to append a true expression after the command.
Current options:
Usage: ./tp-fancontrol [OPTION]...
Available options:
-s N Shift up the min temperature thresholds by N degrees
(positive for quieter, negative for cooler).
Max temperature thresholds are not affected.
-S N Shift up the max temperature thresholds by N degrees
(positive for quieter, negative for cooler). DANGEROUS.
-t Test mode
-q Quiet mode
-d Daemon mode, go into background (implies -q)
-l Log to syslog
-k Kill already-running daemon
-u Tell already-running daemon that the system is being suspended
-p Pid file location for daemon mode
ATTENTION!
The list of temperature ranges used in this script is much more liberal than the rules used by the embedded controller firmware, and is derived mostly from anecdotal evidence, hunches and wishful thinking. It is also model-specific - see
thermal sensors.
init script for the comprehensive script
This is optional. It assumes that the above tp-fancontrol script is saved at /usr/bin/tp-fancontrol.
Simple bash script with fine control over fan speed (requires kernel patch)
The following is a simpler patch (without extra features like daemon mode and logging). It requires the patch for controlling fan speed or a recent kernel (>=2.6.19).
tp-fancontrol-basic (download)
tp-fan: Automatic daemon with GTK+ GUI
Provides easy setup and monitoring through graphical GTK+ interface. Temperature thresholds can be set separately for each sensor since version 0.90.
At the moment packages are available for Ubuntu 8.04, 8.10, and 9.04. However, porting to other distributions or manual setup should be easy.
http://www.gambitchess.org/moin.py/tpfan
thinkfan: A minimalist fan control program
Written in C to use as little CPU power as possible. Configuration is done via a simple text file, by providing (FAN_LEVEL, LOWER_LIMIT, UPPER_LIMIT) tuples. Inspired by i8kfan. Requires thinkpad_acpi with fan_control=1. Just released version 0.7, which now allows a more fine-grained control over temperature limits.
Fan enable/disable scripts
The following scripts were written before it was known how to control the fan speed, so they only toggle between fan disabled and default (noisy) fan behavior. In some models, they also do not monitor all available thermal sensors.
sh script example
fan-enable-basic (download)
sh script with more features
fan-enable-extended (download)
ibm_acpi usually works well. But to rely on it completely, this script provides some extra safety functionality:
- It catches various signals and turns the fan on before it quits.
- It turns off the fan under very strict conditions, leaving it on when unexpected errors occur.
fan-enable-safe (download)
Init scripts
Init script example
fan-enable.init (download)
Init script example for gentoo
Assume one of the above control scripts is /usr/sbin/ibm-fancontrold, for gentoo use the following init script in /etc/init.d/ibm-fancontrol.
Copy the script to /etc/init.d/ibm-fancontrol, then do
# rc-update add ibm-fancontrol default
This will add the init script to the default runlevel.
ibm-fancontrol.init (download)
Init script example for rh/fedora
Assume one of the above control scripts is /sbin/tp-fancontrold,
copy the script to /etc/init.d/tp-fancontrol, then do
# chkconfig --add tp-fancontrol
This will add the init script to the default runlevel.
tp-fancontrol-fc.init (download)
You'd have to install also "kernel-module-ibm-acpi" package.
Other
tpfand
This little piece of python code is only there to speed up your fan in a T400 with an ATI card cause the fglrx driver does not control the fan speed which leads to overheating while gaming or do other graphic stuff with the ati chip. This script relies on the normal bios control of the fan. If the laptop gets to hot it will speed up the fan to max speed (somehow the bios does not do this ??!!) and re-enables the bios control on a certain temperature. This was only tested on a T400 with ATI chip.
You can just run in in the background as root. It is very chatty and writes in a logfile in /tmp. It should work with any Thinkpad who has /proc/acpi/ibm/fan interface.
tpfand
Tested on:
T400 with Radeon HD 3400
Please test on other models with ATI chip.
fanctrld
fanctrld is a daemon (written in C) that controls the Thinkpad's fan. The basic approach is to monitor both temperature and fan speed. The fan is enabled when a certain temperature is exceeded, and disabled when the BIOS slows down the fan below a certain speed.
ThinkPad Fan Control GTK GUI tool
A GTK GUI program (packaged for Ubuntu Gutsy Gibbon 7.10) may also help.
For those using Ubuntu 8.10 and recent Thinkpad models (eg: X200), this is the fan control packages to use: sudo apt-get install tpfand tpfan-admin tpfand-profiles (The packages are part of the main ubuntu repository). It solves the problem of a constantly-on fan. I don't think there are yet profiles for those newer thinkpad models, but it's fairly easy to manually configure the right thresholds. For reference, this is the /etc/tpfand.conf I use for my X200:
enabled = True
override_profile = True
0. Sensor 0 = 0:0 50:3 58:5 67:8
1. Sensor 1 = 0:0 55:3 62:5 69:8
2. Sensor 2 = 0:255
3. Sensor 3 = 0:0 48:3 61:5 69:8
4. Sensor 4 = 0:0 43:3 50:8
5. Sensor 5 = 0:255
6. Sensor 6 = 0:0 40:8
7. Sensor 7 = 0:255
Ideas for improvement
- Use the HDAPS sensor to automatically lower the temperature thresholds when the laptop is moving. Prolonged movement usually happens when the laptop is on the user's lap (see Problem with hot surfaces for implications), or when in a moving vehicle where fan noise is typically overshadowed by vehicle noise.
- Use a PID controller feedback loop instead of simple thresholds.
- Monitor the UltraBay disk temperature too.
See also
- How to control fan speed
- Shimodax's ThinkPad fan control tool for a Windows offers functionality similar to these scripts; see the forum discussion at thinkpads.com.
- Yury Polyanskiy has a kernel patch for automatic fan control in kernelspace (only enable/disable based on maximum temperature).