Time/Temperature controlled Freezer help!

Hello, first off this is my first project so be patiant with me lol

Project Scope - Im tired of paying higher rates of electricity during the day so im trying to make smart appliances. I am going to start with a freezer because it seems easiest to minipulate because of the solid state relay. What I am trying to do is to run a clock on the arduino and make the freezer run to a lower temperature during the night and idle during the day when electricity is more expensive.

From 7pm - 7am set the temperature to -20
From 7am - 7pm set the temperature to -5

Hardware
-Arduino Uno, software 0022
-Termometer DS18S20 (1-wire, range of -55°C to +125°C)
-4x20 Serial enabled LED screen

I got the arduino reading temperature by using the one wire library
I also seperatly got the arduino keeping time and outputting to the serial monitor using the Timeserial library.

How to execute: The way i see it, is that I will have the time library running all the time and at the end of the code put in a If/Else statement to decide what time setting we are currwently in. Then under each statment, jump to a sub rutine where it will check the tremperature and output to a pin to turn the relay on/off depending on the current temperature.

My Issue: My problem right now is that this is my first time programming and i am not sure how to call the time libray to check what time it currently is so it can jump into the correct sub rutine (which i also still need to write). Any help would be hugly appreciated - even directing me to some programming help with this situation. I have been trying to find something but havent come up with anything.

Thanks

Better add a DS1307 RealTimeClock - http://www.sparkfun.com/datasheets/Components/DS1307.pdf -
check - Data-Logger Shield for Arduino - for a RTC library

#define MORNING (7*60)
#define EVENING (19*60)
#define DOORPIN   4

#define DAYLOW -6
#define DAYHIGH -5
#define NIGHTLOW -22
#define NIGHTHIGH -20

void setup()
{
  // setup things here of course ;)
}

void loop()
{
  // MEASUREMENTS
  float temp = getTemperature();                                        // DS18B20 code goes into this subroutine
  unsigned long tod = RTC.hour*60 + RTC.minutes();             // time Of Day  rtc code could differ
  bool door = digitalRead(DOORPIN);

  // PROCESS
  bool nightMode = ( tod < MORNING  || tod > EVENING );                   

  // DISPLAY
  Serial.println(what needs to be printed on display)
  log(time, temp, door);                                         // to some SD card so you can read it in excel ;)

  // ACTION
  if (nightMode)
  {
    if (temp > NIGHTHIGH)         // better use #define for all the constants 
    {
      startFreezer();
    }
    if (temp < NIGHTLOW) 
    {
      stopFreezer();
    }
  }
  else
  {
    if (temp > DAYHIGH) 
    {
      startFreezer();
    }
    if (temp < DAYLOW ) 
    {
      stopFreezer();
    }
  }
}

startFreezer()
{
  digitalWrite(FREEZERPIN, HIGH);
}

etc

Note that the switching uses 2 different temperatures for ON / OFF. This prevents that the motor runs very short times, which costs even more electricity and wears the motor..

It would be fun to do this with an Arduino but means making your own programmable thermostat (and you'll need an RTC to go with it or you'll find it gets out of sync with real time).

Have you considered simply buying and fitting a programmable thermostat?

Once read about a circadian clock;

Add an LDR to see if it is day or night and you can make a quite good estimate of the mid-day moment. Assume this is 12:00.
A sketch to monitor the LDR value during the day is not too difficult.

Then you can calculate 07:00 and 19:00 quite good with millis().
Of course every day the peak moment will be slightly different, so adjusting the mid-day moment should be done in small steps.

The LDR should of course watch the outside world and not be influenced by electric light or so.

Thanks for your reply guys. Im going to look into getting the RTC clock and getting it working but im not sure with time constraints I can get that done in time. Im ordering the chip but in the meantime I just found the time alarm library and was wondering if i could use this to call a function as a "rough draft" to get it working. This is kinda what i mean -

#define DAYLOW -6
#define DAYHIGH -5
#define NIGHTLOW -22
#define NIGHTHIGH -20

setTime(6,0,0,1,28,12); // set time to 6:00:00am Jan 28 2012
Alarm.alarmRepeat(0,01,00, Daymode); // 7:00am every day
Alarm.alarmRepeat(0,17,20,Nightmode); // 7:00pm every day
Float temp = getTemperature() ; // DS18B20 code goes into this subroutine

}

void Daymode()
{
if (temp > DAYHIGH) // better use #define for all the constants
{
startFreezer();
}
if (temp < DAYLOW)
{
stopFreezer();
}
}

void Nightmode()
{
if (temp > NIGHTHIGH) // better use #define for all the constants
{
startFreezer();
}
if (temp < NIGHTLOW)
{
stopFreezer();
}
}

