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.