Controlar las RPM de los ventiladores en Unraid (II)
2024-11-25
Ya vimos como controlar las RPM de los ventiladores de nuestro ordenador en Unraid mediante el uso de los plugins de Dymamix, pero esto no siempre funciona o funciona a medias, es por ello por lo que mediante el uso de un par de sencillos scripts podemos llegar controlarlos de una manera muy parecida.
⚠️ Hay que configurar en la BIOS de la placa base que el control de la temperatura de los sensores se va a realizar por software
Para hacer uso de los scripts es necesarios que tengas instalado el plugin User Scripts
Hay que identificar los sensores que se corresponden con cada ventilador, para ello y tal como expliqué en este otro articulo hacemos uso de pwmconfig
desde una consola
root@Nas01:~# pwmconfig
# pwmconfig version 3.6.0
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. Note that many motherboards do not have pwm
circuitry installed, even if your sensor chip supports pwm.
We will attempt to briefly stop each fan using the pwm controls.
The program will attempt to restore each fan to full speed
after testing. However, it is ** very important ** that you
physically verify that the fans have been to full speed
after the program has completed.
Found the following devices:
hwmon0 is acpitz
hwmon1 is nvme
hwmon2 is nvme
hwmon3 is eth1
hwmon4 is coretemp
hwmon5 is it8613
Found the following PWM controls:
hwmon5/pwm2 current value: 60
hwmon5/pwm3 current value: 106
hwmon5/pwm4 current value: 0
hwmon5/pwm5 current value: 60
Giving the fans some time to reach full speed...
Found the following fan sensors:
hwmon5/fan2_input current speed: 5000 RPM
hwmon5/fan3_input current speed: 2109 RPM
Warning!!! This program will stop your fans, one at a time,
for approximately 5 seconds each!!!
This may cause your processor temperature to rise!!!
If you do not want to do this hit control-C now!!!
Hit return to continue:
Como ves, entre los dispositivos detectados ha encontrado hwmon4 is coretemp
y hwmon5 is it8613
y los sensores PWM con ventiladores conectados hwmon5/fan2_input
y hwmon5/fan3_input
Puedes determinar cual se corresponde con el la CPU y cual con el de la caja, parando o poniendo al máximo las RPM del ventilador, por ejemplo para pleno funcionamiento
echo 255 > /sys/class/hwmon/hwmon5/pwm3
Para pararlo
echo 0 > /sys/class/hwmon/hwmon5/pwm3
En mi ordenador el sensor pwm3
controla el ventilador de la caja y el el pwm2
la cpu
Una vez que tenemos claro que sensor se corresponde con cada ventilador procedemos a crear un script para controlar las RPM del ventilador de la CPU y otro script para conrolar las RPM del ventilador de la caja en función de la temperatura de los discos desde el plugin User Scripts
Script para controlar las RPM del ventilador de la CPU
#!/bin/bash
TEMPS=(0 40 55 75 80)
SPEEDS=(60 90 130 190 255)
# Fan device. Depends on your system. pwmconfig can help with finding this out.
# pwm1 is usually the cpu fan. You can "cat /sys/class/hwmon/hwmon0/device/fan1_input"
# or fan2_input and so on to see the current rpm of the fan. If 0 then fan is off or
# there is no fan connected or motherboard can't read rpm of fan.
CPU_FAN=/sys/class/hwmon/hwmon5/pwm2
#REPLACE HD TEMP WITH CPU TEMP FROM SENSORS
HIGHEST_TEMP=$(/usr/bin/sensors | grep "CPU Temp" | cut -d"+" -f2 | cut -c1-2)
for i in ${!TEMPS[@]}; do
CHECKTEMP=${TEMPS[$i]}
#echo "loop " $i $CHECKTEMP
if [ "$HIGHEST_TEMP" -le "$CHECKTEMP" ]; then
break
fi
LASTTEMP=${TEMPS[$i]}
FANSET=${SPEEDS[$i]}
done
echo "Temp " $HIGHEST_TEMP " >= " $LASTTEMP "Setting fan to " $FANSET
echo $FANSET > $CPU_FAN
Aquí tienes que jugar con los ajustes de temperatura y las RPM a las que quieres que funcione el ventilador, con las variables TEMPS
y SPEEDS
🗨️
CPU_FAN
es el sensor que va a controlar el ventilador, aquí debes de poner el que se corresponda con el tuyo.
Comprueba que el script se ejecuta sin errores
Configura el script para que se ejecute cada minuto
No olvides aplicar los cambios
Script para controlar las RPM del ventilador de la caja
El siguiente script controla la velocidad del ventilador de la caja en funcion de la temperatura del array de los discos.
#!/bin/bash
# This script will automatically adjust the fans speed
# based on your hard drives temperature. You may select
# which disks to include and exclude and play around with
# different temperature settings.
# Prerequisites:
# 1. Enable manual fan speed control in Unraid
# This can be done by editing "/boot/syslinux/syslinux.cfg"
# Right beneath "label Unraid OS" you will have to change:
# "append initrd=/bzroot" to "append initrd=/bzroot acpi_enforce_resources=lax"
# 2. Set the PWM headers you want to control to 100%/255 and mode to PWM in your BIOS
# Tips:
# In order to see what fan headers Unraid sees use "sensors -uA"
# Another useful tool is "pwmconfig". Makes it easier to find the correct fan header
# You may test your pwm pins from the terminal. Here is a list of attributes:
# pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range:
# 0 (lowest speed) to 255 (full)
# pwm[1-5]_enable - this file controls mode of fan/temperature control:
# * 0 Fan control disabled (fans set to maximum speed)
# * 1 Manual mode, write to pwm[0-5] any value 0-255
# * 2 "Thermal Cruise" mode
# * 3 "Fan Speed Cruise" mode
# * 4 "Smart Fan III" mode (NCT6775F only)
# * 5 "Smart Fan IV" mode
# pwm[1-5]_mode - controls if output is PWM or DC level
# * 0 DC output
# * 1 PWM output
# Minimum PWM value
# Used when all disks are spun down
# and fan speed will never be set to a lower value
MIN_PWM=40
# Low/High PWM values
# Used for calculating new PWM values when
# disk temp is between LOW_TEMP and HIGH_TEMP temperature
LOW_PWM=60
HIGH_PWM=225
# Max PWM
# Used for setting the fan to max speed while parity
# is running or if the disk temperature is too hot
# This settings should in most cases NOT BE CHANGED!
MAX_PWM=255
# Low/High temperature
# Define the disks temperature range for when
# the fans speed should be automatically adjusted
#LOW_TEMP=35
LOW_TEMP=40
HIGH_TEMP=50
# Max temperature
# If the hottest disk reaches this temperature
# a notification will be sent through Unraid
MAX_TEMP=55
# Disks to monitor
# Select disks to include by type and
# exclude by name (found in disk.ini)
INCLUDE_DISK_TYPE_PARITY=1
INCLUDE_DISK_TYPE_DATA=1
INCLUDE_DISK_TYPE_CACHE=0
INCLUDE_DISK_TYPE_FLASH=0
EXCLUDE_DISK_BY_NAME=(
"cache"
"sistema"
"sistema2"
)
# Array fans
# Define one or more fans that should be controlled by this script
ARRAY_FANS=(
"/sys/class/hwmon/hwmon5/pwm3"
)
############################################################
# Make a list of disk types the user wants to monitor
declare -A include_disk_types
include_disk_types[Parity]=$INCLUDE_DISK_TYPE_PARITY
include_disk_types[Data]=$INCLUDE_DISK_TYPE_DATA
include_disk_types[Cache]=$INCLUDE_DISK_TYPE_CACHE
include_disk_types[Flash]=$INCLUDE_DISK_TYPE_FLASH
# Make a list of all the existing disks
declare -a disk_list_all
while IFS='= ' read var val
do
if [[ $var == \[*] ]]
then
disk_name=${var:2:-2}
disk_list_all+=($disk_name)
eval declare -A ${disk_name}_data
elif [[ $val ]]
then
eval ${disk_name}_data[$var]=$val
fi
done < /var/local/emhttp/disks.ini
# Filter disk list based on criteria
declare -a disk_list
for disk in "${disk_list_all[@]}"
do
disk_name=${disk}_data[name]
disk_type=${disk}_data[type]
disk_id=${disk}_data[id]
disk_type_filter=${include_disk_types[${!disk_type}]}
if [[ ! -z "${!disk_id}" ]] && \
[[ "${disk_type_filter}" -ne 0 ]] && \
[[ ! " ${EXCLUDE_DISK_BY_NAME[*]} " =~ " ${disk} " ]]
then
disk_list+=($disk)
fi
done
# Check temperature
declare -A disk_state
declare -A disk_temp
disk_max_temp_value=0
disk_max_temp_name=null
disk_active_num=0
for disk in "${disk_list[@]}"
do
# Check disk state
eval state_value=${disk}_data[spundown]
if (( ${state_value} == 1 ))
then
state=spundown
disk_state[${disk}]=spundown
else
state=spunup
disk_state[${disk}]=spunup
disk_active_num=$((disk_active_num+1))
fi
# Check disk temperature
temp=${disk}_data[temp]
if [[ "$state" == "spunup" ]]
then
if [[ "${!temp}" =~ ^[0-9]+$ ]]
then
disk_temp[${disk}]=${!temp}
if (( "${!temp}" > "$disk_max_temp_value" ))
then
disk_max_temp_value=${!temp}
disk_max_temp_name=$disk
fi
else
disk_temp[$disk]=unknown
fi
else
disk_temp[$disk]=na
fi
done
# Check if parity is running
disk_parity=$(awk -F'=' '$1=="mdResync" {gsub(/"/, "", $2); print $2}' /var/local/emhttp/var.ini)
# Linear PWM Logic
pwm_steps=$((HIGH_TEMP - LOW_TEMP - 1))
pwm_increment=$(( (HIGH_PWM - LOW_PWM) / pwm_steps))
# Print heighest disk temp if at least one is active
if [[ $disk_active_num -gt 0 ]]; then
echo "Hottest disk is $disk_max_temp_name at $disk_max_temp_value°C"
fi
# Calculate new fan speed
# Handle cases where no disks are found
if [[ ${#disk_list[@]} -gt 0 && ${#disk_list[@]} -ne ${#disk_temp[@]} ]]
then
fan_msg="No disks included or unable to read all disks"
fan_pwm=$MAX_PWM
# Parity is running
elif [[ "$disk_parity" -gt 0 ]]
then
fan_msg="Parity-Check is running"
fan_pwm=$MAX_PWM
# All disk are spun down
elif [[ $disk_active_num -eq 0 ]]
then
fan_msg="All disks are in standby mode"
fan_pwm=$MIN_PWM
# Hottest disk is below the LOW_TEMP threshold
elif (( $disk_max_temp_value <= $LOW_TEMP ))
then
fan_msg="Temperature of $disk_max_temp_value°C is below LOW_TEMP ($LOW_TEMP°C)"
fan_pwm=$MIN_PWM
# Hottest disk is between LOW_TEMP and HIGH_TEMP
elif (( $disk_max_temp_value > $LOW_TEMP && $disk_max_temp_value <= $HIGH_TEMP ))
then
fan_msg="Temperature of $disk_max_temp_value°C is between LOW_TEMP ($LOW_TEMP°C) and HIGH_TEMP ($HIGH_TEMP°C)"
fan_pwm=$(( ((disk_max_temp_value - LOW_TEMP - 1) * pwm_increment) + MIN_PWM ))
# Hottest disk is between HIGH_TEMP and MAX_TEMP
elif (( $disk_max_temp_value > $HIGH_TEMP && $disk_max_temp_value <= $MAX_TEMP ))
then
fan_msg="Temperature of $disk_max_temp_value°C is between HIGH_TEMP ($HIGH_TEMP°C) and MAX_TEMP ($MAX_TEMP°C)"
fan_pwm=$MAX_PWM
# Hottest disk exceeds MAX_TEMP
elif (( $disk_max_temp_value > $MAX_TEMP ))
then
alert_msg="$disk_max_temp_name exceeds ($MAX_TEMP°C)"
fan_msg=$alert_msg
fan_pwm=$MAX_PWM
# Send an alert
/usr/local/emhttp/webGui/scripts/notify \
-i alert \
-s "Disk (${disk_max_temp_name}) overheated" \
-d "$alert_msg"
# Handle any unexpected condition
else
fan_msg="An unexpected condition occurred"
fan_pwm=$MAX_PWM
fi
# Apply fan speed
for fan in "${ARRAY_FANS[@]}"
do
# Set fan mode to 1 if necessary
pwm_mode=$(cat "${fan}_enable")
if [[ $pwm_mode -ne 1 ]]; then
echo 1 > "${fan}_enable"
fi
# Set fan speed
echo $fan_pwm > $fan
done
pwm_percent=$(( (fan_pwm * 100) / 255 ))
echo "$fan_msg, setting fans to $fan_pwm PWM ($pwm_percent%)"
Al igual que el anterior script este también es configurable, eligiendo la temperatura mas baja a la cual el ventilador deja de giar, revoluciones miniamos, máximas, etc
También nos va a permitir seleccionar los discos a incluir o excluir a monitorizar. Un script bastante configurable como puedes ver.
Comprueba que el script se ejecuta sin errores
Por ultimo configuralo para que se ejecute cada 5 minutos, por ejemplo:
Espero que te haya gustado, pasa un gran día 🐧