Difference between revisions of "Code/tp-fancontrol-basic"
(moved from ACPI fan control script) |
(No difference)
|
Revision as of 22:08, 26 July 2006
- !/bin/bash
- This script dynamically controls fan speed on some ThinkPad models
- 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 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
# (this also prevents fan speed updates)
IBM_ACPI=/proc/acpi/ibm 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."; }
- Enable the fan in default mode if anything goes wrong:
set -e -E -u $DRY_RUN || trap "echo enable > $FAN; exit 0" EXIT HUP INT ABRT QUIT SEGV TERM
thermometer() { # output list of temperatures
read X Y < $IBM_ACPI/thermal "$X" == "temperatures:" || {
echo "$0: Bad temperatures: $X $Y" >&2 exit 1
} echo "$Y";
}
speedometer() { # output fan speed
cat $FAN | sed '/^speed/!d; s/speed:[ \t]*//'
}
IDX=0 MAX_IDX=$(( ${#LEVELS[@]} - 1 )) SETTLE=0
while true; do
TEMPS=`thermometer` $VERBOSE && SPEED=`speedometer`
# Calculate new level
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
OLDLEVEL=${LEVELS[$IDX]}
NEWLEVEL=${LEVELS[$NEWIDX]}
$VERBOSE && echo "tpfan: Temps: $TEMPS Fan: $SPEED Level: $OLDLEVEL->$NEWLEVEL"
$DRY_RUN || echo level $NEWLEVEL > $FAN
sleep $INTERVAL
# 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