Designing a fan controller

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
Problem:
When I’m running computer intensive tasks, I want the fans to cool my processor. When I’m not, I want the fans to be quiet. I know that fan controllers exist that you can buy, but I wanted to learn more about control systems, so I decided to design one myself.

Context:
I’m starting from a project I did a while ago where I used ductwork to route air through my PC. 5” diameter dryer duct hose connects the front and back fans (Silverstone FM121 - http://www.silverstonetek.com/product.php?pid=118&area=usa) to the heat-sink (CoolerMaster Hyper 212+ http://www.coolermaster.com/product.php?product_id=3096) that is mounted on the processor.




Solution:
Essentially, a PLC (I chose the Arduino Uno http://arduino.cc/en/Main/ArduinoBoardUno, because it is cheap and easy to program) will read the temperature, generate an output based on a comparison between the temperature and the set-point, and translate that output into the appropriate fan speed. I read the temperature in two stages: 1) to get from the PLC’s voltage input to the thermistor’s resistance, I used a voltage divider circuit and 2) to get from the thermistor’s resistance to the temperature, I used the Steinhart-Hart equation. I used a PID algorithm to generate an output based on a comparison between the set-point and the temperature. I used PWM to translate the algorithm’s output into the appropriate fan speed.








Results:
  • When doing tasks that are not processor-intensive, the computer runs at 39 dB instead of 57 dB as measured by the Sound Meter app on my phone when my phone is on my desk.
  • While the primary purpose of the project was reducing sound, I was curious to see if it also resulted in power savings. It turned out not to change power usage much. I estimate that the computer will use about 8 less kW-h per year (the PC uses 72 W @ 100% fan speed and 58 W @ 40% fan speed as measured by the kill-a-watt meter that I plugged my computer into. Assuming 3 hours of use per day split evenly between computer intensive and computer un-intenstive tasks, 72 W - 58 W = 14 W; 14 W * 1.5 hr / day * 365 days / yr * 1 kW / 1000 W = about 8 kW-h per year). At $0.15 per kW-h my utility bills me, I will save a whopping $1.20 per year. In testing so far, the computer has used an average of 0.38 kW-h per day without the controller and 0.37 kW-h per day with the controller. 0.01 kW-h / day * 365 days / year = about 4 kW-h per year.

Here are a couple of questions I would like your input on:
  • Where can I put the sensor such that running the CPU exhaust fan doesn’t interfere with it?
  • What tunings should I use for gs for my PID algorithm? (I've seen a couple of strategies by googling around, but I wonder what your experience suggests).
  • How can I add a tolerance to the set-point? For example, the controller currently adjusts the fan speed if the temperature is 22.07 degrees C, when I would be fine with anything in the 21-23 degrees C range.
  • How should I change the wire colors to make the circuit easier to read?

---
www.jeffsinventions.com
 

SugarFree

Junior Member
Mar 11, 2012
5
0
0
I like your project and I have a question, where can I purchase these silver pipe that you use for air flow in the picture above? Can I purchase it online? If yes, which webside?
 

Subyman

Moderator <br> VC&G Forum
Mar 18, 2005
7,876
32
86
I like your project and I have a question, where can I purchase these silver pipe that you use for air flow in the picture above? Can I purchase it online? If yes, which webside?

Those are just drier vents. You can get them at Home Depot/Menards/Lowes for practically nothing.
 

Charlie98

Diamond Member
Nov 6, 2011
6,292
62
91
Actually, I considered sort of the same thing... ducting the CPU fans to the rear case vent (I have a 212+ with twin fans.)

One thing I will mention... if you look at your photos, you will notice a fairly large gap between the fan and the heat exchanger... if you put your hand over it you can feel much of the air blowing out of it... or, rather, bypassing the heat exchanger... defeating the purpose of it somewhat. I have the same problem...

HAF922004-1.jpg


My thought was to create some sort of rubber boot to fit over the gaps (or over the entire heat exchanger) to increase efficiency.

Just a thought.
 

T_Yamamoto

Lifer
Jul 6, 2011
15,007
795
126
Actually, I considered sort of the same thing... ducting the CPU fans to the rear case vent (I have a 212+ with twin fans.)

One thing I will mention... if you look at your photos, you will notice a fairly large gap between the fan and the heat exchanger... if you put your hand over it you can feel much of the air blowing out of it... or, rather, bypassing the heat exchanger... defeating the purpose of it somewhat. I have the same problem...

HAF922004-1.jpg


My thought was to create some sort of rubber boot to fit over the gaps (or over the entire heat exchanger) to increase efficiency.

Just a thought.
maybe some ducttape?
 

Charlie98

Diamond Member
Nov 6, 2011
6,292
62
91
RAM will not fit, right?

maybe some ducttape?

You would have to use a low-profile RAM with my mobo and the 212... not an issue with just the 2 sticks.

DUCT TAPE? D:D:D: Surely you jest? But, yes, as a test bed I plan on trying it unless I can find a suitable material to wrap around the gap (maybe a sliced up bicycle innertube... flexable yet impervious to heat and conductivity.)
 

T_Yamamoto

Lifer
Jul 6, 2011
15,007
795
126
You would have to use a low-profile RAM with my mobo and the 212... not an issue with just the 2 sticks.

DUCT TAPE? D:D:D: Surely you jest? But, yes, as a test bed I plan on trying it unless I can find a suitable material to wrap around the gap (maybe a sliced up bicycle innertube... flexable yet impervious to heat and conductivity.)
fine, cardboard
 

GoStumpy

Golden Member
Sep 14, 2011
1,211
11
81
obviously they're kidding, there is only one PROPER solution:

Foil Tape:

AF9732.jpg


:biggrin:
 

PCTC2

Diamond Member
Feb 18, 2007
3,892
33
91
Isn't 4" duct only 101mm? I could've sworn that 4" meant diameter for dryer ducts.

Now to the OP,
Looking at your circuit diagram, I see you show the PWM with it's own dedicated ground. The third pin isn't ground for PWM, it's actually the RPM sensing pin. The 4th pin is PWM input. They all share a common ground. I would say you should isolate your Arduino from the fans completely, but that adds another whole level of complexity. You could always just do a bunch of conditionals for ranges of temperatures mapped to different RPM ranges.
 
Last edited:

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
Isn't 4" duct only 101mm? I could've sworn that 4" meant diameter for dryer ducts.

Now to the OP,
Looking at your circuit diagram, I see you show the PWM with it's own dedicated ground. The third pin isn't ground for PWM, it's actually the RPM sensing pin. The 4th pin is PWM input. They all share a common ground. I would say you should isolate your Arduino from the fans completely, but that adds another whole level of complexity. You could always just do a bunch of conditionals for ranges of temperatures mapped to different RPM ranges.

The FM 121 is unusual in that it has, in effect, five pins: two pins for power (12V DC), one pin for tachometer, and two pins--a positive and a ground--for fan control.
 

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
The next few posts have more details about the project.

Reading the temperature
To read the temperature, I have to choose a sensor, figure out where to put it, and pass its reading to the plc.


Which sensor should I use?
I opted for a 10K NTC thermistor (TE-701-D-12-A http://mamacsys.com/TE-701-702ordering_information.htm). I tried an RTD initially, but it took too long (5-10 minutes) between when the temperature changed and the resistance changed. I my sensor, measuring the 19,000 ohms predicted at 10.5 degrees C by the spec sheet (http://mamacsys.com/pdf/Sensortype12C.pdf).


Where should I put the sensor?
I opted to put the probe where I thought I would, between the CPU exhaust fan and the case exhaust fan. One of my concerns was that air would escape through the hole where the probe was installed. The bulkhead seal was a good one—I didn’t feel air escaping when I put my finger on it when the fans were running. The other concern was that it would block airflow too much. It didn’t seem to be a big problem.

One outstanding problem with the current placement is that when I power the cpu exhaust fan, which is right in front of the thermistor, the thermistor readings jump all over the place. My current solution is not powering that fan. However, I would be interested if you can think of another way around this.


How will I pass the information from the sensor to the plc?
This is done in two steps: 1) getting from the PLC’s input voltage to the resistance of the thermistor, then 2) getting from the resistance of the thermistor to the temperature it is measuring.


1) How can I get from the 0-5V PLC analog input to the resistance of the thermistor?
I chose to pull this off with a voltage divider circuit (http://en.wikipedia.org/wiki/Voltage_divider). Basically, if you have two resistors in series (R1 is closer to the voltage source and R2 is closer to ground) and measure the voltage between ground and the voltage source (Vin) and the voltage between ground and a point between the two resistors (Vout), then Vout/Vin = R2/(R1+R2). Solving for R1,

(R1+R2)/Vin = R2/Vout

R1+R2 = R2*Vin/Vout

R1 = -R2 + R2*Vin/Vout


So, what are R1, R2, Vin, and Vout in this case?

R1 = resistance of thermistor

R2 = resistance of an arbitrary resistor (I choose a 1K)

Vin = 5V generated by the PLC

Vout = PLC input voltage


This is the circuit in the below picture, in the bottom half of the breadboard.



Plugged into the equation above:

Thermistor resistance = -1000 ohm + 1000 ohm *5 V/PLC input voltage


The tricky thing about the PLC input voltage is that it converts the 0-5V reading into a value from 1-1024 (e.g., 2.5 V = 512). Put another way, PLC input voltage = 5 V * reading/ 1024

So, the equation becomes:

Thermistor resistance

= -1000 ohm + (1000 ohm *5 V * 1024) / (5 V * reading)

= -1000 ohm + 1000 ohm * 1024 / reading


2) How can I get from the resistance of the thermistor to the temperature it is measuring?

One of the things that makes thermistors a pain to use is that their resistance does not vary linearly with temperature. Instead, the relationship is given by the Steinhart-Hart equation (http://en.wikipedia.org/wiki/Steinhart–Hart_equation):

Thermistor temperature = 1.0 / [A + B * log (thermistor resistance) + C * (log(thermistor resistance))^3 ]

To figure out the A, B, and C coefficients for my thermistor, I plugged in three resistance-temperature points (12493 ohm, 20 C; 6530 ohm, 35 C; 3601 ohm, 50 C) from the thermistor’s datasheet (http://mamacsys.com/pdf/Sensortype12C.pdf) into a Steinhart-Hart coefficient calculator (http://www.thinksrs.com/support/Therm Calc/NTCCalibrator/NTCcalculator.htm). I chose the three I did, because they are in the temperature range that I expect to see in my computer. The calculator spit out these coefficients: A: 1.128527013e^-3; B: 2.342316349e^-4; C: 0.8721921627e^-7.

So, for my thermistor, thermistor temperature

= 1.0 / [1.128527013e^-3 + 2.342316349e^-4 * log (thermistor resistance) + 0.8721921627e^-7 * (log(thermistor resistance))^3 ]

Entering thermistor resistance as a function of voltage calculated above,

Thermistor temperature = 1.0 / [1.128527013e^-3 + 2.342316349e^-4 * log (-1000 ohm + 1000 ohm * 1024 / reading) + 0.8721921627e^-7 * (log(-1000 ohm + 1000 ohm * 1024 / reading))^3 ]

Luckily for me, instead of having to code this monstrous equation, someone has already done it: http://disipio.wordpress.com/2009/07/17/temperature-measurement-using-arduino-and-a-thermistor/. I just enter R1, A, B, and C, and it does all of the leg-work.
 

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
Comparing the set-point and temperature reading to calculate fan speed
What should the set-point be?
To figure out the set-point, I wanted to understand the limits of the temperatures the sensor would read. It would be at its coldest if there were 0% CPU load and 100% fan speed. It would be at its hottest if it were 100% PC load with 40% fan speed (40% is the minimum speed besides “off”). In both cases, the intake air was 20 C (this is where my landlord tends to leave the thermostat). Taking this approach, I found that the range of thermistor temperatures was 20.6 C to 25.4 C. I wanted to let the PLC back off the fans at idle and make sure they were going full blast at load. A 22 C set-point strikes this balance.


Which algorithm will I choose?
I opted for a PID algorithm, an algorithm that calculates an output based on the difference between the temperature and the set-point (P – for proportionate), the rate that the temperature is moving towards or away from the set point (D – for differential), and the sum of the differences between the temperature and the set-point over the past couple measurements (I – for integral). You can adjust the degree that each of these factors is weighted to have the controller behave differently. My concern with using this approach was that it was going to be a hassle to program. Fortunately, there is a PID library for Arduino (http://arduino.cc/playground/Code/PIDLibrary). All you have to do is enter the input, the set-point, and the weightings for the P, I, and D components, and it will kick out an output.


The library defaults to weightings of 2 * P, 5 * I, and 1 * D. I haven’t started fiddling around with these, but have seen in my preliminary googling that there is a whole science associated with “PID tuning.” If anyone has advice about how to approach this it would be appreciated. The main problem with the current weightings is that it takes a long time after the temperature reading changes for the fan speed to change


Here is an example of the algorithm at work. I let the computer idle for the first 10 minutes. I then applied a 25-35% CPU load by playing a video for the following 50 minutes. My concern with the current tuning is that it takes too long between a change in temperature and a change in fan speed. For example, it isn’t until the six minute mark that the algorithm finds out that the 40% fan speed is the solution to cooling an idle CPU to the set-point.



---
www.jeffsinventions.com
 

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
Translating that output into the appropriate fan speed
If the PID algorithm has determined the rate the fan should run, the puzzle then becomes how to convert that digital representation of the fan speed into the fan actually spinning at the rate I want it to. There are basically two approaches for doing this&#8212;adjusting the fan voltage and controlling the fan speed using PWM. The voltage route involves reducing the voltage applied to the fan in a way that corresponds to the reduction in fan speed that you want to see. For example, if you want a 12V fan to run at 50%, give it 6V. The other approach is to use PWM. Instead of varying the voltage applied to the fan, you vary the frequency you send the full voltage to it. If you want a fan to run at 50%, send signals that are that are 12V half the time and 0V for the other half. The trick is to keep each signal short enough that you can&#8217;t hear the fan switching on and off [while humans can hear signals in the 20-20,000 cycles per second range (http://en.wikipedia.org/wiki/Hearing_range), the standard for 4 pin PC fans is 21,000-25,000 cycles per second (formfactors.org/developer%5Cspecs%5CREV1_2_Public.pdf)]

PWM was the easiest to implement, because the Arduino PID library is designed to generate a PWM signal (the PID library outputs a number from 0-255 (0 is 0% and 255 is 100%), and the Arduino function for generating a PWM signal, AnalogWrite, is also 0-255). Given that it was easiest and has no glaring downside I decided to go with it.

---
www.jeffsinventions.com
 
Last edited:

JeffsInventions

Junior Member
Mar 11, 2012
7
0
0
www.jeffsinventions.com
Code

#include <math.h>


double A = 1.128527013e-3;
double B = 2.342316349e-4;
double C = 0.8721921627e-7;
// double K = 9.5; // mW/dec C &#8211; dissipation factor

double SteinhartHart(double R)


{
// calculate temperature
double logR = log(R);
double logR3 = logR * logR * logR;
return 1.0 / (A + B * logR + C * logR3 );
}


#include <PID_v1.h>
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
int fanPin = 3;

void setup() {
Serial.begin(9600);
Input = 20;
Output = 125;
Setpoint = 20;
myPID.SetMode(AUTOMATIC);
pinMode(fanPin,OUTPUT);
}


#define READING_PIN 0
double R1 = 1004.0; //resistance put in parallel
double V_IN = 5;

void loop() {
//read voltage
double adc_raw = analogRead(READING_PIN);
// Serial.println(adc_raw);
double V = V_IN - (adc_raw / 1024 * V_IN);
// Serial.print("V = ");
// Serial.print(V);

//calculate resistance
double R_th = (R1 * V) / (V_IN - V);
// double R_th = 3600;
// Serial.print("V R_th = ");
// Serial.print(R_th);

//calculate temperature
double kelvin = SteinhartHart(R_th);
double celsius = kelvin - 273.15;
// Serial.print("Ohm T = ");
Serial.print("T = ");
Serial.print(celsius);

//calculate fan speed
Input = celsius;
myPID.Compute();
analogWrite(fanPin,Output);
Serial.print("C Fan speed = ");
Serial.print(40 + (60 - (Output / 255 * 60))); // the minimum fan speed is 40%
Serial.print("%\n");

delay(1000);
}

---
www.jeffsinventions.com