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.

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…


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

In Operation

In Operation

Here is the main chunk of code…

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


#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 3 on the Arduino
#define ONE_WIRE_BUS 3
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
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.println("Dallas Temperature IC Control Library Demo");
// Start up the library
 // 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.print("Outside Thermometer Resolution: ");
 Serial.print(sensors.getResolution(outsideThermometer), DEC); 
// 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: ");


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(" Temp F: ");

 // 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 = ");
 // 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");