Controlling power usage during the day has been a part-time project of mine for over a year now. I had the problems with keeping track of time and approached it differently. I created a clock to service all the devices in the house and hooked it to an XBee. This little device provides time to all the other devices and gets the time from the GPS satellite system. The devices themselves use the TimeAlarm library to set various alarms and timers for the particular appliance they control. I started with my two heat pumps. They use a huge amount of power during the cold winter (relatively) and hot summers (absolutely) and were sending me to the poor house.

I don't use a real time clock, simply because I didn't want to put one of them in every device in the house and then deal with checking on them all the time. The TimeAlarm library is perfect (from my point of view) for this kind of thing. Simply setting an alarm for when the power rates go up and then another for when the rates go down did the job very nicely. You're welcome to steal any idea or piece of code from my site that discusses this desert-home.com

My particular implementation may not be what you need or want, but maybe it could provide some ideas you can use.

Hey guys, thanks for the replies, I did end up ordering the data logger shield and have it up and running. I have it getting temperature, the time, and also have the photo-resistor hooked up as it will let me know when someone has opened the door of the freezer. I'm down to writing the code to jump to the two functions that will set my temperature for Day and Night. This is what I have so far:

#include <Wire.h>
#include "RTClib.h"
#define aref_voltage 3.3

RTC_DS1307 RTC;

int tempReading;
int tempPin = 1;
int photocellReading;
int photocellPin = 2;

void setup () {
    Serial.begin(9600);
    Wire.begin();
    analogReference(EXTERNAL);
  }

void loop () {
    
    analogRead(photocellPin);
  delay(10);
  photocellReading = analogRead(photocellPin);  
  
  Serial.print("Light reading = ");
  Serial.print(photocellReading);     // the raw analog reading
  
  // We'll have a few threshholds, qualitatively determined
  if (photocellReading < 10) {
    Serial.println(" - Dark");
  } else if (photocellReading < 200) {
    Serial.println(" - Dim");
  } else if (photocellReading < 500) {
    Serial.println(" - Light");
  } else if (photocellReading < 800) {
    Serial.println(" - Bright");
  } else {
    Serial.println(" - Very bright");
  }
  
  analogRead(tempPin);
  delay(10);
  tempReading = analogRead(tempPin);  
  
  Serial.print("Temp reading = ");
  Serial.print(tempReading);     // the raw analog reading
  
  // converting that reading to voltage, which is based off the reference voltage
  float voltage = tempReading * aref_voltage / 1024; 
 
  // print out the voltage
  Serial.print(" - ");
  Serial.print(voltage); Serial.println(" volts");
 
  // now print out the temperature
  float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((volatge - 500mV) times 100)
  Serial.print(temperatureC); Serial.println(" degrees C");
 
  // now convert to Fahrenheight
  float temperatureF = (temperatureC * 9 / 5) + 32;
  Serial.print(temperatureF); Serial.println(" degrees F");
 
  DateTime now = RTC.now();
    
    Serial.print("The time is:");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    delay(1000);
    
  {
    if (now.hour >= 7 && now.hour <= 19);   //If time is between 7am and 7pm print day time setting)
    {                                       //It will later call a function to check if the temp is between a value
      Serial.print("Day time setting");     // and then turn a relay on for the freezer if not the correct setting
    }
    else                                    // if it is not set to day time - set to night time. Which will call a function
    {                                       // that turns on the freezer if not the correct "Night time" temp.
      Serial.print("Night time setting");
    }
  }
}

I'm having problems with the if/else statement at the end of the code. I have it just printing what setting its at and then once this is working I will have it jump to that function which will then check what temperature it is at and set the relay of the freezer accordingly. When I compile, I get an error saying:

Complex_TempLight_Clock_pde:75: error: invalid use of member (did you forget the '&' ?)
Complex_TempLight_Clock_pde:79: error: 'else' without a previous 'if'

I know its just my code writing that's the error but I cant figure out how I should rewrite it.
Thanks alot for your help

if (now.hour >= 7 && now.hour <= 19); //If time is between 7am and 7pm print day time setting)

try getting rid of the semicolon at the end of the if on this line.

I tried taking it out, and that is the line that is producing the error (highlighted yellow when I compile)

It still returned this error:
Complex_TempLight_Clock_pde:75: error: invalid use of member (did you forget the '&' ?)

Original line:

if (now.hour >= 7 && now.hour <= 19); //If time is between 7am and 7pm print day time setting)

I think it should look like this:

if (now.hour() >= 7 && now.hour() <= 19) //If time is between 7am and 7pm print day time setting)

