Temperature depending PWM fan

This started out as just wanting to play around with a 4 pin fan with build-in PWM.

All in one

This first example got almost everything inside the same function, only thing outside it is the initial call to it to start it repeating itself over and over.

function fanUpdatePWM()
{
  local pwmMax = 1.0;   //Max PWM cycle
  local pwmMin = 0.1;  //Min PWM cycle

  local tempMin = 20.0; //Min temperature (below this it will run at pwmMin)
  local tempMax = 45.0; //Max temperature (above this it will run at pwmMax)

  local tempAct = getTemp(); //Set the current temperature that will determine the fan speed

  local pwmVal = (tempAct - tempMin) * (pwmMax - pwmMin) / (tempMax - tempMin); //Calculate pwm cycle
  if (pwmVal < pwmMin) pwmVal = pwmMin; //If the pwm cycle is below minimum, set it to minimum
  if (pwmVal > pwmMax) pwmVal = pwmMax; //If the pwm cycle is above maximum, set it to maximum

  hardware.pin7.configure(PWM_OUT, 1.0/23000.0, pwmVal); //Setting pin7 to putput with pwm at 23000hz to not be able to hear it (average human hearing range is 20 to 20000 hz)

  server.log("Temperature: " + tempAct + "c - Fan PWM: " + pwmVal); //Output temperature and pwm
  imp.wakeup(5, fanUpdatePWM); //Do this again 5 seconds
}
fanUpdatePWM(); //Initial start of the function

But as you can see, this got a bit bigger than first expected. With this function you can set a minimum temperature, and a maximum temperature. This is the range within the PWM cycle will be calculated. So tempMin = pwmMin, and tempMax = pwmMax. You most likely want to play around with these to get a pwm cycle that will keep the temperature as stable as possible and as close to your desired target temperature as possible.

In this function I use the getTemp(); function I posted some time ago, but it can easily be changed to something else that just returns a number.

If everything is going as expected, it should output something like this in the Log window.

2013-12-22 11:36:49 UTC+1: [Device] Temperature: 22.4832c - Fan PWM: 0.374719
2013-12-22 11:36:54 UTC+1: [Device] Temperature: 22.7539c - Fan PWM: 0.379231
2013-12-22 11:36:59 UTC+1: [Device] Temperature: 22.7627c - Fan PWM: 0.379379
2013-12-22 11:37:04 UTC+1: [Device] Temperature: 22.9268c - Fan PWM: 0.382113

The better way

Even when the first function works just fine, and pretty much does what you want, it still sets the output pin over and over. Every time it sets the pin the fan makes a tiny noise while the pin is set. This noise is only a few milliseconds, but it is possible to get rid of it. Here is how…

function fanUpdatePWM()
{
  local pwmMax = 1.0;   //Max PWM cycle
  local pwmMin = 0.05;  //Min PWM cycle
  
  local tempMin = 20.0; //Min temperature (below this it will run at pwmMin)
  local tempMax = 45.0; //Max temperature (above this it will run at pwmMax)
  
  local tempAct = getTemp(); //Set the current temperature that will determine the fan speed
  
  local pwmVal = (tempAct - tempMin) * (pwmMax - pwmMin) / (tempMax - tempMin); //Calculate pwm cycle
  if (pwmVal < pwmMin) pwmVal = pwmMin; //If the pwm cycle is below minimum, set it to minimum
  if (pwmVal > pwmMax) pwmVal = pwmMax; //If the pwm cycle is above maximum, set it to maximum

  hardware.pin7.write(pwmVal); //Write the PWM cycle to the pin
  server.log("Temperature: " + tempAct + "c - Fan PWM: " + pwmVal); //Output temperature and pwm
  imp.wakeup(5, fanUpdatePWM); //Do this again 5 seconds
}
hardware.pin7.configure(PWM_OUT, 1.0/23000.0, 1.0); //Setting pin7 to putput with pwm at 23000hz to not be able to hear it (average human hearing range is 20 to 20000 hz)
fanUpdatePWM(); //Initial start of the function

With this the output pin is set when the micro controller starts, and afterwards the new PWM value is only written to the pin.

Leave a Reply