LCC Code v4

Below the break is revision 4. Read the comments in the code. I’ll post a formal description of the software’s behavior soon.

Also included is a zip file of the serialreceiver to get data from the arduino. This runs in the processing language. Get it here: serialreceiver for LCC v4
[php]

/*
Software started on 3/5/2012
Revision 1 – initial
Revision 2 – adds Minute on time specification, simplified rule definitions
Revision 3 – adds Weekend On Time Delay, changes day/night rule handling

This is the software for controlling a simple time and temp constrained environment for our bearded dragon.
Temps are checked constantly and compared to a high and low temp.
Light use is defined by a On and Off schedule.
Items are on/off based on the hour and minute from the RTC.

Rule Definitions:
DAY
1 Day if temp is ok turn all on
2 Day if temp is too high
Condition 1 rock off/light on condition existed for < overTempFirstAction Condition 2 rock off/light on condition existed for > overTempFirstAction && < overTempSecondAction
Condition 3 delay turning all on until temp has dropped to 5 below high temp threshold
NIGHT
1 Night if temp is ok turn all off
2 Night if temp is too low
Condition 1 rock on/light off condition existed for < underTempFirstAction Condition 2 rock on/light off condition existed for > underTempFirstAction && < underTempSecondAction Condition 3 rock on/light on condition existed for > underTempSecondAction
Condition 4 rock on/light on condition existed for > underTempSecondAction + 5 Min Sound Alarm

*/

#include “Wire.h”
#include “PCD8544.h”
#include “DHT.h”
#include “Tone.h”
#include “Time.h”
#include “DS1307RTC.h”

//pins for the temp sensors
#define DHTPIN1 8
#define DHTPIN2 9

//type of temp sensors
#define DHTTYPE DHT22

//the AC switch digital pins
#define SW1 10 //light
#define SW2 11 //rock

//set the HOUR and MINUTES (24 HR Format) for lights on/off
#define LightsOnHr 5
#define LightsOnMin 45
#define LightsOffHr 20
#define LightsOffMin 5
#define WeekendDelay 2
int isDay = 0; //global variable to indicate day/night period

//set the high and low temp thresholds in F
#define HighTempF 108
#define LowTempF 75

//setup time stamps for condition changes
static unsigned long overTempFirstAction = 600000; //10 minutes
static unsigned long overTempSecondAction = 1200000; //20 minutes
unsigned long overTempStart;
unsigned long overTempDuration;
static unsigned long underTempFirstAction = 600000; //10 minutes
static unsigned long underTempSecondAction = 1200000; //20 minutes
unsigned long underTempStart;
unsigned long underTempDuration;
String stringDateTime; //used to print the date/time properly
int inByte = 0; // incoming serial byte
int DEBUG = 0;

#define aref_voltage 5.0

//setup the two temp/humid probes as objects
DHT dht1(DHTPIN1, DHTTYPE);
DHT dht2(DHTPIN2, DHTTYPE);

//config the lcd
static PCD8544 lcd = PCD8544(7, 6, 5, 4, 3);

void setup() {
Serial.begin(57600);
Serial.println(“Lizard Climate Control Starting Up…”);

//setup the lcd
lcd.init();
lcd.setContrast(21);
lcd.clear();

Wire.begin();

setSyncProvider(RTC.get); // the function to get the time from the RTC

//turn off the AC devices while we set things up

pinMode(SW1, OUTPUT);
pinMode(SW2, OUTPUT);
digitalWrite(SW1, LOW);
digitalWrite(SW2, LOW);

}

void loop() {
determineIsDay();
processSchedule();
// Read the temperature (in celsius)…
float temperatureC1 = dht1.readTemperature();
float temperatureF1 = (temperatureC1 * 9.0 / 5.0) + 32.0;
float humid1 = dht1.readHumidity();
float temperatureC2 = dht2.readTemperature();
float temperatureF2 = (temperatureC2 * 9.0 / 5.0) + 32.0;
float humid2 = dht2.readHumidity();

//output basics to the lcd screen
lcd.clear();
lcd.setCursor(0, 0);
printDateTimeNoYear(); //get properly formatted date/time into a printable string
lcd.print(stringDateTime);

lcd.setCursor(0, 8);
lcd.print(“Right:”);
lcd.println(temperatureF1, 2);

lcd.setCursor(0, 16);
lcd.print(“Humid:”);
lcd.print(humid1, 2);
lcd.println(“%”);

lcd.setCursor(0, 24);
lcd.print(“Left :”);
lcd.println(temperatureF2, 2);

lcd.setCursor(0, 32);
lcd.print(“Humid:”);
lcd.print(humid2, 2);
lcd.println(“%”);

lcd.setCursor(0,40);
lcd.print(“SW1:”);
lcd.print(digitalRead(SW1));
lcd.print(” SW2:”);
lcd.print(digitalRead(SW2));
lcd.display();

}

