# Dynamic fancontrol? [Solved]

## nic01

Hi there.

I'm playing around with fancontrol to get an acceptable fan speed. After upgrading my Gigabyte K8NS Ultra-939 (will strongly advise people NOT to buy this piece of crap board!!) to BIOS F8 (from F5) the CPU fan is killing me. Idle cpu toogles the CPU fan to 3-4000 RPM CPU temp around 30 degrees. So I disabled the dynamic CPU fan in the BIOS.

Now what I want it to do is the following:

Temp below 45 degrees: CPU fan off

Temp between 45 - 55: CPU fan ~3000 RPM

Temp above 55: full CPU fan speed (max is around 5800 RPM)

When I use the fancontrol script the fan enables, as it's supposed to, at 45 degrees, but it's full speed. 

```
echo 15 > /sys/bus/i2c/devices/0-0290/pwm1
```

 gives me a the ideal 3000 RPM medium CPU fan speed.[/code]

My /etc/fancontrol

```

INTERVAL=10

FCTEMPS= 0-0290/pwm1=0-0290/temp2_input

FCFANS= 0-0290/pwm1=0-0290/fan1_input

MINTEMP= 0-0290/pwm1=45

MAXTEMP= 0-0290/pwm1=55

MINSTART= 0-0290/pwm1=15

MINSTOP= 0-0290/pwm1=100

```

Thanks,

NicLast edited by nic01 on Mon Aug 15, 2005 12:38 pm; edited 1 time in total

----------

## theDOC_23

That is pretty much what I wanted to do, so i patched the fancontol script a bit:

```

#!/bin/bash

#

# Simple script implementing a temperature dependent fan speed control

#

# Version 0.63

#

# Usage: fancontrol [CONFIGFILE]

#

# Dependencies:

#   bash, awk, egrep, sed, lm_sensors :)

#

# Please send any questions, comments or success stories to

# marius.reiner@hdev.de

# Thanks!

#

# The latest version of this script is available at:

# http://www.hdev.de/fancontrol/fancontrol.html

# or in the CVS version of lm_sensors

#

# For configuration instructions and warnings please see fancontrol.txt, which

# can be found in the doc/ directory or at the website mentioned above.

#

#

#    Copyright 2003 Marius Reiner <marius.reiner@hdev.de>

#

#    This program is free software; you can redistribute it and/or modify

#    it under the terms of the GNU General Public License as published by

#    the Free Software Foundation; either version 2 of the License, or

#    (at your option) any later version.

#

#    This program is distributed in the hope that it will be useful,

#    but WITHOUT ANY WARRANTY; without even the implied warranty of

#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

#    GNU General Public License for more details.

#

#    You should have received a copy of the GNU General Public License

#    along with this program; if not, write to the Free Software

#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#

#

#DEBUG=1

MAX=255

echo $$ > /var/run/fancontrol.pid

function LoadConfig {

   echo "Loading configuration from $1 ..."

   # grep configuration from file

   INTERVAL=`egrep '^INTERVAL=.*$' $1 | sed -e 's/INTERVAL=//g'`

   FCTEMPS=`egrep '^FCTEMPS=.*$' $1 | sed -e 's/FCTEMPS=//g'`

   MINTEMP=`egrep '^MINTEMP=.*$' $1 | sed -e 's/MINTEMP=//g'`

   MIDTEMP=`egrep '^MIDTEMP=.*$' $1 | sed -e 's/MIDTEMP=//g'`

   MAXTEMP=`egrep '^MAXTEMP=.*$' $1 | sed -e 's/MAXTEMP=//g'`

   MINSTART=`egrep '^MINSTART=.*$' $1 | sed -e 's/MINSTART=//g'`

   MINSTOP=`egrep '^MINSTOP=.*$' $1 | sed -e 's/MINSTOP=//g'`

   # optional settings:

   FCFANS=`egrep '^FCFANS=.*$' $1 | sed -e 's/FCFANS=//g'`

   

   # Check whether all mandatory settings are set

   if [[ -z ${INTERVAL} || -z ${FCTEMPS} || -z ${MINTEMP} || -z ${MAXTEMP} || -z ${MINSTART} || -z ${MINSTOP} ]]

   then

      echo "Some mandatory settings missing, please check your config file!"

      exit 1

   fi

   # here the other settings should be verified

   

   # write settings to arrays for easier use and print them

        echo

   echo "Common settings:"

   echo "  INTERVAL=$INTERVAL"

                  

   let fcvcount=0

   for fcv in $FCTEMPS

   do

      AFCPWM[$fcvcount]=`echo $fcv |cut -d'=' -f1`

      AFCTEMP[$fcvcount]=`echo $fcv |cut -d'=' -f2`

      AFCFAN[$fcvcount]=`echo $FCFANS |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      AFCMINTEMP[$fcvcount]=`echo $MINTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      AFCMIDTEMP[$fcvcount]=`echo $MIDTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      AFCMAXTEMP[$fcvcount]=`echo $MAXTEMP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      AFCMINSTART[$fcvcount]=`echo $MINSTART |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      AFCMINSTOP[$fcvcount]=`echo $MINSTOP |sed -e 's/ /\n/g' |egrep "${AFCPWM[$fcvcount]}" |cut -d'=' -f2`

      echo

      echo "Settings for ${AFCPWM[$fcvcount]}:"

      echo "  Depends on ${AFCTEMP[$fcvcount]}"

      echo "  Controls ${AFCFAN[$fcvcount]}"

      echo "  MINTEMP=${AFCMINTEMP[$fcvcount]}"

      echo "  MIDTEMP=${AFCMIDTEMP[$fcvcount]}"

      echo "  MAXTEMP=${AFCMAXTEMP[$fcvcount]}"

      echo "  MINSTART=${AFCMINSTART[$fcvcount]}"

      echo "  MINSTOP=${AFCMINSTOP[$fcvcount]}"

      let fcvcount=fcvcount+1

   done

   echo

}