Notice that new.hour() is a function that returns the hour, and the semicolon would have terminated the 'if' statement.

    delay(1000);
    
  {
    if (now.hour >= 7 && now.hour <= 19);   //If time is between 7am and 7pm print day time setting)
    {                                       //It will later call a function to check if the temp is between a value
      Serial.print("Day time setting");     // and then turn a relay on for the freezer if not the correct setting
    }
    else                                    // if it is not set to day time - set to night time. Which will call a function
    {                                       // that turns on the freezer if not the correct "Night time" temp.
      Serial.print("Night time setting");
    }
  }

You might try removing the extra set of brackets just for clarity.
And then add some parenthesis to the conditional branch (the if()) and get rid of the semicolon (:wink: since what follows cannot with the ; there.

    if ((now.hour >= 7) && (now.hour <= 19))   //If time is between 7am and 7pm print day

Quite likely the compiler is seeing your code like this:

    if (now.hour >= (7 && now.hour) <= 19);

BTW, I have seen a lot of places where freezer heat exchangers are kept sitting inside trapped in their own heat with fans furiously running warm to hot air over the radiators. They need to duct air but they don't.

Look into spraying water mist on the radiators (cooling lines) when they are hot if you can't get cool air. The transfer of heat to vaporize water is large though you only want to do that when humidity is not extreme. That to compound the efficiency you are already wanting.

Lastly, why go by time when you should go by air temperature over the radiator?

Ok so was going good. I sauldered on the relay to the freezer and ran the program. The only problem is that it doesnt appear to be following the code. Here is the code that I am using, and I will explain below.

#include <Wire.h>
#include "RTClib.h"
#define NIGHTHIGH -19   
#define NIGHTLOW -21    
#define DAYHIGH -4
#define DAYLOW -6
#define aref_voltage 3.3

RTC_DS1307 RTC;

int tempReading;
int tempPin = 1;
int photocellReading;
int photocellPin = 2;
int relayPin = 6;
float temperatureC;

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(relayPin, HIGH);      // sets relay pin as output
  analogReference(EXTERNAL);
}

void loop()

{
  photocellReading = analogRead(photocellPin);  

  if (photocellReading < 10) 
  {      
    Serial.println("Dark");
  } 
  else if (photocellReading < 200) 
  {
    Serial.println("Dim");
  } 
  else if (photocellReading < 500) 
  {
    Serial.println("Light");
  } 
  else if (photocellReading < 800) 
  {
    Serial.println("Bright");
  } 
  else 
  {
    Serial.println("Very bright");
  }

  tempReading = analogRead(tempPin);  

  // converting that reading to voltage, which is based off the reference voltage
  float voltage = tempReading * aref_voltage / 1024; 

  // now print out the temperature
  float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
  //to degrees ((volatge - 500mV) times 100)
  Serial.print(temperatureC); 
  Serial.println(" degrees C");

  DateTime now = RTC.now();                   // Get time from the RTC chip

  Serial.print("Time:");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  delay(1000);

  if (now.hour() >= 7 && now.hour() < 19)   //If time is between 7am and 7pm print Day time setting)
  {
    Daytime();
    Serial.println("Temp set to -5'C");        // Display what Setting we are currently in
  }
  else                                     //Else set to Night time setting  
  {                                 
    Nighttime();
    Serial.println("Temp set to -20'C");      // Display what Setting we are currently in
  }
 
  Serial.print("The Relay pin is set = ");
  Serial.println(digitalRead(relayPin));

}


void Nighttime()  
{                     
  if (temperatureC > NIGHTHIGH)  //Check temp and compare with setting and set the output accordingly
  { 
    digitalWrite(relayPin, HIGH);
  }
  else if (temperatureC < NIGHTLOW)
  {
    digitalWrite(relayPin, LOW);
  }
}

void Daytime()
{
  if (temperatureC > DAYHIGH)  //Check temp and compare with setting and set the output accordingly
  { 
    digitalWrite(relayPin, HIGH);
  }
  else if (temperatureC < DAYLOW)
  {
    digitalWrite(relayPin, LOW);
  }
}

It correctly displays time, the temperature, the brightness but it consistently displays the relay pin as low (0). This is the code that I had in there to do this

Serial.print("The Relay pin is set = ");
  Serial.println(digitalRead(relayPin));

Also, a larger issue - when I run the program, it displays that is at the correct setting, but it always outputs a high and does not toggle off when it reaches the DAYLOW, or NIGHTLOW. It just keeps it on all the time. I did try forcing the pin high and low and read the voltages coming out of the relay and it did change accordingly but the monitor still showed a low (0). My voltages at the relay were 1.23V as HIGH, and 0V as LOW. So I know that it is going to the correct Daytime, or Nighttime routine, I know it can toggle from forcing it low and high and the freezer responding accordingly, but it just isn't following the program and switching at the set temperatures within the Daytime and Nighttime routines. Does anyone have any ideas? Attached is a print screen of the serial monitor notice how the temperature, light, and temp setting are displaying correctly. But the relay pin shows low (0) and the freezer is still running. It says that it is running in daytime mode - so the max temperature it should reach is a little over -6 and it is at -11.01 and still climbing.