void processSchedule(){//turn the lights on/off based on the time schedule and temperature

if (DEBUG) {Serial.println(“Running processSchedule function”);}

// Read the temperature (in celsius) and convert to F…
float temperatureC1 = dht1.readTemperature();
float temperatureF1 = (temperatureC1 * 9.0 / 5.0) + 32.0;

//print this only if debugging has been called
if (DEBUG) {
Serial.print(“Run @ “);
printDateTime(); //get properly formatted date/time into a printable string
Serial.print(stringDateTime);
Serial.println();
}

//**********day time rules**********
//SW1=rock
//SW2=light

if (isDay == 1){
if (DEBUG) {Serial.println(“–DAY–“);}

if (temperatureF1 < HighTempF && overTempStart == 0) { if (DEBUG) {Serial.println(“RULE 1 TRUE–“);} digitalWrite(SW1, HIGH); digitalWrite(SW2, HIGH); }//END DAY RULE 1 //if temp is too high and it’s daytime if (temperatureF1 > HighTempF || overTempStart > 0)
{
if (DEBUG) {Serial.println(“RULE 2 TRUE–“);}

//if overtempstart is zero set it otherwise get the difference between now and when it was set
if (overTempStart == 0) {overTempStart = millis();} else {overTempDuration = millis() – overTempStart;}

//if the condition has existed for less than overTempFirstAction keep rock off and the light on
if (overTempDuration < = overTempFirstAction) {digitalWrite(SW1, LOW); digitalWrite(SW2, HIGH); if (DEBUG) {Serial.println(“–CONDITION 1 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}} //if the condition has existed for more than overTempFirstAction // and less than overTempSecondAction keep rock off and the light on if (overTempDuration > overTempFirstAction && overTempDuration < overTempSecondAction) {digitalWrite(SW1, LOW); digitalWrite(SW2, HIGH); if (DEBUG) {Serial.println(“–CONDITION 2 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}} //if the condition has existed for more than overTempSecondAction turn off rock and light if (overTempDuration > overTempSecondAction) {digitalWrite(SW1, LOW); digitalWrite(SW2, LOW);
if (DEBUG) {Serial.println(“–CONDITION 3 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}}

if (temperatureF1 < HighTempF – 5) {overTempStart = 0; overTempDuration = 0;} else {//temp still too high, wait a while until it drops to 5 below HighTempF if (DEBUG) {Serial.println(“–DELAY IN ALL ON AGAIN–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);} } } else {overTempStart = 0; overTempDuration = 0;} } //end of isDay group //*********night time rules********* if (isDay == 0) { if (DEBUG) {Serial.println(“–NIGHT–“);} //if temp is ok and it’s outside LightsOn time keep it all off if (temperatureF1 >= LowTempF ) {
if (DEBUG) {Serial.println(“RULE 1 TRUE–“);}
digitalWrite(SW1, LOW);
digitalWrite(SW2, LOW);
}

//if temp is too low turn on the heating rock keeping lights off

if (temperatureF1 < LowTempF) {
if (DEBUG) {Serial.println(“RULE 2 TRUE–“);}

//if underTempStart is zero set it otherwise get the difference between now and when it was set
if (underTempStart == 0) {underTempStart = millis();} else {underTempDuration = millis() – underTempStart;}

//if the condition has existed for less than underTempFirstAction keep rock on and the light off
if (underTempDuration underTempFirstAction && underTempDuration < underTempSecondAction) {digitalWrite(SW2, HIGH); digitalWrite(SW1, LOW); if (DEBUG) {Serial.println(“–CONDITION 2 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}} //if the condition has existed for more than underTempSecondAction turn on rock and light if (underTempDuration > underTempSecondAction) {digitalWrite(SW1, HIGH); digitalWrite(SW2, HIGH);
if (DEBUG) {Serial.println(“–CONDITION 3 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}}

//if the condition has existed for more than underTempSecondAction + 5 Minutes turn on rock and light and sound alarm
if (underTempDuration > underTempSecondAction + 300000) {digitalWrite(SW1, HIGH); digitalWrite(SW2, HIGH); soundALARM();
if (DEBUG) {Serial.println(“–CONDITION 4 TRUE–“); Serial.println(overTempStart,DEC); Serial.println(overTempDuration,DEC);}}

}

} else {underTempStart = 0; underTempDuration = 0;}

if (DEBUG) {Serial.print(“isDay=”);}
if (DEBUG) {Serial.println(isDay);}
if (DEBUG) {Serial.println(“*”);}

}

void determineIsDay(){ //all the rules to decide if it’s day or night according to the on/off times
//weekday() 1 = sunday 7 = saturday
time_t t = now();

if (hour(t) >= LightsOnHr && hour(t) < LightsOffHr && weekday(t) != 1 && weekday(t) != 7){
if (hour(t) == LightsOnHr && minute(t) < LightsOnMin){isDay = 0;} //0 = night if (hour(t) == LightsOnHr && minute(t) >= LightsOnMin){isDay = 1;} //1 = day
if (hour(t) > LightsOnHr){isDay = 1;} //1 = day
//if (DEBUG) {Serial.println(“isDay Rule 1 Used”);}
}

if ((hour(t) >= LightsOffHr) || (hour(t) < LightsOnHr)){
if (hour(t) == LightsOffHr && minute(t) < LightsOffMin){isDay = 1;} //1 = day if (hour(t) == LightsOffHr && minute(t) >= LightsOffMin){isDay = 0;} //0 = night
if (hour(t) >= LightsOffHr || hour(t) < LightsOnHr){isDay = 0;} //0 = night //if (DEBUG) {Serial.println(“isDay Rule 2 Used”);} } if ((hour(t) >= LightsOnHr + WeekendDelay && hour(t) < LightsOffHr) && (weekday(t) == 1 || weekday(t) == 7)){
if (hour(t) == LightsOnHr + WeekendDelay && minute(t) < LightsOnMin){isDay = 0;} //0 = night if (hour(t) == LightsOnHr + WeekendDelay && minute(t) >= LightsOnMin){isDay = 1;} //1 = day
if (hour(t) > LightsOnHr + WeekendDelay){isDay = 1;} //1 = day
//if (DEBUG) {Serial.println(“isDay Rule 3 Used”);}
}

if ((hour(t) >= LightsOffHr || hour(t) < LightsOnHr + WeekendDelay) && (weekday(t) == 1 || weekday(t) == 7)){
if (hour(t) == LightsOffHr && minute(t) < LightsOffMin){isDay = 1;} //1 = day if (hour(t) == LightsOffHr && minute(t) >= LightsOffMin){isDay = 0;} //0 = night
if (hour(t) >= LightsOffHr || hour(t) < LightsOnHr + WeekendDelay){isDay = 0;} //0 = night
//if (DEBUG) {Serial.println(“isDay Rule 4 Used”);}
}
}

void soundALARM() {
//play_rtttl(song);

}

void serialEvent() {
//serial output for Processing to use in updating a web page
// if we get a valid byte, read analog ins:
// get incoming byte:
inByte = Serial.read();
if (inByte != NULL) {
switch (inByte){
case 82: case 114: //”R or r” as ASCII DEC Byte Value
outputDebugData();
break;

case 68: case 100://”D or d” as ASCII DEC Byte Value
DEBUG = 1;
outputDebugData();
processSchedule();
DEBUG = 0;
break;

case 84: case 116: //”T or t” as ASCII DEC Byte Value
printDateTime();
Serial.println(stringDateTime);
break;

default:
break;
}
}

}

void printDateTime(){
//print date/time with leading zeros
String dataOutput = “”;
if (month() < 10) {dataOutput += “0”; dataOutput += month(), DEC;} else {dataOutput += month(), DEC;}
dataOutput += ‘/’;
if (day() < 10) {dataOutput += “0”; dataOutput += day(), DEC;} else {dataOutput += day(), DEC;}
dataOutput += ‘/’;
dataOutput += year(), DEC;
dataOutput += ” “;
if (hour() < 10) {dataOutput += “0”; dataOutput += hour(), DEC;} else {dataOutput += hour(), DEC;}
dataOutput += ‘:’;
if (minute() < 10) {dataOutput += “0”; dataOutput += minute(), DEC;} else {dataOutput += minute(), DEC;}
dataOutput += ‘:’;
if (second() < 10) {dataOutput += “0”; dataOutput += second(), DEC;} else {dataOutput += second(), DEC;}
//Serial.println(dataOutput);
stringDateTime = dataOutput;
}

void outputDebugData(){
// Read the temperature (in celsius)…
float temperatureC1 = dht1.readTemperature();
float temperatureF1 = (temperatureC1 * 9.0 / 5.0) + 32.0;
float humid1 = dht1.readHumidity();
float temperatureC2 = dht2.readTemperature();
float temperatureF2 = (temperatureC2 * 9.0 / 5.0) + 32.0;
float humid2 = dht2.readHumidity();

printDateTime(); //get properly formatted date/time into a printable string
Serial.print(stringDateTime);
Serial.println();
Serial.print(“Right:”);
Serial.println(temperatureF1, 2);
Serial.print(“Humid:”);
Serial.println(humid1, 2);
Serial.print(“Left:”);
Serial.println(temperatureF2, 2);
Serial.print(“Humid:”);
Serial.println(humid2, 2);
Serial.print(“Switch 1:”);
Serial.println(digitalRead(SW1));
Serial.print(“Switch 2:”);
Serial.println(digitalRead(SW2));
Serial.println(“*”);
}

void printDateTimeNoYear(){
//print date/time with leading zeros
String dataOutput = “”;
if (month() < 10) {dataOutput += “0”; dataOutput += month(), DEC;} else {dataOutput += month(), DEC;}
dataOutput += ‘/’;
if (day() < 10) {dataOutput += “0”; dataOutput += day(), DEC;} else {dataOutput += day(), DEC;}
//dataOutput += ‘/’;
//dataOutput += year(), DEC;
dataOutput += ” “;
if (hour() < 10) {dataOutput += “0”; dataOutput += hour(), DEC;} else {dataOutput += hour(), DEC;}
dataOutput += ‘:’;
if (minute() < 10) {dataOutput += “0”; dataOutput += minute(), DEC;} else {dataOutput += minute(), DEC;}
dataOutput += ‘:’;
if (second() < 10) {dataOutput += “0”; dataOutput += second(), DEC;} else {dataOutput += second(), DEC;}
//Serial.println(dataOutput);
stringDateTime = dataOutput;
}

[/php]

Author: Helicopter Jeff

I'm a vinyl decal cutting and designing, Astrophotography and general photography capturing, RC helicopter/quad copter pilot, Arduino and Raspberry Pi hardware/software developer, network, scripting and troubleshooting ninja living in the metro NY area. I am passionate about my hobbies so much I do them for a living. There's nothing better than getting paid to do what you love.

3 thoughts on “LCC Code v4”

  1. I was looking at trying my hand at this as well as I have 2 adult “beardies” as well in there separate enclosures. It looks like you have worked most of it out.
    Question/thought for you, I was thinking that having a Fan (like a small box fan) might be a good way to cool the area and help regulate the temperature and humidity of the enclosure. Is there enough outputs left to be able to control the fan based on temp and humidity levels?
    Also another question, I noticed that you have 2 sensors but I am not sure which sensor you are using as the determination on too hot or cold. Are you using the “hot” side during the day and the “cold” side at night???

    1. I think there are a few. I need to add a 3 color LED to indicate the temp state (normal,warning,over). That’ll take 2 pins, although the output side (3 pins) could go to a fan. The logic as it is now would turn on the red LED and wait until the temp drops. If your case you could add a transistor to the red or yellow LED to turn on a fan at the same time. The LED indicating isn’t implemented yet. I’m fighting with LED driver chips right now.

      I use the hot side for all temp readings. The other is just for reference. Technically you could dump the cold side and use that for a fan if you wanted. I’m not sure what the point of monitoring the cold side yet…

      I’m going to reevaluate the setup soon because my I/O usage is very poor. I’m hunting for a latching multiplexer- meaning that when you open an address/io port you can set it high or low and it’ll stay that way when you go read another.

    2. As an update to your questions- I’m looking at using I2C to allow more devices/switches per I/O port. I hope this will solve the shortage. I did add the 3 color LED but it used the last of the I/O in the current configuration.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s