问题
当笔记本电脑插上电源且未充电时,风扇会一直打开。噪音不大,但肯定能听到。
然而,当笔记本电脑未插上电源或仍在充电时,风扇偶尔会保持静音(旋转速度较慢或根本不旋转)。
问题
当机器一直插着电源却没有充电时,如何实现同样的效果?
也许解决方案就这么简单:https://askubuntu.com/a/300921/69296
机器:
- 惠普 Elitebook 8470p
- Ubuntu 13.10 LTS(全新安装,实际上是 Lubuntu 风格,但没什么区别)
- 英特尔 i5-3360M
uname -a
: Linux elite 3.11.0-12-generic #19-Ubuntu SMP 星期三 十月 9 16:20:46 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux- 8GB 内存
- SATA3 固态硬盘
- AMD Radeon HD 7570M
power_method
:profile
,power_profile
:auto
答案1
我有一台 HP 4510s 笔记本电脑。风扇控制在 Windows 下工作正常。在任何尝试过的 Linux 发行版/版本下都不起作用。在 Linux/Ubuntu 下,风扇以非常低的速度运行。这不足以在高负载下保持 CPU 足够凉爽。
我尝试了互联网上关于 Linux 笔记本电脑风扇控制的大多数提示,但都不起作用。我尝试了 lm_sensors、pwmconfig、acpi_os= 设置和许多其他方法,但都无济于事。我更新了 BIOS,除了“交流电时风扇始终打开”外什么也没有,而且它不起作用。
可以使用 lm_sensors 获取系统温度。此外,风扇控制点位于
/sys/devices/virtual/thermal/cooling_device*/cur_state (* 0-4 处于活动状态)
我最终从
http://thinkwiki.org/wiki/ACPI_fan_control_script
并将其改成 hp-fancontrol。我对自动化研究的记忆不够深刻(那是 20 年前的事了),所以它变得非常简单。但到目前为止它似乎可以正常工作。仍然有很多剩余的代码,而且它丑陋得要命。我将其安装为 /usr/bin/hp_fancontrol,并像这样将触发器添加到 /etc/rc.local
# Start hp-fancontrol on multiuser
/usr/bin/hp-fancontrol -l -d
exit 0
如果有更好的办法,我将不胜感激,即使只是 control_loop 部分,所以请发表评论。另外,请保持礼貌并阅读免责声明(丑陋如……上面和代码本身)。QUIET 似乎不起作用,它破坏了 DAEMONIZE。
#!/bin/bash
# hp-fancontrol 0.1
# Based on tp-fancontrol (http://thinkwiki.org/wiki/ACPI_fan_control_script)
# 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 HP laptop models
# (ProBook 4510s) according to user-defined temperature thresholds. It
# implements its own decision algorithm, overriding the any embedded
# controller.
#
# Run 'hp-fancontrol --help' for options.
#
# For optimal fan behavior during suspend and resume, invoke
# "hp-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 core:
# (min temperature: when to step up from 0-th fan level,
# max temperature: when to step up to maximum fan level)
THRESHOLDS=( # Core
# min max # ----
43 65 # 0
43 65 # 1
)
# LEVELS=0 - 31 (5 bits) # Fan speed levels
ANTIPULSE=1 # Prevent fan pulsing noise
# (reduces frequency of fan RPM updates)
OFF_THRESH_DELTA=3 # when gets this much cooler than 'min' above, may turn off fan
MIN_THRESH_SHIFT=0 # increase min thresholds by this much
MAX_THRESH_SHIFT=0 # increase max thresholds by this much
MIN_WAIT=180 # minimum time (seconds) to spend in a given level before
# stepping down
HP_ACPI=/sys/devices/virtual/thermal/cooling_device
PID_FILE=/var/run/hp-fancontrol.pid
LOGGER=/usr/bin/logger
INTERVAL=3 # sample+refresh interval
SETTLE_TIME=6 # wait this many seconds long before applying anti-pulsing
RESETTLE_TIME=600 # briefly disable anti-pulsing at every N seconds
SUSPEND_TIME=5 # seconds to sleep when receiving SIGUSR1
SEP=',' # Separator char for display
WATCHDOG_DELAY=$(( 3 * INTERVAL ))
HAVE_WATCHDOG=false
HAVE_LEVELCMD=true
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 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, default: $PID_FILE
"
exit 1;
}
while getopts 's:S:qtdlp:kuh' OPT; do
case "$OPT" in
s) # shift thresholds
MIN_THRESH_SHIFT="$OPTARG"
;;
S) # shift thresholds
MAX_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
# 2 basic temperatures from CPU cores:
CPU0=`/usr/bin/sensors | /usr/bin/awk '/Core 0/ { print $3 }' | sed -e s/[^0-9]//g`
CPU1=`/usr/bin/sensors | /usr/bin/awk '/Core 1/ { print $3 }' | sed -e s/[^0-9]//g`
echo -n "$CPU0 $CPU1 ";
return 0
}
speedometer() { # output fan speed RPM
read F0 < /sys/devices/virtual/thermal/cooling_device0/cur_state
read F1 < /sys/devices/virtual/thermal/cooling_device1/cur_state
read F2 < /sys/devices/virtual/thermal/cooling_device2/cur_state
read F3 < /sys/devices/virtual/thermal/cooling_device3/cur_state
read F4 < /sys/devices/virtual/thermal/cooling_device4/cur_state
FAN=$(($F4+$F3*2+$F2*4+$F1*8+$F0*16))
echo -n $FAN;
return 0
}
setlevel() { # set fan speed level
local LEVEL=$1
if ! $DRY_RUN; then
if $HAVE_LEVELCMD; then
BLEVEL=$(echo "obase=2;$LEVEL" | bc)
LEN=$(echo ${#BLEVEL})
BLEVEL5=`echo "0000"$BLEVEL`
B5=${BLEVEL5:(-5)}
echo ${B5:0:1} > /sys/devices/virtual/thermal/cooling_device0/cur_state
echo ${B5:1:1} > /sys/devices/virtual/thermal/cooling_device1/cur_state
echo ${B5:2:1} > /sys/devices/virtual/thermal/cooling_device2/cur_state
echo ${B5:3:1} > /sys/devices/virtual/thermal/cooling_device3/cur_state
echo ${B5:4:1} > /sys/devices/virtual/thermal/cooling_device4/cur_state
else
case "$LEVEL" in
(auto) LEVEL=0x80 ;;
(disengaged) LEVEL=0x40 ;;
esac
#echo 0x2F $LEVEL > $IBM_ACPI/ecdump
fi
fi
}
getlevel() { # get fan speed level
# perl -e 'm/^EC 0x20: .* .(..)$/ and print $1 and exit 0 while <>; exit 1' < $IBM_ACPI/ecdump
read F0 < /sys/devices/virtual/thermal/cooling_device0/cur_state
read F1 < /sys/devices/virtual/thermal/cooling_device1/cur_state
read F2 < /sys/devices/virtual/thermal/cooling_device2/cur_state
read F3 < /sys/devices/virtual/thermal/cooling_device3/cur_state
read F4 < /sys/devices/virtual/thermal/cooling_device4/cur_state
FAN=$(($F4+$F3*2+$F2*4+$F1*8+$F0*16))
echo -n $FAN;
}
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, fan turned up"
if ! $DRY_RUN; then
if $HAVE_LEVELCMD; then
setlevel 31
fi
fi
}
floor_div() {
echo $(( (($1)+1000*($2))/($2) - 1000 ))
}
set_priority() {
! $DRY_RUN && renice -10 -p $$
}
init_state() {
IDX=0
NEW_IDX=0
START_TIME=0
MAX_IDX=31
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
# Get readouts
TEMPS=`thermometer`
$QUIET || SPEED=`speedometer`
$QUIET || ECLEVEL=`getlevel`
NOW=`date +%s`
if echo "$TEMPS" | grep -q "[^ 0-9$SEP\n-]"; then
echo "Invalid character in temperatures: $TEMPS" >&2; exit 1;
fi
OLDLEVEL=$ECLEVEL
NEWLEVEL=$OLDLEVEL
CHANGE=0
for TEMP in $TEMPS; do
if [ $TEMP -gt 430 ] ; then
if [ $OLDLEVEL -lt 31 ] ; then
CHANGE=$(($CHANGE+1)) ;
# NEWLEVEL=$(($OLDLEVEL+1)) ;
fi
elif [ $TEMP -gt 410 ] ; then
# No change between 41-43C
CHANGE=$(($CHANGE)) ;
else
if [ $OLDLEVEL -gt 0 ] ; then
CHANGE=$(($CHANGE-1)) ;
# NEWLEVEL=$(($OLDLEVEL-1)) ;
fi
fi
NEWLEVEL=$(($OLDLEVEL+$CHANGE)) ;
if [ $NEWLEVEL -gt 31 ] ; then
NEWLEVEL=31 ;
fi
if [ $NEWLEVEL -lt 0 ] ; then
NEWLEVEL=0 ;
fi
OLDLEVEL=$NEWLEVEL ;
done
# Interrupted by a signal?
if $RESTART; then
init_state
log "Resetting state"
continue
fi
# Transition
if [ "$ECLEVEL" != "$NEWLEVEL" ]; then
START_TIME=$NOW
log "Changing fan level: $ECLEVEL->$NEWLEVEL (temps: $TEMPS)"
fi
setlevel $NEWLEVEL
sleep $INTERVAL
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
set_priority
AM_DAEMON=true QUIET=false control_fan 0<&- 1>&- 2>&- &
echo "$0: Starting as daemon"
echo $! > "$PID_FILE"
exit 0
fi
else
[ -e "$PID_FILE" ] && echo "WARNING: daemon already running"
set_priority
control_fan
fi
答案2
风扇速度设置明确不受操作系统的控制,否则我可能是错的。
但我知道适用于 Windows 的实用程序很少。不过,有些 BIOS 会为您提供控制风扇行为的选项。您应该先在 BIOS 中检查这些选项。
不建议使用会改变某些关键硬件行为的实用程序。