Printscreen.docx (46.6 KB)

#define NIGHTHIGH -19
#define NIGHTLOW -21
#define DAYHIGH -4
#define DAYLOW -6

change to

#define NIGHTHIGH -19.0

or you may be able to:

if (temperatureC > (float)NIGHTHIGH)

Out of all the things to save electricity a frezzer uses minimal electricity already unless it is super old you can just use a furnace therm set low to control a relay for the ac to the frezzer, or just cut the power during peak power hours.

But that's not nearly as much fun.

Defiantly not as much fun, altho this one is starting to frustrate me a little as it was suppose to be the simpler one to start on lol. so I went back and I was declaring the Digital I/O pin wrong. It should have been pinmode (relayPin, OUTPUT) not pinmode (relayPin, HIGH). I also went back and added in the settings (NIGHTHIGH, NIGHTLOW ect.) as a float because I thought that since the temperature reading had decimal places this could have caused an issue.
The code reads temperature and the time good, It compares them correctly and prints to the serial screen that it is on the correct setting. BUT - it does not turn off when it reaches the low parameter - it seems that once it gets to the void loop, it just turns on the freezer and keeps it on. I also noticed another problem - when i put in a positive value for the daytime parameters the serial monitor only displays this:
Dark //Light setting
-3.23 degrees C //Temp
Time: 17:43:24 //Time
Temp set to -5'C //Setting (Daytime)

but does not display
HIGH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //relay pin high

even though the freezer is still running. I dont understand why a positive number would make it skip just that one part, and i dont understand how it will jump to the correct subroutine but only turns the freezer on but never off. Here is my code:

#include <Wire.h>
#include "RTClib.h"
#define NIGHTHIGH -19.00   
#define NIGHTLOW -21.00    
#define DAYHIGH 3.00
#define DAYLOW -6.00
#define aref_voltage 3.3

RTC_DS1307 RTC;

int tempReading;
int tempPin = 1;
int photocellReading;
int photocellPin = 2;
int relayPin = 6;
float temperatureC;

void setup() 
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(relayPin, OUTPUT);      // sets relay pin as output
  analogReference(EXTERNAL);
}

void loop()
{
  photocellReading = analogRead(photocellPin);  

  if (photocellReading < 10) 
  {      
    Serial.println("Dark");
  } 
  else if (photocellReading < 200) 
  {
    Serial.println("Dim");
  } 
  else if (photocellReading < 500) 
  {
    Serial.println("Light");
  } 
  else if (photocellReading < 800) 
  {
    Serial.println("Bright");
  } 
  else 
  {
    Serial.println("Very bright");
  }

  tempReading = analogRead(tempPin);  
  
  // converting that reading to voltage, which is based off the reference voltage
  float voltage = tempReading * aref_voltage / 1024; 
 
  // now print out the temperature
  float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((volatge - 500mV) times 100)
  Serial.print(temperatureC); Serial.println(" degrees C");

  DateTime now = RTC.now();                   // Get time from the RTC chip
  
  Serial.print("Time:");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  delay(1000);
  
  if (now.hour() >= 7 && now.hour() <= 19)   //If time is between 7am and 7pm print Day time setting)
  {
    Daytime();
    Serial.println("Temp set to -5'C");        // Display what Setting we are currently in
  }
  else                                     //Else set to Night time setting  
  {                                 
    Nighttime();
    Serial.println("Temp set to -20'C");      // Display what Setting we are currently in
  }
    
}

void Nighttime()  
{                     
  if (temperatureC > (float)NIGHTHIGH)  //Check temp and compare with setting and set the output accordingly
  { 
    digitalWrite(relayPin, HIGH);
    if (relayPin = HIGH)
      {
        Serial.println("HIGH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
      }
  }
  else if (temperatureC < (float)NIGHTLOW)
  {
    digitalWrite(relayPin, LOW);
    if (relayPin = LOW)
      {
        Serial.println("OFFFFF!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
      }
  }
}

void Daytime()
{
  if (temperatureC > (float)DAYHIGH)  //Check temp and compare with setting and set the output accordingly
  { 
    digitalWrite(relayPin, HIGH);
    if (relayPin = HIGH)
      {
        Serial.println("HIGH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
      }
  }
  else if (temperatureC < (float)DAYLOW)
  {
    digitalWrite(relayPin, LOW);
    if (relayPin = LOW)
      {
        Serial.println("OFFFFF!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
      }
  }
}

Thanks