Intercooler Fan control

Hi all im a bit stumped with some code im working on to control a fan that i have installed on the inter-cooler of my vehicle. I'm using the screen to display other information as well.

But for the purpose of this question I'm concentrating on the fan control part.

As it stands the code compiles and works with the screen. Yay......

The part that im not sure if i have right is lines 89 - 92. What i need is for the fan to turn on at mindiffTemp which is the temperature above ambient that the inter-cooler has reached due to engine load etc, and continue to increase fan speed to 100% which is defined by maxdiffTemp. The whole thing is floating which i why i can just say turn the fan on at 30degC. The point to the whole exercise is to control the fan so its not running the whole time. And because a inter-cooler cant cool below ambient temperature and that varies all the time i need the fan to come on at different temperatures.

Clear as mud right haha

Thanks for any help.

John.

fan_controller_OLED.ino.ino (3.3 KB)

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html
then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

But before that, do a TOOLS, AUTO-FORMAT.
I will indent you sketch to make it easier to read for and if functions.

Thanks .. Tom.. :slight_smile:

// Vehicle Information System.
// Version 5.0.
// JTechNZ Engineering and Tech Soultions.

#include <max6675.h>
#include <SeeedOLED.h>
#include <Wire.h>

int intertempPin = A1; // Inter-cooler outlet Temperature. LM35 Sensor
int atPin = A2; // Ambient Air Temperature. LM35 Sensor
int intertemp;
int AT;
int egt;
int fan = 11; // Fan PWM Output.
int led = 8; // Red EGT status LED.
int led1 = 9; // Green EGT Status LED.
int fanSpeed;
int fanOLED;
int egttempMax = 500; // Max EGT temp.
int mindiffTemp = 3; // Min temp above ambient to start fan.
int maxdiffTemp = 40; // Max temp above ambient for fan to be at 100%.

// MAX6675 Pin outs
int thermo_gnd_pin = 45;
int thermo_vcc_pin = 47;
int thermo_so_pin  = 49;
int thermo_cs_pin  = 51;
int thermo_sck_pin = 53;

MAX6675 thermocouple(thermo_sck_pin, thermo_cs_pin, thermo_so_pin); // EGT Probe.

void setup()
{
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(intertempPin, INPUT);
  pinMode(atPin, INPUT);
  pinMode(thermo_vcc_pin, OUTPUT);
  pinMode(thermo_gnd_pin, OUTPUT);
  digitalWrite(thermo_vcc_pin, HIGH);
  digitalWrite(thermo_gnd_pin, LOW);

  Wire.begin();
  SeeedOled.init(); //initialze SEEED OLED display.
  SeeedOled.clearDisplay(); //clear the screen and set start position to top left corner.
  SeeedOled.setNormalDisplay(); //Set display to Normal mode.
  SeeedOled.setPageMode(); // Set addressing mode to Page Mode.
  SeeedOled.setBrightness(255);
  SeeedOled.setTextXY(0, 0);
  SeeedOled.putString("InterC Temp:");
  SeeedOled.setTextXY(2, 0);
  SeeedOled.putString("Intake Temp:");
  SeeedOled.setTextXY(4, 0);
  SeeedOled.putString("FanSpeed:");
  SeeedOled.setTextXY(6, 0);
  SeeedOled.putString("EGT Temp:");
}

void loop() {
  intertemp = readTemp(); // Read Inter-cooler Temperature.
  AT = readTemp1(); // Read Ambient Air Temperature.
  egt = thermocouple.readCelsius(); // Read the Exhaust Gas Temperature (EGT).

  if (intertemp < AT) // If Intercooler is less than Ambient air temperature Stop FAN.
    fanSpeed = 0;
  digitalWrite(fan, LOW);

  SeeedOled.setTextXY(0, 12);
  SeeedOled.putNumber(intertemp);
  SeeedOled.setTextXY(2, 12);
  SeeedOled.putNumber(AT);
  SeeedOled.setTextXY(4, 12);
  SeeedOled.putNumber(fanOLED);
  SeeedOled.setTextXY(6, 12);
  SeeedOled.putNumber(egt);
  delay(1000);

  if (egt > egttempMax) { // if EGT temperature is higher that temp max turn on red LED.
    digitalWrite(led, HIGH);  // turn on Red LED.
  } else {
    digitalWrite(led, LOW); // turn off red LED.
  }
  if (egt <= egttempMax) { // If EGT temp is below egttempMax Light Green LED.
    digitalWrite(led1, HIGH);
  } else {
    digitalWrite(led1, LOW);
  }
  if ((intertemp >= AT + mindiffTemp) && (intertemp <= AT + maxdiffTemp)) { // If intercooler is above ambient temperature PLUS mindiffTemp spin fan.
    fanSpeed = map(intertemp, AT + mindiffTemp, AT + maxdiffTemp, 30, 255); // the actual speed of fan.
    fanOLED = map(intertemp, AT + mindiffTemp, AT + maxdiffTemp, 0, 100);  // speed of fan to display on OLED.
    analogWrite(fan, fanSpeed);  // spin the fan at the fanSpeed speed.
  }
}