if [ -f "$1" ]

then 

   LoadConfig $1

else

   LoadConfig /etc/fancontrol

fi

DIR=/proc/sys/dev/sensors

SDIR=/sys/bus/i2c/devices

if [ ! -d $DIR ]

then

   if [ ! -d $SDIR ]

   then

      echo $0: 'No sensors found! (did you load the necessary modules?)'

      exit 1

   else

      SYSFS=1

      DIR=$SDIR

   fi   

fi

cd $DIR

# $1 = pwm file name

function pwmdisable()

{

   if [ "$SYSFS" = "1" ]

   then

      echo $MAX > $1

      ENABLE=${1}_enable

      if [ -f $ENABLE ]

      then

         echo 0 > $ENABLE

      fi

   else

      echo $MAX 0 > $1

   fi

}

# $1 = pwm file name

function pwmenable()

{

   if [ "$SYSFS" = "1" ]

   then

      ENABLE=${1}_enable

      if [ -f $ENABLE ]

      then

         echo 1 > $ENABLE

      fi

   else

      echo $MAX 1 > $1

   fi

}

function restorefans()

{

   echo 'Aborting, restoring fans...'

   let fcvcount=0

   while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs

   do

      pwmo=${AFCPWM[$fcvcount]}

      pwmdisable $pwmo

      fcvcount=$fcvcount+1

   done

   echo 'Verify fans have returned to full speed'

   exit 1

}

trap restorefans SIGHUP SIGINT SIGQUIT SIGTERM SIGKILL

# function doing all the math

function calc () {

   awk "BEGIN { print $@ }"

}

# main function

function UpdateFanSpeeds {

   let fcvcount=0

   while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs

   do

      #hopefully shorter vars will improve readability:

      pwmo=${AFCPWM[$fcvcount]}

      tsens=${AFCTEMP[$fcvcount]}

      fan=${AFCFAN[$fcvcount]}

      mint=${AFCMINTEMP[$fcvcount]}

      midt=${AFCMIDTEMP[$fcvcount]}

      maxt=${AFCMAXTEMP[$fcvcount]}

      minsa=${AFCMINSTART[$fcvcount]}

      minso=${AFCMINSTOP[$fcvcount]}

      

      tval=`cat ${tsens}`

      if [ $? -ne 0 ]

      then

         echo "Error reading temperature from $DIR/$tsens"

         restorefans

      fi

      tval=`echo ${tval} |cut -d' ' -f3 |cut -d'.' -f1`

      if [ "$SYSFS" = "1" ]

      then

         let tval="$tval / 1000"

      fi

      pwmpval=`cat ${pwmo}`

      if [ $? -ne 0 ]

      then

         echo "Error reading PWM value from $DIR/$pwmo"

         restorefans

      fi

      pwmpval=`echo ${pwmpval} | cut -d' ' -f1`

      

      # If fanspeed-sensor output shall be used, do it

      if [[ -n ${fan} ]]

      then

         fanval=`cat ${fan}`

         if [ $? -ne 0 ]

         then

            echo "Error reading Fan value from $DIR/$fan"

            restorefans

         fi

         fanval=`echo ${fanval} | cut -d' ' -f2`

      else

         fanval=1  # set it to a non zero value, so the rest of the script still works

      fi

      

      # debug info

      if [ "$DEBUG" != "" ]

      then

         echo "pwmo=$pwmo"

         echo "tsens=$tsens"

         echo "fan=$fan"

         echo "mint=$mint"

         echo "maxt=$maxt"

         echo "minsa=$minsa"

         echo "minso=$minso"

         echo "tval=$tval"

         echo "pwmpval=$pwmpval"

         echo "fanval=$fanval"

      fi

      

      if [ $tval -le $mint -a $pwmpval -ge $minsa ]

      then

        pwmval=$minso

      elif [ $tval -ge $midt -a $pwmpval -le $minso ]

      then 

        pwmval=$minsa

      elif (( $tval >= $maxt ))

      then 

        pwmval=255

      fi

#      if (( $tval <= $mint ))

#        then pwmval=0 # at specified mintemp shut fan off

#      elif (( $tval >= $maxt ))

#        then pwmval=255 # at specified maxtemp switch to 100%

#      else 

#        # calculate the new value from temperature and settings

#        pwmval=`calc "(((${tval}-${mint})/(${maxt}-${mint}))^2*(255-${minso})+${minso})" |cut -d'.' -f1`

#        if [ $pwmpval -eq 0 -o $fanval -eq 0 ]

#        then # if fan was stopped start it using a safe value

#           echo $minsa > $pwmo

#         sleep 1

#        fi

#      fi

      echo $pwmval > $pwmo # write new value to pwm output

      if [ $? -ne 0 ]

      then

         echo "Error writing PWM value to $DIR/$pwmo"

         restorefans

      fi

      if [ "$DEBUG" != "" ]

      then

         echo "new pwmval=$pwmval"

      fi

      fcvcount=$fcvcount+1

   done

}

