/* * Open and close the door on the chicken house depending on the * ambient light levels. * Copyright Alex Tucker 2013 * */ #include <Narcoleptic.h> #define NODEBUG #ifdef DEBUG #define DPRINTLN(str) Serial.println(str) #else #define DPRINTLN(str) #endif #define ONOFF_PIN 5 #define FWREV_PIN 3 #define DOOR_CONTACT_PIN 4 #define BUTTON_PIN 2 #define PHOTOCELL_PIN 0 #define TEMP_SUPPLY_PIN 6 #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 #define OPEN_DELAY 6500 #define MAX_CLOSE_TIME 7500 #define HYSTERESIS 50 word brightness[BRIGHTNESS_SIZE]; int state = WAIT_FOR_LIGHT; volatile int button_state = 0; void setup() { pinMode(ONOFF_PIN, OUTPUT); pinMode(FWREV_PIN, OUTPUT); pinMode(DOOR_CONTACT_PIN, INPUT); digitalWrite(DOOR_CONTACT_PIN, LOW); pinMode(BUTTON_PIN, INPUT); pinMode(TEMP_SUPPLY_PIN, OUTPUT); digitalWrite(TEMP_SUPPLY_PIN, HIGH); // for initial photocell reading // attachInterrupt(0, pressButton, LOW); digitalWrite(ONOFF_PIN, LOW); digitalWrite(FWREV_PIN, LOW); state = INITIALIZE; word currentBrightness = analogRead(PHOTOCELL_PIN); for (int i = 0; i < BRIGHTNESS_SIZE; i++) { brightness[i] = currentBrightness; } digitalWrite(TEMP_SUPPLY_PIN, LOW); Narcoleptic.disableTimer1(); Narcoleptic.disableTimer2(); #ifdef DEBUG Serial.begin(9600); #else Narcoleptic.disableSerial(); #endif Narcoleptic.disableWire(); Narcoleptic.disableSPI(); Narcoleptic.disableADC(); } /* void pressButton() { button_state = 1; } */ void raiseDoor() { long millisLeft = MAX_CLOSE_TIME; digitalWrite(TEMP_SUPPLY_PIN, HIGH); digitalWrite(FWREV_PIN, LOW); delay(100); millisLeft -= 100; digitalWrite(ONOFF_PIN, HIGH); while ((digitalRead(DOOR_CONTACT_PIN) == LOW) && (millisLeft > 0)) { delay(100); millisLeft -= 100; } delay(200); digitalWrite(ONOFF_PIN, LOW); delay(10); digitalWrite(TEMP_SUPPLY_PIN, LOW); } void lowerDoor() { digitalWrite(TEMP_SUPPLY_PIN, HIGH); digitalWrite(FWREV_PIN, HIGH); delay(10); digitalWrite(ONOFF_PIN, HIGH); delay(OPEN_DELAY); digitalWrite(ONOFF_PIN, LOW); delay(10); digitalWrite(FWREV_PIN, LOW); digitalWrite(TEMP_SUPPLY_PIN, LOW); } word readBrightness() { Narcoleptic.enableADC(); digitalWrite(TEMP_SUPPLY_PIN, HIGH); delay(500); word currentBrightness = analogRead(PHOTOCELL_PIN); DPRINTLN(currentBrightness); digitalWrite(TEMP_SUPPLY_PIN, LOW); Narcoleptic.disableADC(); unsigned long total = brightness[0]; for (int i = 0; i < BRIGHTNESS_SIZE; i++) { if (i == (BRIGHTNESS_SIZE - 1)) { brightness[i] = analogRead(PHOTOCELL_PIN); } else { brightness[i] = brightness[i+1]; } total += brightness[i]; } word avg = total / (BRIGHTNESS_SIZE + 1); return avg; } void loop() { switch (state) { case INITIALIZE: digitalWrite(TEMP_SUPPLY_PIN, HIGH); delay(500); if (digitalRead(DOOR_CONTACT_PIN) == LOW) { raiseDoor(); } DPRINTLN("-> WAIT_FOR_LIGHT"); state = WAIT_FOR_LIGHT; break; case WAIT_FOR_LIGHT: if ((readBrightness() > (BRIGHT_THRESHOLD + HYSTERESIS)) || (button_state == 1)) { button_state = 0; DPRINTLN("-> LOWER_DOOR"); state = LOWER_DOOR; } else { #ifdef DEBUG delay(10000); #else Narcoleptic.delay(30000); #endif } break; case LOWER_DOOR: lowerDoor(); DPRINTLN("-> WAIT_FOR_DARK"); state = WAIT_FOR_DARK; break; case WAIT_FOR_DARK: if ((readBrightness() < (BRIGHT_THRESHOLD - HYSTERESIS)) || (button_state == 1)) { button_state = 0; DPRINTLN("-> RAISE_DOOR"); state = RAISE_DOOR; } else { #ifdef DEBUG delay(10000); #else Narcoleptic.delay(30000); #endif } break; case RAISE_DOOR: raiseDoor(); DPRINTLN("-> WAIT_FOR_LIGHT"); state = WAIT_FOR_LIGHT; break; } }