Variable Fan speed with Variable temperature settings

Hello all

I've tried a few times searching for ways and help in this small project i'm doing just to get use to the whole programming of the arduino (Uno R3 in my case) right now i have used the sketch from electroschematics.com as my base line and have modified it a little to have a Low Temp LED along with a High temp LED.

At this time i felt to see if i can change the tempmax to be a variable number based on a Potentionmeter (10K) that's hooked up to the UNO's Ground and 5Volt and into A1, then remapped the signal from that to a 28 - 40 range. and got it to enter into the tempmax value?

The problem seems to be that the program seems to compile correctly, uploads correctly, but when it's running the values for Temp seem to change around when i turn the Pot and also the tempmax seems to vary up and down too. basically nothing is stable?

// include the library
#include <LiquidCrystal.h>

// Pin Orientation

int tempPin = A0;   // the output pin of LM35
int tempset = A1;   // Input of Variable Resistor
int fan = 10;       // the pin where fan is (TIP122)
int Highled = 12;   // High temp LED pin
int Lowled = 11;    // Low temp LED pin
int tempMin = 24;   // the temperature to start the fan
int tempMax = 0;   // the maximum temperature when fan is at 100%
int tempset2;
int fanSpeed;
int fanLCD;
int temp;

LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins

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

void loop()  {

    temp = readTemp();    // get the temperature
    tempMax = getmax();   //Get Max 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, 0, 255); // the actual speed of fan
      fanLCD = map(temp, tempMin, tempMax, 0, 100);  // speed of fan to display on LCD
      analogWrite(fan, fanSpeed);  // spin the fan at the fanSpeed speed
    }

    if (temp > tempMax) {      // if temp is higher than tempMax
      digitalWrite(Highled, HIGH);  // turn on led
      analogWrite(fan, 255);
      fanLCD = 100;
    } else {                    // else turn off led
      digitalWrite(Highled, LOW);
    }

    if (temp < tempMin) {        // if temp is lower then tempMin
      digitalWrite(Lowled, HIGH); //turn on led
    } else {
      digitalWrite(Lowled, LOW); //turn off led
    }

    lcd.print("TEMP: ");
    lcd.print(temp);      // display the temperature
    lcd.print("C");
    lcd.print(" Min:");
    lcd.print(tempMin);   // Display Min set temperature
    lcd.setCursor(0, 1);  // move cursor to next line
    lcd.print("FAN: ");
    lcd.print(fanLCD);    // display the fan speed
    lcd.print("%");
    lcd.print(" Max:");
    lcd.print(tempMax);   // Display Max set temperature
    delay(1000);
    lcd.clear();
  }

  int readTemp() {  // get the temperature and convert it to celsius
    temp = analogRead(tempPin);
    return temp * 0.48828125;
  }
  int getmax(){ // Get to the Max setting and converted to temperature range
   tempset2 = analogRead (tempset);
   return tempMax = map(tempset2, 0, 1023, 28, 40);
  }

hopefully someone can point me in the ways of my errors on implementing this adjustment, so i can see what it'll take to change the tempmin setting aswhile (which then i want to see about have tempMax's range start @5-10 degrees higher then what tempmin is at)

and thank you for your time,
Kevin

Is your 5V power supply voltage stable? Measure it with a multimeter or stick an LED (with resistor) on the 5 Volts to see if the LED flickers when the fan starts to turn-on.

I'd try disconnecting the fan (disconnect everything from pin 10) to see if things stabilize. The fan could be dragging-down the power supply or generating noise on the power supply which will mess-up the analog voltage reference.

I assume you've got current-limiting resistors on your LEDs? If the pot is mis-wired, that could also cause problems. (You may need to show us your schematic.)

At first-glance your code looks OK, but I didn't carefully analyze it.

The way to develop code is to write a little code at a time and test & debug it before adding more. That way when a problem crops-up you know it's from the code you just added. i.e. Start with a little program that just treads the pot or reads the temperature sensor, and proceed from there.

