PWM+fan problem (or something else?)

Hello!
I have a problem with my project when using PWM signals.
I need to maintain a system around 30ºC, with a maximum temperature of 40ºC. No matter I use function ‘map’ or the way it is shown below, the fan does not start spinning until 32ºC (about 25% of speed) instead of 30.01ºC, as it should be. (Don’t care about the G and so, it is because an amplification stage for the sensor)

Please, I have tried so many things and nothing works.

Here is the sketch too:

int tempPin = A0; //Asigna el pin A0 al sensor LM35
int G=10; //Define la variable entera ‘Ganancia’
int fan = 9; //Asigna el pin 9 al ventilador
float temp; //Define la variable no entera ‘Temperatura’
float tempMax = 40; //Límite superior de temperatura
float desired_temp = 30; //Temperatura óptima
//Define la variable no entera ‘Velocidad del ventilador’
float fanSpeed;

void setup() {
pinMode(tempPin, INPUT); //Define al pin A0 como entrada
pinMode(fan, OUTPUT); //Define al pin 9 como salida
}

void loop(){
//Lee el valor del pin A0
temp=analogRead(tempPin);
//Convierte la lectura del pin a temperatura (ºCelsius)
temp=((5*temp/1023)/(G))*100;

if(temp>=desired_temp && temp<=tempMax){
fanSpeed=((temp-desired_temp)*255/(tempMax-desired_temp));
analogWrite(fan, fanSpeed);
}
}

temp.ino (910 Bytes)

Print out the temperature to serial - are you getting the right value?
Print out the fanSpeed - are you getting the right value?

The fan may not start spinning until the duty cycle passes a certain threshold, in which case you can adjust for that in software - what kind of fan is it?

I’m going to guess the problem is that the fan won’t start-up with low PWM values. Try a simple program that directly writes various PWM values to find the minimum PWM required to start the fan, and the minimum PWM required to keep it running once it starts.

In general, “infinite” fan speed control can be tricky because there is a time-lag. You can get into a weird oscillation where the fan is “hunting” for the correct speed. Heating & cooling systems usually just turn on and off when needed without trying to set the exact amount of heating/cooling required. So for example, turn the fan on when the temperature hit’s 30, and off when it goes below 30. (Most real-world systems also have hysteresis, so you might turn the fan on when the temp hits 30.5 and shut it off when the temp hits 29.5, etc.)

So I’d start with a simple on/off system, then maybe change it to 2-speeds. Then if you want, experiment with more speeds or PWM.

float fanSpeed;

PWM requires a byte. I’m not sure what happens if you feed it a float, but make sure it’s constrained to values between 0 and 255. If you go over 255, the lower 8 bytes will “wrap”. i.e. 256 would give you a PWM value of zero and 257 would give you PWM of 1.

if(temp>=desired_temp && temp<=tempMax){

What happens if the temperature is above maximum? :wink:

Before we get into what your problem is prove to us that your temp measurement is correct. Print out the values to your serial monitor (after conversion) and compare them to some reference (your thermostat reading on the wall ?) or a digital room thermometer. At 25 degrees C you should read about 127.5 counts on the analog raw data without any manipulation. Is that what you have ? Have you made any attempt to calibrate your readings (through comparison to a reference ) ?

Post a schematic