Compartilho uma solução para um problema que me afetava em um Laptop Acer Predator Helios Neo 16 - PHN16-72. Mas que pode com alguns poucos ajustes ajudar outras pessoas com o mesmo problema.
O Problema:
O acer não tem na sua BIOS o controle de temperatura que possa ser alterado fica tudo escondido e pode ser modificado (via Windows) com o app da própria Acer. No linux por algum motivo esse controle era inexistente ou ineficiente e o micro passou a desligar-se por problema de super aquecimento. Por tratar-se de um core i7 com uma 4070 isso ficou perigosamente frequente.
Depois de muito pesquisar, com um pouco de ajuda do ChatGPT (e me atrapalhou bastante também) cheguei a uma solução que pode ajudar mais pessoas e deixo aqui o registro. Foi feito baseado no CachyOS (Arch) meu sistema atual, mas com poucos ajustes pode ser usado em outras distribuições.
GUIA COMPLETO — CONTROLE DE FAN (ACER PREDATOR + LINUX)
Objetivo
Restaurar controle de fan em notebooks Acer Predator no Linux, especialmente após kernels novos onde NBFC quebra ou fica instável.
Pré-requisitos
-
Linux (Arch / CachyOS / derivados testados)
-
GPU NVIDIA (testado com RTX 30/40)
-
Acesso root (
sudo) -
NBFC instalado
1. Instalar dependências
Pacotes necessários
Arch / CachyOS:
sudo pacman -S lm_sensors nvidia-utils stress-ng
NBFC (AUR):
yay -S nbfc-linux
Detectar sensores
sudo sensors-detect
Aceita tudo com YES.
Depois testa:
sensors
2. Preparar acesso ao EC
Habilitar escrita no EC
sudo modprobe ec_sys write_support=1
Persistir:
echo "options ec_sys write_support=1" | sudo tee /etc/modprobe.d/ec_sys.conf
3. Configurar NBFC
Edita:
sudo nano /etc/nbfc/nbfc.json
Conteúdo:
{
"SelectedConfigId": "Acer Predator PH315-54",
"EmbeddedControllerType": "dev_port"
}
Teste básico
sudo nbfc start
nbfc status
Se aparecer ativo → OK.
4. Criar script de controle
Cria o arquivo:
mkdir -p ~/bin
nano ~/bin/fan-control.sh
Script
#!/bin/bash
LOGDIR="/tmp/fan-control"
mkdir -p "$LOGDIR"
temps=()
last_speed=-1
last_change_time=0
last_cpu_temp=0
start_nbfc() {
if ! nbfc status >/dev/null 2>&1; then
nbfc stop >/dev/null 2>&1
sleep 1
nbfc start
sleep 2
fi
}
get_cpu_temp() {
sensors | grep "Package id 0" | awk '{print int($4)}' | tr -d '+°C'
}
get_nvidia_temp() {
nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits 2>/dev/null
}
get_gpu_usage() {
nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits 2>/dev/null
}
get_cpu_usage() {
top -bn1 | grep "Cpu(s)" | awk '{print int(100 - $8)}'
}
is_on_ac() {
grep -q 1 /sys/class/power_supply/AC*/online 2>/dev/null
}
get_avg_temp() {
local sum=0
[ "${#temps[@]}" -eq 0 ] && echo 0 && return
for t in "${temps[@]}"; do
sum=$((sum + t))
done
echo $((sum / ${#temps[@]}))
}
start_nbfc
while true; do
LOGFILE="$LOGDIR/fan-control-$(date +%Y-%m-%d).log"
cpu_temp=$(get_cpu_temp)
nvidia_temp=$(get_nvidia_temp)
cpu_usage=$(get_cpu_usage)
gpu_usage=$(get_gpu_usage)
[ -z "$cpu_temp" ] && cpu_temp=0
[ -z "$nvidia_temp" ] && nvidia_temp=0
[ -z "$cpu_usage" ] && cpu_usage=0
[ -z "$gpu_usage" ] && gpu_usage=0
# média móvel (mantida pra log/diagnóstico)
temps+=($cpu_temp)
if [ "${#temps[@]}" -gt 5 ]; then
temps=("${temps[@]:1}")
fi
avg_temp=$(get_avg_temp)
current_time=$(date +%s)
############################################
# 🧠 DETECÇÃO DE CARGA GLOBAL
############################################
if [ "$cpu_usage" -gt 70 ] || [ "$gpu_usage" -gt 70 ]; then
load_mode="heavy"
elif [ "$cpu_usage" -gt 30 ] || [ "$gpu_usage" -gt 30 ]; then
load_mode="medium"
else
load_mode="light"
fi
############################################
# ⚡ PERFIL (AC vs bateria)
############################################
if is_on_ac; then
profile="performance"
else
profile="silent"
fi
############################################
# 🔥 TEMPERATURA DOMINANTE
############################################
max_temp=$cpu_temp
[ "$nvidia_temp" -gt "$max_temp" ] && max_temp=$nvidia_temp
############################################
# 🎯 CURVA INTELIGENTE
############################################
if [ "$profile" = "performance" ]; then
case $load_mode in
heavy)
if [ "$max_temp" -ge 80 ]; then speed=100
elif [ "$max_temp" -ge 70 ]; then speed=90
elif [ "$max_temp" -ge 60 ]; then speed=80
else speed=70
fi
;;
medium)
if [ "$max_temp" -ge 75 ]; then speed=90
elif [ "$max_temp" -ge 65 ]; then speed=75
elif [ "$max_temp" -ge 55 ]; then speed=60
else speed=50
fi
;;
light)
if [ "$max_temp" -ge 70 ]; then speed=80
elif [ "$max_temp" -ge 60 ]; then speed=60
else speed=40
fi
;;
esac
else
if [ "$max_temp" -ge 80 ]; then speed=90
elif [ "$max_temp" -ge 70 ]; then speed=70
elif [ "$max_temp" -ge 60 ]; then speed=50
else speed=30
fi
fi
############################################
# 🔥 SEGURANÇA ABSOLUTA
############################################
if [ "$cpu_temp" -ge 90 ] || [ "$nvidia_temp" -ge 88 ]; then
speed=100
fi
############################################
# 🔄 HISTERese
############################################
if [ "$speed" -gt "$last_speed" ]; then
apply=1
last_change_time=$current_time
elif [ "$speed" -lt "$last_speed" ]; then
if [ "$cpu_temp" -le $((last_cpu_temp - 3)) ] && \
[ $((current_time - last_change_time)) -gt 8 ]; then
apply=1
last_change_time=$current_time
else
apply=0
fi
else
apply=0
fi
############################################
# 🔧 NBFC CHECK
############################################
if ! nbfc status >/dev/null 2>&1; then
echo "$(date '+%F %T') | NBFC caiu, reiniciando..." >> "$LOGFILE"
start_nbfc
fi
############################################
# 🚀 APPLY (SEM FLOOD)
############################################
if [ "$apply" -eq 1 ]; then
nbfc set -s "$speed"
last_speed=$speed
fi
############################################
# 🔔 ALERTA
############################################
if [ "$cpu_temp" -ge 85 ]; then
notify-send "🔥 CPU CRÍTICA: ${cpu_temp}°C"
fi
############################################
# 📝 LOG
############################################
echo "$(date '+%F %T') | CPU:${cpu_temp}°C GPU:${nvidia_temp}°C CPU_LOAD:${cpu_usage}% GPU_LOAD:${gpu_usage}% MODE:${profile}/${load_mode} FAN:${speed}%" >> "$LOGFILE"
find "$LOGDIR" -name "fan-control-*.log" -mtime +7 -delete
last_cpu_temp=$cpu_temp
sleep 5
done
Permissão
chmod +x ~/bin/fan-control.sh
5. Criar serviço systemd
Cria:
sudo nano /etc/systemd/system/fan-control.service
Conteúdo:
[Unit]
Description=Fan Control Script
After=multi-user.target
[Service]
ExecStart=/home/SEU_USUARIO/bin/fan-control.sh
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
Substitui SEU_USUARIO
Ativar serviço
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable fan-control
sudo systemctl start fan-control
Ver status
sudo systemctl status fan-control
6. Testar funcionamento
Monitorar log
tail -f /tmp/fan-control/fan-control-$(date +%Y-%m-%d).log
Teste de carga
stress-ng --cpu 8
Comportamento esperado
-
Fan sobe antes do spike térmico
-
CPU/GPU não passam de ~80–85°C facilmente
-
Sem “respiração” (oscilação constante)
Como funciona (resumo técnico)
O script:
-
lê:
-
temperatura CPU
-
temperatura GPU
-
uso CPU (%)
-
uso GPU (%)
-
-
decide baseado em:
-
carga (leve / média / pesada)
-
fonte de energia (AC vs bateria)
-
temperatura dominante
-
-
aplica:
-
curva dinâmica
-
histerese (evita oscilar)
-
proteção térmica
-