...This isn't you current issue, but a continuously variable temperature control fan can be tricky. It may tend to "hunt", continuously speeding-up and slowing-down. Most heating/cooling systems simply cycle on & off with some hysteresis. (i.e, The fan might turn-on at 31 degrees and stay on 'till you get down to 29 degrees, or something like that.) I'd start with something like that first, or maybe try 2-speeds. When that all works, try continuously-variable speed if you want.

Still Haven't figured it out since my last post like 20 minutes ago,

But have noticed that the Max Temp is now reasonably solid in where it's set, but the Temperature input (A0) side of things is bouncing from say 22 degree upwards to 47 degrees!!

and when i disconnect the pot from A1 the Temp input becomes stable, still bounces between 26-28 degrees with the Max locked at 29 degrees.

With the Variable set point part removed from the sketch temp is at a solid 27 degree's.

thank you again

DVDdoug:
Is your 5V power supply voltage stable? Measure it with a multimeter or stick an LED (with resistor) on the 5 Volts to see if the LED flickers when the fan starts to turn-on.

I'd try disconnecting the fan (disconnect everything from pin 10) to see if things stabilize. The fan could be dragging-down the power supply or generating noise on the power supply which will mess-up the analog voltage reference.

I assume you've got current-limiting resistors on your LEDs? If the pot is mis-wired, that could also cause problems. (You may need to show us your schematic.)

At first-glance your code looks OK, but I didn't carefully analyze it.

The way to develop code is to write a little code at a time and test & debug it before adding more. That way when a problem crops-up you know it's from the code you just added. i.e. Start with a little program that just treads the pot or reads the temperature sensor, and proceed from there.

...This isn't you current issue, but a continuously variable temperature control fan can be tricky. It may tend to "hunt", continuously speeding-up and slowing-down. Most heating/cooling systems simply cycle on & off with some hysteresis. (i.e, The fan might turn-on at 31 degrees and stay on 'till you get down to 29 degrees, or something like that.) I'd start with something like that first, or maybe try 2-speeds. When that all works, try continuously-variable speed if you want.

The Fan in question is a PC 80mm fan running on it's own 12volt supply and using a TIP122 transistor to power it via the arduino's D10 pin. (also have a Cap and diode in the circuit too) and before trying the variable adjustment part of the programming it was VERY stable

the two LEDs have 330ohm resistor on them, Well i would think that even for me mis-wiring the Pot would be nearly impossible but it can be so? I have wiper going to A1 of the Arduino, one outside leg to the 5volt rail of my breadboard (shared with the display and LM35 temp sensor) and the other leg to the Negative rail shared by the same items PLUS the LEDs

Yep and that's how i basically started off, got going with just showing the temperature on the display, then added PWM fan control with help from the above linked site, then added on the two LEDs to show cold and hot basically, ran it like that for almost a week off and on. i am learning and believe in learning in small steps (usually best for me in the long run)

yah some hysteresis would be nice in this project, i've build analog devices before to control coolant pumps before using a LM311 and the like, but that was a on/off device, which would be easy to program into an arduino i would think (haven't tried it) but i'm trying to do PWM fan control, at this time.

Thank you for your thoughts Doug

Kevin

I also tried to build a project which includes temperature sensor LM35, but getting problem, Then I switch to this sensor DHT11. Look at This Temperature Fan controller, looking promising:

Also let me know whether you come up with any solution with LM35
Thanks

Newton1:
I also tried to build a project which includes temperature sensor LM35, but getting problem, Then I switch to this sensor DHT11. Look at This Temperature Fan controller, looking promising:

Also let me know whether you come up with any solution with LM35
Thanks

Well as a simple temperature reader even turning on and off items the LM35 works fine for me. the problem i have is when i try to set the temperature (tempMax) by the way of a variable resistor that things seem to go funny..

Just a small update;

Using serial.print for debugging purposes i have found a couple of thing.

  1. the signal from the Pot is rock solid.
  2. Temperature is somewhat solid (typically now only bounces 1 degree)
  3. The Signal from the LM35 swings by 50mv? (goes from @50-110 at times) (but has no effect of the calculated temp now?) and adjusting the Pot effects it's reading?

If i comment out the parts that deal with the pot and variable temperature settings, and even leaving the Pot and wiring in places. Signal from the LM35 is steady, and everything seems to work as is should.

