I keep forgetting to close the coop door so I automated the door with an Arduino, a linear actuator from Firgelli Automations, four solid state relays from Fotek (in hindsight this is super over designed), and a real time clock from Sparkfun (uses i2c).
Below is the code. It takes into account the day of the year and adjusts sunrise and sunset. The door opens one hour after sunrise and closes one hour after sunset.
/*
- ChickenCoopDoor.pde
- Close door at sunset plus
- Open door at sunrise plus
- Once a day just after midnight calculate sunrise and sunset times for the day
- Edwin A. Pell III 06/29/2010
*/
#include <Wire.h>
#include <Math.h>
#define RTC_ADDR 0x68
int current_day;
int door_opened;
int door_closed;
int sunrise; // in minutes from midnight
int sunset; // in minutes from midnight
int close_a = 2;
int close_b = 3;
int open_a = 4;
int open_b = 5;
int second;
int minutex;
int hour;
int dayOfWeek;
int dayOfMonth;
int month;
int year;
void setup()
{
// Serial.begin(9600);
pinMode(close_a, OUTPUT);
pinMode(close_b, OUTPUT);
pinMode(open_a, OUTPUT);
pinMode(open_b, OUTPUT);
digitalWrite(open_a, LOW);
digitalWrite(open_b, LOW);
digitalWrite(close_a, LOW);
digitalWrite(close_b, LOW);
door_opened = 1;
door_closed = 0;
Wire.begin();
ReadTime();
int current_day = dayOfMonth;
getRiseSet();
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
void OpenDoor()
{
digitalWrite(open_a, HIGH);
digitalWrite(open_b, HIGH);
delay(25000);
digitalWrite(open_a, LOW);
digitalWrite(open_b, LOW);
door_opened = 1;
}
void CloseDoor()
{
digitalWrite(close_a, HIGH);
digitalWrite(close_b, HIGH);
delay(25000);
digitalWrite(close_a, LOW);
digitalWrite(close_b, LOW);
door_closed = 1;
}
void getRiseSet()
{
sunrise = int(350 + (90*cos(((((month-1)30.5)+dayOfMonth)+8)/58.1)));
sunset = int(1075 + (90sin(((((month-1)*30.5)+dayOfMonth)-83)/58.1)));
}
void NewDay()
{
current_day = dayOfMonth;
getRiseSet();
door_opened = 0;
door_closed = 0;
}
void ReadTime()
{
Wire.beginTransmission(RTC_ADDR); // Open I2C line in write mode
Wire.send(0x00); // Set the register pointer to (0x00)
Wire.endTransmission(); // End Write Transmission
Wire.requestFrom(RTC_ADDR, 7); // Open the I2C line in send mode
second = bcdToDec(Wire.receive() & 0x7f); // Read seven bytes of data
minutex = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0x3f);
dayOfWeek = bcdToDec(Wire.receive());
dayOfMonth = bcdToDec(Wire.receive());
month = bcdToDec(Wire.receive());
year = bcdToDec(Wire.receive());
}
void loop()
{
delay(300000);
ReadTime();
if (current_day!=dayOfMonth)
{
NewDay();
}
int current_time = (hour*60)+minutex;
if (current_time > (sunrise+60))
{
if (door_opened == 0)
{
OpenDoor();
}
}
if (current_time > (sunset+60))
{
if (door_closed == 0)
{
CloseDoor();
}
}
}
Ed