Custom PWM Fan Control Script based on Disk Temps using disks.ini to Avoid Drive Spinup


Recommended Posts

Have been working on a custom script to manage fan control within my external disk only 24 bay chassis using drive temps within unraid.

Didnt like the auto fan control plugin or another custom script I found as using smart reports caused drives to spinup unnecessarily.

Additionally as using 3x 3A 120mm server fans both noise and power consumption were issues needing bringing in check.

So I have parsed the disks.ini file to check temps reported by UNRAID itself.

I wanted to go this route to remove any unnecessary additional scripts/dockers/plugins, just simple check unraid reported temps and adjust fans accordingly.

Its a little crude right now but seems to be working, after a few hours of testing.

Feel free to offer any comments/suggestions but please be gentle as was my first attempt at bash scripting.

 

Can probably reduce the pwm level steps, would like to implement basic logging and needs bit more testing but its a good start.

 

Few ideas/lines were borrowed from another script I found online but struggling to find right now to credit.

 

#!/bin/bash
##VARIABLES
MIN_PWM=40
LOW_PWM=50
HIGH_PWM=180
MAX_PWM=220
LOW_TEMP=25
HIGH_TEMP=35
MAX_TEMP=39
ARRAY_FAN=/sys/class/hwmon/hwmon2/pwm3

##Disk Types Checked (0 disabled, 1 enabled)
declare -A diskTypesChecked
diskTypesChecked[Parity]=1
diskTypesChecked[Data]=1
diskTypesChecked[Cache]=0
diskTypesChecked[Flash]=0

##Excluded Disks (name as in disk.ini)
excludedDisks=(nvme,cache,cache2,flash)

##Variables
isNumber='^[0-9]+$'

##GET LIST OF ARRAY DISKS
declare -a fullDiskList
while IFS='= ' read var val
do
    if [[ $var == \[*] ]]
    then
        section=${var:2:-2}
        fullDiskList+=($section)
        eval declare -A ${section}_data
    elif [[ $val ]]
    then 
        eval ${section}_data[$var]=$val
    fi
done < /var/local/emhttp/disks.ini

##filter out excluded disks and disk types
declare -a diskList
for disk in "${fullDiskList[@]}"
do
    diskName=${disk}_data[name]
    diskType=${disk}_data[type]
    diskId=${disk}_data[id]
    diskTypeChecked=${diskTypesChecked[${!diskType}]}
    if [[ "${!diskId}" == "" ]] ##ignore unassigned slots
    then
        : ##dont check
    elif [[ "${diskName}" == "${excludedDisks[*]}" ]] ##needs improvement
    then
        : ##dont check
    elif (( ${diskTypeChecked} == 0 ))
    then
        : ##dont check
     else
        diskList+=($disk)
    fi
done



##CHECK DISKS
declare -A diskState
declare -A diskTemp
maxTempC=0
maxTempDisk=null
activeDisks=0

for disk in "${diskList[@]}"
do
    ##check disk state
    eval thisDiskStateVal=${disk}_data[spundown]
    if (( ${thisDiskStateVal} == 1 ))
    then
        thisDiskState=spundown
        diskState[${disk}]=spundown
    else
        thisDiskState=spunup
        diskState[${disk}]=spunup
		activeDisks=$((activeDisks+1))
    fi
    ##check disk temp
    thisDiskTemp=${disk}_data[temp]
	
    if [[ "$thisDiskState" == "spunup" ]]
    then
        if [[ "${!thisDiskTemp}" =~ $isNumber ]]
        then
            diskTemp[${disk}]=${!thisDiskTemp}
            if (( "${!thisDiskTemp}" > "$maxTempC" ))
            then
                maxTempC=${!thisDiskTemp}
                maxTempDisk=$disk
            fi
        else
            diskTemp[$disk]=unknown
        fi
    else
        diskTemp[$disk]=na
    fi
done

echo Hottest Disk is $maxTempDisk at $maxTempC C

##calculate PWM
##maxTempC=26 ##overide temp for manual control
# Linear PWM Logic Variables - do not modify
NUM_STEPS=$((HIGH_TEMP - LOW_TEMP - 1))
PWM_INCREMENT=$(( (HIGH_PWM - LOW_PWM) / NUM_STEPS))

if (( $activeDisks == 0 ))
then
    ##all disks spun down
	echo All drives are idle/spundown, setting fans to minimum.
	FAN_PWM=$MIN_PWM
	
elif (( $maxTempC <= $LOW_TEMP ))
then
    ##if hottest drive below low
	echo $maxTempC C is below low temp of $LOW_TEMP C, setting fans to minimum.
	FAN_PWM=$MIN_PWM

elif (( $maxTempC > $LOW_TEMP && $maxTempC <= $HIGH_TEMP ))
then
    ##if hottest drive above low but below high
	echo $maxTempC C is above low temp of $LOW_TEMP C but below high temp of $HIGH_TEMP C, setting fans to ...
	FAN_PWM=$(( ((maxTempC - LOW_TEMP - 1) * PWM_INCREMENT) + MIN_PWM ))
elif (( $maxTempC > $HIGH_TEMP && $maxTempC <= $MAX_TEMP ))
then
    ##if hottest drive above high but below max
	echo $maxTempC C is above high temp of $HIGH_TEMP C but below max temp of $MAX_TEMP C, setting fans to ...
	FAN_PWM=$MAX_PWM

elif (( $maxTempC > $MAX_TEMP ))
then
    ##if hottest drive exceeds max temp
    ##pause parity/alert
	echo $maxTempC C is above max temp of $MAX_TEMP C, setting fans to full and ...
	FAN_PWM=255

else
    ##if all else fails - full power fans
    echo undefined outcome, setting fans to full and ...
	FAN_PWM=255

fi

echo $FAN_PWM > $ARRAY_FAN
echo Fan PWM set to $FAN_PWM

#for key in "${!diskList[@]}"
#do
#  echo -n "key  : $key, "
#  echo "value: ${diskList[$key]}"
#done
#
#for key in "${!diskTemp[@]}"
#do
#  echo -n "key  : $key, "
#  echo "value: ${diskTemp[$key]}"
#done

#param=temperature
#echo ${!parity_data[@]}
#echo ${!disk2_data[@]}
#echo \*

 

Edited by Joseph Trice-Rolph
Link to comment
  • Joseph Trice-Rolph changed the title to Custom PWM Fan Control Script based on Disk Temps using disks.ini to Avoid Drive Spinup
  • 5 months later...
  • 4 months later...
On 10/6/2021 at 9:28 AM, Joseph Trice-Rolph said:

Have been working on a custom script to manage fan control within my external disk only 24 bay chassis using drive temps within unraid.

Didnt like the auto fan control plugin or another custom script I found as using smart reports caused drives to spinup unnecessarily.

 

This is a great script, I wish this had been around when i was looking earlier.

 

I was using this one, but found that all drives would be spun up just to check the temperature. This one here - 

 

Another request that feel free to ignore, but would be to be able to set an additional temperature monitor and desired temperature range. As in a motherboard temperature, and be able to spin fans based on MB temp or HDD temp, whichever is higher in its range.

Link to comment
  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.