One can say it's the pot but if that's still in the circuit when it's been removed from the program side, shouldn't it still have an effect?

I also found it kinda weird that when i first started this thread to now, that the how thing seems to be a bit more stable without wild swings in calculated temperature, LEDs flashing all over and fan doing some funky things to being reasonably solid. but still not right..

Thank you

Maybe you could adapt/clip this LM35 code I wrote.
It is stable at 0.05C because of 1.1volt Aref and smoothing.
Use "total/numReadings" if you only want to work with the raw value.
Leo..

// TMP35 temp sensor connected to Analogue input A1, 3.3volt and ground
// or LM35 temp sensor connected to A1, 5volt and ground
// temp range ~2C to ~105C
// display on serial monitor and/or LCD
// for a TMP36 (-40C to ~55C), change line 45 to:   tempC = total * Aref * 0.1 / numReadings - 50.0;
//
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // your LCD pins could be different
byte ledPin = 10; // backlight pin
const byte numReadings = 25; // number of readings for smoothing (max 64)
int readings[numReadings]; // readings from the analog input
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
int inputPin = A1; // the pin that the TMP35 is connected to
float Aref = 1.0759; // change this value to the actual Aref voltage of ---YOUR--- Arduino (1.0 - 1.2), or adjust to get accurate readings
float tempC; // Celcius
float tempF; // Fahrenheit

void setup() {
  //analogWrite(ledPin, 200); // optional dimming
  analogReference(INTERNAL); // use the internal ~1.1volt reference | change (INTERNAL) to (INTERNAL1V1) for a Mega
  Serial.begin(115200); // ---set serial monitor to this value---
  lcd.begin(16, 2); // shield with 2x16 characters
  lcd.print("Thermometer"); // info text
  lcd.setCursor(0, 1); // second row
  lcd.print("0-100 Celcius");
  for (index = 0; index < numReadings; index++) { // fill the array for faster startup
    readings[index] = analogRead(inputPin);
    total = total + readings[index];
  }
  index = 0; // reset
  delay(2000); // info display time
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(inputPin); // one unused reading to clear ghost charge
  readings[index] = analogRead(inputPin); // read from the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to temp
  tempC = total * Aref * 0.1 / numReadings; // value to celcius conversion
  tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit conversion

  // print to LCD
  if (total == 1023 * numReadings) { // if overflow
    lcd.clear();
    lcd.print("---TOO HOT---");
  }
  else {
    lcd.clear();
    lcd.print(tempC, 2); // two decimal places
    lcd.setCursor(6, 0); // position 6, first row
    lcd.print("Celcius");
    lcd.setCursor(0, 1); // second row
    lcd.print(tempF, 1); // one decimal place
    lcd.setCursor(6, 1); // position 6, second row
    lcd.print("Fahrenheit");
  }

  // print to serial monitor
  Serial.print("Raw average = ");
  Serial.print(total / numReadings);
  if (total == 1023 * numReadings) {
    Serial.println("  ----too hot----");
  }
  else {
    Serial.print("   The temperature is  ");
    Serial.print(tempC, 2);
    Serial.print(" Celcius  ");
    Serial.print(tempF, 1);
    Serial.println(" Fahrenheit");
  }

  delay(1000); // use a non-blocking delay when combined with other code
}

Thank you for all that have helped so far.. Now i've decided to move onto the second stage hopefully someone can figure out this one.

some changes i've made are i'm now running a 7805 off the 12 volt power supply for the Fan to supply 5V power to the Pots, LCD display and LM35 temp sender

i have two 1K pots (thought they were 10K) in the circuit Pot1 is to set the Minimum turn on point, Pot2 set the range between Min and Max points.

The problem that now has come up is that the first half of the pots movement nothing seems to happen, then suddenly we have change and it can go from say 21 to 30 instantly

So anyone have a answer to why the pots don't do anything in the lower half, even thou the ADC is saying there is a change?

Seems like more things i add to my little project the more issues i run into?

Current Code as of now.

// include the library
#include <LiquidCrystal.h>