echo 'Enabling PWM on fans...'

let fcvcount=0

while (( $fcvcount < ${#AFCPWM[@]} )) # go through all pwm outputs

do

   pwmo=${AFCPWM[$fcvcount]}

   pwmenable $pwmo

   if [ $? -ne 0 ]

   then

      echo "Error enabling PWM on $DIR/$pwmo"

      restorefans

   fi

   fcvcount=$fcvcount+1

done

echo 'Starting automatic fan control...'

# main loop calling the main function at specified intervals

while true

do

   UpdateFanSpeeds

   sleep $INTERVAL

done

# some old stuff/missing features, will clean this up soon

#if ( test "$regulationtype" = "quad" ) ; then

#  while true ; do

#    temp=`cat ${temp1} | cut -b 12-13`

#    if (( ${temp} < ${mintemp} )) ;

#       then pwm=0

#    elif (( ${temp} > ${maxtemp} )) ;

#       then pwm=255

#    else

#   pwm=`calc "((10/(${maxtemp}-${mintemp})*(${temp}-${mintemp}))^2/1000*(${maxtemp}-${mintemp})*(255-${minspeed})+${minspeed})"`

#   #no optimization here for readability (or sloth :))

#    fi ;

#    echo $pwm > ${pwm1} ;

#

#    sleep 10 ;

#  done ;

#elif ( test "$regulationtype" = "exp" ) ; then

  #add support for exponential calculation here

#else

#  pwmconst=$[(255-${minspeed})/(${maxtemp}-${mintemp})]

#  while true ; do

#    let temp=`cat temp1 | cut -b 12-13` ;

#    if (( ${temp} < ${mintemp} )) ;

#        then pwm=0

#    elif (( ${temp} > ${maxtemp} )) ;

#        then pwm=255

#    else

#       pwm=$[(${temp}-${mintemp})*${pwmconst}+${minspeed}]

#    fi ;

#    echo $pwm > pwm2 ;

#

#    sleep 10 ;

#  done ;

#fi

```

/etc/fancontrol

```

INTERVAL=10

FCTEMPS=0-0d00/pwm2=0-0d00/temp1_input

MINTEMP=0-0d00/pwm2=40

MIDTEMP=0-0d00/pwm2=50

MAXTEMP=0-0d00/pwm2=55

MINSTART=0-0d00/pwm2=20

MINSTOP=0-0d00/pwm2=12

```

What I have done, is, I added the MIDTEMP value and replaced the speed/temp checks and changes with my own (very ugly but works for me  :Smile: ). The script adjusts as follows:

If the temp falls below MINTEMP the fan is set to MINSTOP, if it raises above MIDTEMP the fan is set to MINSTART and if it raises above MAXTEMP the fan goes to full speed. The speed the fan has in the zone between MIN- and MIDTEMP depends on what it was before. In my config that means, if the cpu temp raises above 50 the fan will speed up to MINSTART and the temp has to fall below 40 to get the fan set to MINSTOP again. This is to prevent the fan from switching constantly between MINSTART MINSTOP if the temp is switching between 40 and 41 i.e.

a setup for you would be something like this:

```

INTERVAL=10

FCTEMPS=0-0d90/pwm1=0-0d90/temp2_input

MINTEMP=0-0d90/pwm1=40

MIDTEMP=0-0d90/pwm1=50

MAXTEMP=0-0d90/pwm1=55

MINSTART=0-0d90/pwm1=15

MINSTOP=0-0d90/pwm1=0

```

I hope you can use this

----------

## nic01

Thanks mate! That was excactly what I was looking. The solution with MIDTEMP is great.

Cheers,

Nicholai

----------

