| | /* |
---|
| | * 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(); |
---|
| | } |
---|
| | } |
---|
| | |
---|
| | |