int tempPin = A0;   // Input: The output pin of LM35
int tempset = A1;   // Input: tempMin set point input
int temprange = A2; // Input: Range between Min and Max settings
int fan = 10;       // Output: The pin where fan is
int Highled = 12;   // Output: High temp LED pin
int Lowled = 11;    // Output: Low temp LED pin
int temp;           // Variable: Calculated temperature in Celsius
int set;            // Variable: Calculated tempMin set point
int range;          // Variable: Calculated Range between Min and Max
int tempMin = 24;   // Variable: the temperature to start the fan
int tempMax = 34;   // Variable: the maximum temperature when fan is at 100%
int fanSpeed;       // Output Variable: Speed to set fan to
int fanLCD;         // Output Variable: percentage of fan speed to be displayed on LCD
int sensorValue = 0;  // Temperature sensor raw data

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup() {
  pinMode(fan, OUTPUT);
  pinMode(Highled, OUTPUT);
  pinMode(Lowled, OUTPUT);
  pinMode(tempPin, INPUT);
  pinMode(tempset, OUTPUT);
  pinMode(temprange, OUTPUT);
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop() {
  temp = readTemp();        // get the temperature
  tempMin = readset();     // Get Minium Set point
  tempMax = readrange();   // Get Max Set point
  sensorValue=analogRead(tempPin); // Display LM35 Value onto Serial only
  
  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, 0, 255); // the actual speed of fan
    fanLCD = map(temp, tempMin, tempMax, 0, 100);  // speed of fan to display on LCD
    analogWrite(fan, fanSpeed);  // spin the fan at the fanSpeed speed
  }

  if (temp > tempMax) {      // if temp is higher than tempMax
    digitalWrite(Highled, HIGH);  // turn on led
    analogWrite(fan, 255);
    fanLCD = 100;
  } else {                    // else turn off led
    digitalWrite(Highled, LOW);
  }

  if (temp < tempMin) {        // if temp is lower then tempMin
    digitalWrite(Lowled, HIGH); //turn on led
  } else {
    digitalWrite(Lowled, LOW); //turn off led
  }

  lcd.print("TEMP: ");
    lcd.print(temp);      // display the temperature
    lcd.print("C");
    lcd.setCursor(10, 0);
    lcd.print("Min:");
    lcd.print(tempMin);   // Display Min set temperature
    lcd.setCursor(0, 1);  // move cursor to next line
    lcd.print("FAN : ");
    lcd.print(fanLCD);    // display the fan speed
    lcd.print("%");
    lcd.setCursor(10, 1);
    lcd.print("Max:");
    lcd.print(tempMax);   // Display Max set temperature
    Serial.print("lM35 value: ");
    Serial.print(sensorValue);
    Serial.print("\t");
    Serial.print("Calculated Temp: ");
    Serial.print(temp);
    Serial.print("\t");
    Serial.print("Set Temp:");
    Serial.print(tempMin);
    Serial.print("\t");
    Serial.print("Max Temp Value: ");
    Serial.println(tempMax);
    delay(1000);
 lcd.clear();
}

int readTemp() {  // get the temperature and convert it to celsius
  temp = analogRead(tempPin);
  return temp * 0.48828125;
}

int readset() {// Get Minium Set point
  set = analogRead(tempset);
  return tempMin = map(set, 0, 1023, 15, 30);
}
   
int readrange(){ // Get Max Set point
  range = analogRead(temprange);
  range = map(range, 0, 1023, 5, 15);
  return tempMax = tempMin + range;
}

Thank you to anyone that like look at it, also give comments on how to streamline it?

Kevin

91XR7:
i'm now running a 7805 off the 12 volt power supply for the Fan to supply 5V power to the Pots, LCD display and LM35 temp sender

Why.
Arduino's 5volt is perfectly able to do that.
Default Aref is probably the cause of your instable readings, and that one still hangs on Arduino's 5volt rail.

Also some danger for the pot input pin there.
When the Arduino is off, and the pot is on full (and powered), it could damage the Arduino pin.

91XR7:
The problem that now has come up is that the first half of the pots movement nothing seems to happen, then suddenly we have change and it can go from say 21 to 30 instantly

Could be a log pot. They usually have an "A" printed on them (audio taper).
Only lineair pots (B) have a lineair increase in value.
Leo..

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.... :slight_smile:

