12V DC Fan Controlled by LM35

Hi all,

First of all, I would like to apologise if this is posted in the wrong place. I have been reading these forums to try and get my fan circuit working but no luck.

I want to control a DC fan with an LM35 and an Arduino Uno. The LM35 sensor is going to be mounted to an LED heatsink and I would like to keep the temperature at a set point.

So I have been following this guide to building the circuit that I need: arduino-fan-speed-controlled-temperature

I have tried the circuit with two fans and had no luck. The fan that I am currently using is: 12V DC Fan

I have attached my circuit schematic, the code that I have used is as follows:

int tempPin = A0;   // the output pin of LM35
int fan = 13;       // the pin where fan is
int led = 8;        // led pin
int temp;
int tempMin = 20;   // the temperature to start the fan
int tempMax = 50;   // the maximum temperature when fan is at 100%
int fanSpeed;
 
void setup() {
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(tempPin, INPUT);
  analogReference(INTERNAL);
  Serial.begin(9600);
}
 
void loop() {  
   temp = readTemp();     // get the temperature
   if(temp < tempMin) {   // if temp is lower than minimum temp
       fanSpeed = 0;      // fan is not spinning
       digitalWrite(fan, LOW);       
   } 
   if((temp >= tempMin) && (temp <= tempMax)) {  // if temperature is higher than minimum temp
       fanSpeed = map(temp, tempMin, tempMax, 100, 255); // the actual speed of fan
       analogWrite(fan, fanSpeed);  // spin the fan at the fanSpeed speed
   } 
   
   Serial.print("TEMP = ");
   Serial.print(temp);
   Serial.println("DEG C");
     
   delay(500);
}
 
int readTemp() {  // get the temperature and convert it to celsius
  temp = analogRead(tempPin);
  return temp * 0.107421875; 
  
}

When I power the circuit on the fan is not spinning. Once the temperature goes above the minimum temperature set the fan goes to 100% output, it appears to have no modulation.

The temperature sensor is working correctly and displays the correct value in the Serial Monitor.

Any guidance would be very much appreciated.

Thanks

Hi, the problem will probably be due to the fan being a brushless type, which does not like pwm control.

Tom...... :slight_smile:

Ah ok thank you! Could you please suggest a fan that would be suitable?

I previously tried this fan with no luck: Gelid Fan

I have ordered the 4-pin PWM fan in the link below:

70mmx15mm 12V 4 Pins PWM PC

Can I connect the PWM signal cable to the PWM pin and the +/- pins to +/- 12V DC?

I see that the fan has a relatively high start up voltage of 7V. Could I set the minimum value in the map function to the equivilent value? In my mind that would be (255/12V)*7V

You are using the analogReference(INTERNAL) which is a 1.1V MAX range. The LM335 outputs 10 mV/deg C. You are then multiplying THAT value by 0.107421875. (which you later use for the MAP function).
If the temp were 100 dec C, (for example) the LM35 would return 1V which you then multiply by 0.107421875 which would give you 0.107 for the MAP function. I have no idea why you are using the
INTERNAL analog reference than cannot accept a value greater than 1.1V but IMO you should be using
the DEFAULT reference.

Thanks for the response.

From background reading 1.1V reference gives a more accurate reading (if you ingnore the 0.5 deg tolerance of the LM35).

Are you saying that the 1.1V reference will stop the code working?

I want to control a DC fan with an LM35 and an Arduino Uno.

int fan = 13;       // the pin where fan is

On the UNO, pin 13 is not a PWM pin. The PWM pins on the UNO are 3,5,6,9,10,11.

I'm saying you CANNOT read ANY voltage GREATER than 1.1V from the LM35 using INTERNAL analog reference.

cattledog:

int fan = 13;       // the pin where fan is

On the UNO, pin 13 is not a PWM pin. The PWM pins on the UNO are 3,5,6,9,10,11.
analogWrite() - Arduino Reference

You were correct! Thank you so much!

raschemmel:
I'm saying you CANNOT read ANY voltage GREATER than 1.1V from the LM35 using INTERNAL analog reference.

So with my LM35 connected to 5V DC I am missing a lot of range or reducing the resolution by using 1.1V as a reference? Should I be feeding a clean 1.1V DC to the AREF pin?

Do the math. The LM35 output 10mV /per deg C . You are using an UNO. The DEFAULT analog reference is
5V. WHY are you NOT using the DEFAULT analog reference ? I don't understand why you are doing what you are doing. Change the analog reference to DEFAULT. But BEFORE you do that , MEASURE the voltage or at
LEAST post the values you are receiving for the INTERNAL analog reference.

From background reading 1.1V reference gives a more accurate reading (if you ingnore the 0.5 deg tolerance of the LM35).

Do the math

Temp = 110 deg C. * 0.01 V = 1.1V (the MAXIMUM input voltage when using INTERNAL reference).

My point ? If the thing you are measuring will NEVER exceed 110 deg C, then it is perfectly fine to use the
INTERNAL analog reference. Show me in your previous posts where you told us the MAXIMUM temperature you would need to measure . Consequently, I have no idea if your UUT will exceed 110 degrees.

The LM35 sensor is going to be mounted to an LED heatsink and I would like to keep the temperature at a set point.

I have no idea how hot that led can get.
Of course you could use a voltage divider but that's kind of lame when you can just change the analog reference. When you tell us what the maximum temp will be we can decide if what you are doing is appropriate. So far , I haven't seen it. If you have known all along it would never exceed 110 deg and just neglected to mention it, then I would say you should have mentioned that is why you are using INTERNAL reference.

Sorry for not mentioning that previously, the LED won't exceed 80 deg C so 1.1V is ok as the reference voltage.

If I were you I would just get rid of all the IF statement conditional stuff and simply :

 fanSpeed = (temp * 5);

and forget the min/max stuff. The result is the same. For a temp of 20 deg C, the fanspeed =100
For a temp of 50 deg C the fanspeed = 250. That' close enough and at least it's better than what you have now. Keep it simple. I don't know why your code doesn't work but that's what I would do with my limited programming experience.