Trouble turning on temperature controlled DC fan at the correct value

Not sure if the right place to post this but…

One of my first Arduino projects, trying to create a temperature controlled dc fan.

My current setup as shown, uses a 12v(1.7w) DC fan, LM 35 temp sensor, BD139 transistor.

My code is suppose to start spinning the fan blades once the temperature measured hits 30 degrees. My fan however only turns on at 50 degrees. Before 50 degrees, the fan makes a slight whining noise at times and the blades jolt ever so slightly but only start spinning at 50 degrees.

I believe the code is correct as I’m using basically a tutorial project that was tested as working. Was advised that it might be my transistor? what would be a suitable transistor to use for a 12v dc fan?

Any help appreciated

edit: added code below

arduino-temperature-fan-speed-control-550x494.jpg

Show us your code.

If your output is simply turned high or low, the temperature makes no difference to the fan. Are you trying to run it as a variable speed fan with PWM?

Test your program by simply removing the resistor from the IO pin and plugging into 5v. If it works then, it should be ok. If not look for a logic level gate mosfet.

Weedpharma

Have you got a Serial.print going on so that you can see the output from the LM35? The usual problem with these is that they're very prone to interference. You'll have a lovely signal in a quiet environment, but as soon as that fan starts, the reading from the LM35 will appear spurious.

The simplest way to work around the problem is to have a function that makes many readings then returns the average.

Dammit skipped my mind to post the code

Ignore the LCD parts as I haven’t done that stage as yet

#include <LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2);
int tempPin = A1;  
int fan = 11;      
int led = 8;        
int temp;
int tempMin = 30;   // the temperature to start the fan
int tempMax = 70;   // the maximum temperature when fan is at 100%
int fanSpeed;
int fanLCD;

void setup()
  {
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(tempPin, INPUT);
  lcd.begin(16,2);  
}

void loop() {  
   temp = readTemp();     
   if(temp < tempMin) 
   { 
       fanSpeed = 0;     
       digitalWrite(fan, LOW);       
   } 
   if((temp >= tempMin) && (temp <= tempMax))
  {  
       fanSpeed = map(temp, tempMin, tempMax, 32, 255);
       fanLCD = map(temp, tempMin, tempMax, 0, 100);  
       analogWrite(fan, fanSpeed);
   } 
   
   if(temp > tempMax)
   {     
     digitalWrite(led, HIGH);  
   } else {                  
     digitalWrite(led, LOW); 
   }
   
   lcd.print("TEMP: ");
   lcd.print(temp);      
   lcd.print("C ");
   lcd.setCursor(0,1);
   lcd.print("FANS: ");
   lcd.print(fanLCD);    
   lcd.print("%");
   delay(200);
   lcd.clear();   
}

int readTemp() {  //convert to degrees celcius
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}

Basically the fan starts of at 0% power and I’m trying to increase the power/speed of a fan based on the temperature measured.

Using a serial display on screen, it shows that when the temperature increases from 30 degrees to 50 degrees, the fan is shown to be turned on and increasing in power, but it actually only ‘turns on’ at 50 degrees when its showing like 30% power.

Give this a try

#include <LiquidCrystal.h>
LiquidCrystal lcd(7,6,5,4,3,2);
int tempPin = A1;  
int fan = 11;      
int led = 8;        
int temp;
int tempMin = 30;   // the temperature to start the fan
int tempMax = 70;   // the maximum temperature when fan is at 100%
int fanSpeed;
int fanLCD;

void setup()
  {
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(tempPin, INPUT);
  lcd.begin(16,2);  
}

void loop() {  
   temp = readTemp();     
   if(temp < tempMin) 
   { 
       fanSpeed = 0;     
       digitalWrite(fan, LOW);       
   } 
   if((temp >= tempMin) && (temp <= tempMax))
  {  
       fanSpeed = map(temp, tempMin, tempMax, 32, 255);
       fanLCD = map(temp, tempMin, tempMax, 0, 100);  
       analogWrite(fan, fanSpeed);
   } 
   
   if(temp > tempMax)
   {     
     digitalWrite(led, HIGH);  
   } else {                  
     digitalWrite(led, LOW); 
   }
   
   lcd.print("TEMP: ");
   lcd.print(temp);      
   lcd.print("C ");
   lcd.setCursor(0,1);
   lcd.print("FANS: ");
   lcd.print(fanLCD);    
   lcd.print("%");
   delay(200);
   lcd.clear();   
}