int readTemp() {  // get the temperature and convert it to celsius.
  intertemp = analogRead(intertempPin);
  return intertemp * 0.48828125;
}
int readTemp1() {
  AT = analogRead(atPin);
  return AT * 0.48828125;
}

I have written a little simulation sketch of the AT, intertemp, and fan speed values. I can see there is something wrong with either the logic or the boundaries on the map function, but the fan is coming full on when the intertemp is cooler than AT +mindiffTemp. That doesn't seem right. I have added a additional conditional to address this.

int intertemp;
int AT;
int fanSpeed;
int mindiffTemp = 3; // Min temp above ambient to start fan.
int maxdiffTemp = 40; // Max temp above ambient for fan to be at 100%.

void setup() {

  Serial.begin(9600);
  Serial.println();
  Serial.println("AT\tIC\tFAN");

  for (AT = 0; AT <= 55;  AT += 5)
  {
    for (intertemp = 0; intertemp <= 100; intertemp += 5)
    {
      if ((intertemp >= AT + mindiffTemp) && (intertemp <= AT + maxdiffTemp)) // If intercooler is above ambient temperature PLUS mindiffTemp spin fan.
      {
        fanSpeed = map(intertemp, AT + mindiffTemp, AT + maxdiffTemp, 30, 255); // the actual speed of fan.
      }

      //ADD THIS CONTROL SECTION
      /*
         if ((AT + mindiffTemp) >= intertemp)
           {
             fanSpeed = 0;
           }
      */

      Serial.print(AT);
      Serial.print('\t');
      Serial.print(intertemp);
      Serial.print('\t');
      Serial.println(fanSpeed);
    }
    Serial.println();
  }
}

void loop() {
}

Hi Tom, sorry about that brain was a bit tired when i wrote this post.

I have had some success i spoke with a work colleague today who has a degree in computer engineering it turns out i needed some more brackets to separate some of the parameters.

This is what it looks like now and appears to be working. Im having allot of trouble getting the LM35 sensors to read without massive error. But I have ordered some digital temp probes that i hope will provide more stable results over the long distances between the probes and the controller. Im using a Mega 2560 and the new digital sensors will be DS18B20.

// Vehicle Information System.
// Version 5.0.
// JTechNZ Engineering and Tech Soultions.

#include <max6675.h>
#include <SeeedOLED.h>
#include <Wire.h>

int intertempPin = A1; // Inter-cooler outlet Temperature. LM35 Sensor
int atPin = A2; // Ambient Air Temperature. LM35 Sensor
int intertemp;
int AT;
int egt;
int fan = 11; // Fan PWM Output.
int led = 8; // Red EGT status LED.
int led1 = 9; // Green EGT Status LED.
int fanSpeed;
int fanOLED;
int egttempMax = 500; // Max EGT temp.
int mindiffTemp = 5; // Min temp above ambient to start fan.
int maxdiffTemp = 70; // Max temp above ambient for fan to be at 100%.

// MAX6675 Pin outs
int thermo_gnd_pin = 45;
int thermo_vcc_pin = 47;
int thermo_so_pin  = 49;
int thermo_cs_pin  = 51;
int thermo_sck_pin = 53;

MAX6675 thermocouple(thermo_sck_pin, thermo_cs_pin, thermo_so_pin); // EGT Probe.

