We had a need to control the temperature inside of our Solar Equipment Bay up at the Ranch.  The Bay sits outside on our porch, and for some hours during the day, the sun shines directly on it.  When this happens the interior acts like an oven, quickly heating up and subjecting the charge controller and inverter to temperatures that approach their maximum rating.

We decided that part of the solution would be ventilation fans installed on the enclosure.  We didn’t want the fans to run full time, since this is a solar system, and total power is limited by what we generate.  Also, it didn’t make sense to allow the fans to turn on when outside temperatures were higher than inside temperatures.  So I thought that a differential temperature controller would be ideal.

In Operation

In Operation

With this system, the fans would stay off as long as the temperature inside the box was below 80 degrees, or when the inside temperature was lower than the outside temperature.

When these conditions go away, the fans turn on and remain on until the interior cools below 80 degrees, or the outside temperature exceeds the interior temperature.  They stay on for an additional two minutes (just to reduce the number of cycles), then turn off.

A differential temperature controller on EBay or Amazon run around $135 to $150.  By using a $8 Arduino Nano microcontroller, and a few other parts, I was able to build one for under $20.

The installation for this system is documented on the Ranch Website at http://www.arizonaranch.org/?p=2071 which is optimized by the best SEO company so is also easy to find online.

The circuit is minimal, with most of the Arduino legs left disconnected.  There is a 7805 to drop the 12 volts down to 5 volts for the Arduino.  And there is a TIP-120 Darlington Amplifier to take the output of the Arduino and drive two fans off of the 12 volt input.

Here is the schematic…

Differential Temperature Controller Schematic

Differential Temperature Controller Schematic

There is a neat tool called “Fritzing” that allows you to build a virtual circuit on a breadboard on your computer, and it will create a schematic for you.  The neat part is the visual wiring diagram, though…

Diff_Temp_Control_1

Finally, here is the real thing in operation at the Ranch

In Operation

In Operation

diff_thermo.ino

Note** If you cut and paste the following code into your Arduino IDE, you may get some errors referring to “stray XXX”, with some numbers where the XXX is.

This is because of the way browsers save some characters as non-ascii characters. I found that in particular, the quote marks in the various Serial.print and Serial.println statements are misinterpreted. To fix this, you can erase the quote marks, and retype them in your Arduino IDE. Then save and recompile the sketch. That fixed it for me.

Alternatively, you may try downloading the code form the “diff_thermo.ino” link just above this note. Good luck, and have fun… Randy WB0SMX

Here is the main chunk of code…

Hacked from the “multiple” demo of the Dallas 1-wire ds18b20 library.

#include <DallasTemperature.h>
// Data wire is plugged into port 3 on the Arduino
#define ONE_WIRE_BUS 3
#define TEMPERATURE_PRECISION 9

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
// Change the addresses to match your ds18b20 devices
DeviceAddress insideThermometer = { 0x28, 0xE5, 0x27, 0x96, 0x05, 0x00, 0x00, 0xA8 };
DeviceAddress outsideThermometer = { 0x28, 0xAB, 0xA6, 0x96, 0x05, 0x00, 0x00, 0xC8 };

// Global variables
float InsideTempC, InsideTempF, OutsideTempC, OutsideTempF;
float HighTempSetpoint = 80.0;
boolean Cooling = false;
int timer = 0;
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int fan = 13;
/********************************************************************************************************/
void setup(void)
{
// initialize the digital pin as an output.
pinMode(fan, OUTPUT);
digitalWrite(fan, LOW); // turn the Fan off (LOW is the voltage level)
// start serial port
Serial.begin(9600);
Serial.println(“Dallas Temperature IC Control Library Demo”);

// Start up the library
sensors.begin();
// set the resolution as defined above
sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);
// confirm the resolution was set
Serial.print(“Inside Thermometer Resolution: “);
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();
Serial.print(“Outside Thermometer Resolution: “);
Serial.print(sensors.getResolution(outsideThermometer), DEC);
Serial.println();
}

// function to get the temperature for a device
float getTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
return tempC;
}

// function to print a device’s resolution
void printResolution(DeviceAddress deviceAddress)
{
Serial.print(“Resolution: “);
Serial.print(sensors.getResolution(deviceAddress));
Serial.println();
}

/********************************************************************************************************/

void loop(void){
// No need to go as fast as we can
delay(10000);
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.println();
Serial.print(“Requesting temperatures…”);
sensors.requestTemperatures();
Serial.println(“DONE”);
OutsideTempC = getTemperature(outsideThermometer);
OutsideTempF = DallasTemperature::toFahrenheit(OutsideTempC);
InsideTempC = getTemperature(insideThermometer);
InsideTempF = DallasTemperature::toFahrenheit(InsideTempC);
// print the device information
Serial.print(“Inside Temperature: “);
Serial.print(“Temp C: “);
Serial.print(InsideTempC);
Serial.print(” Temp F: “);
Serial.print(InsideTempF);
Serial.println();

Serial.print(“Outside Temperature:”);
Serial.print(” “);
Serial.print(“Temp C: “);
Serial.print(OutsideTempC);
Serial.print(” Temp F: “);
Serial.print(OutsideTempF);
Serial.println();

// Turn on Fans if inside temp is above setpoint
// … and inside temp is higher than outside temp
if((InsideTempF > HighTempSetpoint)&&(InsideTempF > OutsideTempF))
{
digitalWrite(fan, HIGH); // turn the Fan on (HIGH is the voltage level)
Cooling = true;
timer = 0;
}
// keep track of delay to shut off fan
else if (((InsideTempF < HighTempSetpoint)&&(Cooling == true))||((InsideTempF <= OutsideTempF)&&(Cooling == true)))
{
timer += 1;
Serial.print(“timer = “);
Serial.println(timer);
}
// once we have been cool enough for about 2 minutes, turn off the fan
// assumes loop delay of 10000 ms set above
if (timer >= 12)
{
digitalWrite(fan, LOW); // turn the Fan off (LOW is the voltage level)
Cooling = false;
timer = 0;
}
if (Cooling == true)
{
Serial.println(“Fan is ON”);
}
}