int readTemp() {  //convert to degrees celcius
  unsigned int totalTemp=0;
  for(int n=0;n<32;n++)
    totalTemp += analogRead(tempPin);  
    temp=totalTemp/32;
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}

Your problem may be that you are outputting an analogue voltage at low temperature. The fan needs a certain voltage to start spinning. A true analogue voltage output of half the voltage on a 12v fan is about 6v and that may not be enough to move the blades.

PWM which switches full 12v at a variable on/off timing should get it moving as it actually receives 12v for a short time each pulse.

Weedpharma

@KenF Thanks, currently out but will try that out soon

@Weedpharma Perhaps using a fan of a lower rating, a 5v dc fan?

And could you explain what you mean by:
“PWM which switches full 12v at a variable on/off timing should get it moving as it actually receives 12v for a short time each pulse.”
So is there a different way to implement PWM in my code?

Thanks again

Hi, what is the fan you are powering, can you post a picture of it please. If it is a brushless fan, you cannot control them with PWM, they have thier own drive circuit in them. That is why some brushless fans have 4 wires, 2 for supply, one for tacho output, and one for speed control voltage input.

Tom...... :)

I’m using the one attached. It has 2 wires.

I believe the the PWM control is working though. Once the fan eventually starts spinning at 50 degrees, If I increase or decrease the temperature, the fan speed seems to increase or decrease appropriately, and even when the temperature drops below 50 degrees, the fan will continue spinning at a slower speed and then increase again when the temperature is increased.

Its just the initial starting of the fan at the correct temperature of 30 degrees instead of 50 degrees that’s got me stumped.

@KenF Tried it out but it didn’t seem to solve the problem, there was no change :disappointed_relieved:

Sunon_Fans-EE80251S1-000U-A99-image.jpg

In that case you need to push up the value in your map function (as you're obviously not supplying enough power at low temperatures)

so replace

fanSpeed = map(temp, tempMin, tempMax, 32, 255);

with

fanSpeed = map(temp, tempMin, tempMax, 144, 255);

That seemed to have worked! How did you find the value 144?

The only issue here is that I don't really get that 'range' of fan speed. When it blows at the minimum 30 degrees it's almost as powerful as when its blowing at maximum 70 degrees.

I'm going to try and get hold of a lower voltage fan and give it a try cause it clearly was the 12v fan not getting enough power.

Thanks again though!

Imo92: That seemed to have worked! How did you find the value 144?

According to the code you'd posted, you were mapping a value between 30 (tempMin) and 70 (tempMax) to be a value between 32 and 255. 50 degrees is exactly midway between your min and max value. Which means the mapped value would be midway between 32 and 255. 144 is close enough.

The only issue here is that I don't really get that 'range' of fan speed. When it blows at the minimum 30 degrees it's almost as powerful as when its blowing at maximum 70 degrees.

Try reducing that 144 a bit then :)

To get the fan started from the stopped condition you could set it to half (or more) power (analogWrite(127)) for a short time to get the blades spinning and then set the speed you need. Once the fan is spinning it will go to a lower speed but I suspect the blades will stall before you get to analogWrite(0)

JohnLincoln: ... the problem might be due to the capacitor you have connected to the base of the transistor.

Using PWM to control a motor, you want the transistor to be able to digitally switch the power to the motor at the PWM frequency. By including the capacitor you are putting the transistor into a linear mode.

This is where I my thoughts were. What is the purpose of the capacitor in your circuit?

Imo92: @KenF Thanks, currently out but will try that out soon

@Weedpharma Perhaps using a fan of a lower rating, a 5v dc fan?

And could you explain what you mean by: "PWM which switches full 12v at a variable on/off timing should get it moving as it actually receives 12v for a short time each pulse." So is there a different way to implement PWM in my code?

Thanks again

Pure PWM switches the voltage on and off at varying rates to give an average of a lower voltage but still applying the full voltage for the period of each pulse. This is like opening and closing the supply switch quickly.

