Initial version, uses photocell and door contact and powers down the Arduino for 8 seconds at a time while waiting.
0 parent commit 0f27e84982b152037d3d3c68062c3aaae2009760
@Alex Tucker Alex Tucker authored on 26 Feb 2013
Showing 1 changed file
View
151
chicken_door.ino 0 → 100644
/*
* Open and close the door on the chicken house depending on the
* ambient light levels.
* Copyright Alex Tucker 2013
*
*/
 
 
// Enable deep sleep with wake on watchdog interrupt.
// Based on Donal Morrissey's code at http://donalmorrissey.blogspot.co.uk/2010/04/sleeping-arduino-part-5-wake-up-via.html
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
 
volatile int f_wdt=1;
 
ISR(WDT_vect) {
if (f_wdt == 0)
{
f_wdt=1;
}
}
 
void enterSleep(void) {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* PWR_SAVE or PWR_DOWN */
sleep_enable();
sleep_mode();
/* The program will continue from here after the WDT timeout*/
sleep_disable(); /* First thing to do is disable sleep. */
/* Re-enable the peripherals. */
power_all_enable();
}
 
#define ONOFF_PIN 2
#define FWREV_PIN 3
#define DOOR_CONTACT_PIN 4
#define BUTTON_PIN 5
#define PHOTOCELL_PIN 0
 
#define INITIALIZE 0
#define WAIT_FOR_LIGHT 1
#define LOWER_DOOR 2
#define WAIT_FOR_DARK 3
#define RAISE_DOOR 4
 
#define BRIGHTNESS_SIZE 3
#define BRIGHT_THRESHOLD 600
 
word brightness[BRIGHTNESS_SIZE];
int state = WAIT_FOR_LIGHT;
 
void setupWDT() {
/* Clear the reset flag. */
MCUSR &= ~(1<<WDRF);
/* In order to change WDE or the prescaler, we need to
* set WDCE (This will allow updates for 4 clock cycles).
*/
WDTCSR |= (1<<WDCE) | (1<<WDE);
 
/* set new watchdog timeout prescaler value */
WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
/* Enable the WD interrupt (note no reset). */
WDTCSR |= _BV(WDIE);
}
 
void setup() {
pinMode(ONOFF_PIN, OUTPUT);
pinMode(FWREV_PIN, OUTPUT);
pinMode(DOOR_CONTACT_PIN, INPUT);
pinMode(BUTTON_PIN, INPUT);
digitalWrite(ONOFF_PIN, LOW);
digitalWrite(FWREV_PIN, LOW);
Serial.begin(9600);
state = INITIALIZE;
word currentBrightness = analogRead(PHOTOCELL_PIN);
for (int i = 0; i < BRIGHTNESS_SIZE; i++) {
brightness[i] = currentBrightness;
}
setupWDT();
}
 
void raiseDoor() {
digitalWrite(FWREV_PIN, LOW);
delay(10);
digitalWrite(ONOFF_PIN, HIGH);
while (digitalRead(DOOR_CONTACT_PIN) == LOW) {
delay(100);
}
digitalWrite(ONOFF_PIN, LOW);
delay(10);
}
 
void lowerDoor() {
digitalWrite(FWREV_PIN, HIGH);
delay(10);
digitalWrite(ONOFF_PIN, HIGH);
delay(10000);
digitalWrite(ONOFF_PIN, LOW);
delay(10);
digitalWrite(FWREV_PIN, LOW);
}
 
word readBrightness() {
word currentBrightness = analogRead(PHOTOCELL_PIN);
unsigned long total = currentBrightness;
for (int i = 0; i < (BRIGHTNESS_SIZE - 1); i++) {
brightness[i] = brightness[i+1];
total += brightness[i];
}
brightness[BRIGHTNESS_SIZE - 1] = currentBrightness;
return total / BRIGHTNESS_SIZE;
}
 
void loop() {
if (f_wdt == 1) {
f_wdt = 0;
switch (state) {
case INITIALIZE:
if (digitalRead(DOOR_CONTACT_PIN) == LOW) {
raiseDoor();
}
state = WAIT_FOR_LIGHT;
break;
case WAIT_FOR_LIGHT:
if (readBrightness() > BRIGHT_THRESHOLD) {
state = LOWER_DOOR;
}
break;
case LOWER_DOOR:
lowerDoor();
state = WAIT_FOR_DARK;
break;
case WAIT_FOR_DARK:
if (readBrightness() < BRIGHT_THRESHOLD) {
state = RAISE_DOOR;
}
break;
case RAISE_DOOR:
raiseDoor();
state = WAIT_FOR_LIGHT;
break;
}
enterSleep();
}
}