Wawa:
Why.
Arduino's 5volt is perfectly able to do that.
Default Aref is probably the cause of your instable readings, and that one still hangs on Arduino's 5volt rail.

Well I just went with an external 5 volt source just in case the Arduino wasn’t able to handle the power requirements of running the LCD, 2 pots and the Sensor. But it did not change a thing other then add more items to my breadboard so i may be removing it the next time i play with it.

Wawa:
Also some danger for the pot input pin there.
When the Arduino is off, and the pot is on full (and powered), it could damage the Arduino pin.
Could be a log pot. They usually have an "A" printed on them (audio taper).
Only lineair pots (B) have a lineair increase in value.

Thank you for the warning about the input pin, the 7805 was only added in the last playing and that was done with the 12volt power supply was off, But usually when the USB cord isn’t attached to my computer for Watching parameters I have it hooked up to my Iphone wall charger(Apple product not 3rd party) and into a power power that the 12volt supply is hooked up and use the power bars power switch to turn on both at the same time.

I’ll have to see what the numbers (if anything) is on my Pots but yah Linear they are not, even watching the ADC value you can see the first half of the Pot range it slowly goes from 0-@150, then the other half it goes up to 1023!

Would you suggest I’ll go out and get a couple linear pots to use/play with? And should I go for 5k ones? Most circuits I have played with usually use either 5 or 10K pots.

10k lin. is probably the most universal one.
It only draws 0.5mA from a 5volt rail.
Leo..

TomGeorge:
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Hey what’s wrong if a Fritzing diagram?? (ducks) Other than that, it will have to be a Hand drawn schematic/diagram, which would probably be wrong as while since I’m more use to automotive wiring diagrams. And that maybe, as a stated above, a while before I get it done. But it won’t be a standard type of schematic/diagram

Hi,
Hand drawn will be fine and a picture of your project.
Is it assemble on protoboard?
If so are you aware some of the boards have a break in the red/blue/black power tracks down the sides of the boards?

Tom... :slight_smile:
A properly drawn fritzy schematic with the proper component symbols is okayyyy.

Protoboards.jpg

Protoboards1.jpg

TomGeorge:
Hi,
Hand drawn will be fine and a picture of your project.
Is it assemble on protoboard?
If so are you aware some of the boards have a break in the red/blue/black power tracks down the sides of the boards?

Tom... :slight_smile:
A properly drawn fritzy schematic with the proper component symbols is okayyyy.

Hello Tom.

The Protoboard, as you call it, doesn't have any breaks in the power "rails" as i call them It's this piece

Also i tried my hand at drawing a minor schematic, but i took out the LCD display which uses the same ground and 5 Volts from the Arduino and the LEDs, which makes it out to be very simple! Also attached is a Fritzing "breadboard" design just for fun and more components?

Wawa:
10k lin. is probably the most universal one.
It only draws 0.5mA from a 5volt rail.
Leo..

Well now the Pots i had where 1K Linear pots!, So that bring into a question of what was happening where i only was able to get a a 0-@200 range for the first half of the travel then from 200-1023 the other half? Some to be looking into i guess.

But i do have some Linear 10K pots thou now

I know my last post was less then 24 hours ago, and it now seems like I'm talking to myself.

Just and update to all those who care.

I decided to start over from scratch started, Program and breadboard. Started off with just having the TM35 and the two B10K pots on the board, wired them to the 5Volt and ground rails of the breadboard (which are powered by the Uno) then wrote a simple code to send the values to the serial monitor. Noticed that the value of the LM35 was bouncing around, no idea why, but decided to put a small 1uF Capacitor on the output of the sensor and that seemed to smooth out it's signal to acceptable levels. Hoping that's gonna be okay.

Right now I'm only back up to displaying the converted values onto the LCD display and been using a LED on the PWM output of the Uno. Next step is to setup the 12Volt supply side for the Fan control and finish off one more piece of the program and see what happens.

May see about putting back in the Low and High temp LEDs, but they where items i just left in from earlier in this adventure of Arduino programming :slight_smile:

Thanks to all those who have been reading and helping