void setup()
{
  pinMode(fan, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(intertempPin, INPUT);
  pinMode(atPin, INPUT);
  pinMode(thermo_vcc_pin, OUTPUT);
  pinMode(thermo_gnd_pin, OUTPUT);
  digitalWrite(thermo_vcc_pin, HIGH);
  digitalWrite(thermo_gnd_pin, LOW);

  Wire.begin();
  SeeedOled.init(); //initialze SEEED OLED display.
  SeeedOled.clearDisplay(); //clear the screen and set start position to top left corner.
  SeeedOled.setNormalDisplay(); //Set display to Normal mode.
  SeeedOled.setPageMode(); // Set addressing mode to Page Mode.
  SeeedOled.setBrightness(255);
  SeeedOled.setTextXY(0, 0);
  SeeedOled.putString("InterC Temp:");
  SeeedOled.setTextXY(2, 0);
  SeeedOled.putString("Intake Temp:");
  SeeedOled.setTextXY(4, 0);
  SeeedOled.putString("FanSpeed:");
  SeeedOled.setTextXY(6, 0);
  SeeedOled.putString("EGT Temp:");
}

void loop() {
  readTemp(); // Read Inter-cooler Temperature.
  readTemp1(); // Read Ambient Air Temperature.
  egt = thermocouple.readCelsius(); // Read the Exhaust Gas Temperature (EGT).


  SeeedOled.setTextXY(0, 12);
  SeeedOled.putNumber(intertemp);
  SeeedOled.setTextXY(2, 12);
  SeeedOled.putNumber(AT);
  SeeedOled.setTextXY(4, 12);
  SeeedOled.putNumber(fanOLED);
  SeeedOled.setTextXY(6, 12);
  SeeedOled.putNumber(egt);
  delay(500);

  if (egt > egttempMax) { // if EGT temperature is higher that temp max turn on red LED.
    digitalWrite(led, HIGH);  // turn on Red LED.
  } else {
    digitalWrite(led, LOW); // turn off red LED.
  }
  if (egt <= egttempMax) { // If EGT temp is below egttempMax Light Green LED.
    digitalWrite(led1, HIGH);
  } else {
    digitalWrite(led1, LOW);
  }
  if (intertemp < (AT + mindiffTemp)) { // If Intercooler is less than Ambient air temperature Stop FAN.
    fanSpeed = 0;
    digitalWrite(fan, LOW);
  }
  else if ((intertemp >= (AT + mindiffTemp)) && (intertemp <= (AT + maxdiffTemp))) { // If intercooler is above ambient temperature PLUS mindiffTemp spin fan.
    fanSpeed = map(intertemp, AT + mindiffTemp, AT + maxdiffTemp, 15, 255); // the actual speed of fan.
    fanOLED = map(intertemp, AT + mindiffTemp, AT + maxdiffTemp, 0, 100);  // speed of fan to display on OLED.
    analogWrite(fan, fanSpeed);  // spin the fan at the fanSpeed speed.
  }
  else if (intertemp > (AT + maxdiffTemp)) {
    analogWrite(fan, 255);
  }
}

void readTemp() {  // get the temperature and convert it to celsius.
  intertemp = analogRead(intertempPin) * 0.48828125;
}
void readTemp1() {
  AT = analogRead(atPin) * 0.48828125;

}

[/code]

Im having allot of trouble getting the LM35 sensors to read without massive error

Look at this : Arduino Playground - HomePage
However,I didn't the above method

I wrote this sketch feew days ago and it works without huge errors, or say, no errors.

/*Thermometer using LM35 and Arduino
 *
 * Reads voltege generated by the LM35 precision temperature sensor
 * and converts it to a temperature value in *c
 *
 * Connections:
 *  LM35       Arduino
 * Pin 1        +5v
 * Pin 2        A0
 * Pin 3        GND
 *
 * modified 8-APR-2016
 * by Malhar Deshmukh
 */
float tem;
// the setup function runs once when you press reset or power the board
void setup()
{
  Serial.begin(9600);
}
// the loop function runs over and over again
// forever and keeps reading the temperature
void loop()
{
  tem = analogRead(A0) * 0.418; //read voltage and convert it to temperature in *C
  Serial.println(tem);//Print the temperature to serial monitor
  delay(100); //Delay for stability
}