Your circuit has a capacitor in the base. This will charge a little each pulse. If the pulse is short the charge voltage will be low until it has received sufficient pulses to reach the voltage required to turn on the transistor. It is a high value C so will take a while to charge and may also have a self discharge (internal resistance).

At a higher pulse rate it will keep the voltage on the base at a level sufficient to turn on the transistor and keep it on.

Simply remove the C to use PWM.

Weedpharma

If you loose the capacitor (as suggested), you’ll have much better response and range for controlling the speed of your fan.

In a minimal sketch, you could predetermine the minimum value for “fanSpeed” that gets the fan blades turning (or the minimum speed you want to start the fan at). For example, to get the blades turning, it might be 13 (5%).

Full speed will occur when “fanSpeed” = 255 (100%).

Now you’ll have your appropriate values for the map function in your sketch.

Hi, please read post #8

The only issue here is that I don't really get that 'range' of fan speed. When it blows at the minimum 30 degrees it's almost as powerful as when its blowing at maximum 70 degrees.

The fan is a brushless type, the internal drive circuitry is designed to run the fan at a constant speed, over a range of loads. The minute that there is sufficient voltage to run the drive circuit it starts the fan rotating, but at the speed the circuit is designed to do. Varying supply only will not give you any decent variation in fan speed.

That is why they have 3 and 4 wire brushless fan assemblies, for feedback and external control when it is needed.

Tom....... :)

Tom, I agree partly.

Even if it is not brushless, the fact that the transistor is likely to be fully on or fully off due to the capacitor being either charged enough to bias the transistor on, or not (except for a small range).

When biased on, it will run close to full speed.

Weedpharma

As said earlier I'm basing this project of a tutorial I found, and to be honest was not 100% sure of the workings behind it, so as said by the author himself :

I had a few problems with the PWM part mainly because the fan made a disturbing noise so I had to add a simple RC filter at the output of the PWM pin on the Arduino board.

That was all that that was said on those components.

From my own testing, when I removed the capacitor, the fan did not start at all until the temperature hit the max 70 degrees(so, 12v?). The fan immediately switched off if the temp dropped below 70 degrees. It also made a whining noise from the start temp of 30 till 70 where it then turned on.

@Tom 144 actually was the exact amount to turn it on at initially at 30 degrees.

If you put the capacitor back as your original circuit (to keep noise levels low), then try this. I’ve added a 1/2 sec fan startup that only runs once as the temp increases to 30+ deg. Temp must previously be below 30 deg for startup to run once again.

If the fan stalls out at 30 deg, then increase the “32” in your map function to a level that keeps it running. It should be much less than the “144” setting found earlier.

#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
int tempPin = A1;
int fan = 11;
int led = 8;
int temp;
int tempPrevious;
int tempMin = 30;   // the temperature to start the fan
int tempMax = 70;   // the maximum temperature when fan is at 100%
int fanSpeed;
int fanLCD;

void setup()
{
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(tempPin, INPUT);
  lcd.begin(16, 2);
}

void loop() {
  temp = readTemp();
  if (temp < tempMin)
  {
    fanSpeed = 0;
    digitalWrite(fan, LOW);
  }

  if ((temp >= tempMin) && (tempPrevious < tempMin));
  {
    analogWrite(fan, 255); // startup fan
    delay (500);
    analogWrite(fan, fanSpeed); // continue at fanSpeed
  }
  tempPrevious = temp;

  if ((temp >= tempMin) && (temp <= tempMax))
  {
    fanSpeed = map(temp, tempMin, tempMax, 32, 255);
    fanLCD = map(temp, tempMin, tempMax, 0, 100);
    analogWrite(fan, fanSpeed);
  }

  if (temp > tempMax)
  {
    digitalWrite(led, HIGH);
  } else {
    digitalWrite(led, LOW);
  }

  lcd.print("TEMP: ");
  lcd.print(temp);
  lcd.print("C ");
  lcd.setCursor(0, 1);
  lcd.print("FANS: ");
  lcd.print(fanLCD);
  lcd.print("%");
  delay(200);
  lcd.clear();
}

int readTemp() {  //convert to degrees celcius
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}