/*
* 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 PHOTOCELL_PIN 0
#define DOOR_CONTACT_2_PIN 2
#define FWREV_PIN 3
#define DOOR_CONTACT_1_PIN 4
#define ONOFF_PIN 5
#define TEMP_SUPPLY_PIN 6
#define AUX_BUTTON_PIN 7
#define INITIALIZE 0
#define WAIT_FOR_LIGHT 1
#define OPEN_DOOR 2
#define WAIT_FOR_DARK 3
#define CLOSE_DOOR 4
#define BRIGHTNESS_SIZE 3
#define BRIGHT_THRESHOLD 200
#define OPEN_DELAY 6400
#define MAX_CLOSE_TIME 4000
#define MAX_OPEN_TIME 10000
#define HYSTERESIS 50
word brightness[BRIGHTNESS_SIZE];
int state = WAIT_FOR_LIGHT;
void setup() {
pinMode(ONOFF_PIN, OUTPUT);
pinMode(FWREV_PIN, OUTPUT);
pinMode(DOOR_CONTACT_1_PIN, INPUT);
digitalWrite(DOOR_CONTACT_1_PIN, LOW);
pinMode(DOOR_CONTACT_2_PIN, INPUT);
digitalWrite(DOOR_CONTACT_2_PIN, LOW);
pinMode(AUX_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 closeDoor() {
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_2_PIN) == LOW) && (millisLeft > 0)) {
delay(100);
millisLeft -= 100;
}
// delay(200);
digitalWrite(ONOFF_PIN, LOW);
delay(10);
digitalWrite(TEMP_SUPPLY_PIN, LOW);
}
void openDoor() {
long millisLeft = MAX_OPEN_TIME;
digitalWrite(TEMP_SUPPLY_PIN, HIGH);
digitalWrite(FWREV_PIN, HIGH);
delay(100);
millisLeft -= 100;
digitalWrite(ONOFF_PIN, HIGH);
while ((digitalRead(DOOR_CONTACT_1_PIN) == LOW) && (millisLeft > 0)) {
delay(100);
millisLeft -= 100;
}
delay(250);
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_2_PIN) == LOW) {
closeDoor();
}
DPRINTLN("-> WAIT_FOR_LIGHT");
state = WAIT_FOR_LIGHT;
break;
case WAIT_FOR_LIGHT:
if (readBrightness() > (BRIGHT_THRESHOLD + HYSTERESIS)) {
DPRINTLN("-> OPEN_DOOR");
state = OPEN_DOOR;
} else {
#ifdef DEBUG
delay(10000);
#else
Narcoleptic.delay(30000);
#endif
}
break;
case OPEN_DOOR:
openDoor();
DPRINTLN("-> WAIT_FOR_DARK");
state = WAIT_FOR_DARK;
break;
case WAIT_FOR_DARK:
if (readBrightness() < (BRIGHT_THRESHOLD - HYSTERESIS)) {
DPRINTLN("-> CLOSE_DOOR");
state = CLOSE_DOOR;
} else {
#ifdef DEBUG
delay(10000);
#else
Narcoleptic.delay(30000);
#endif
}
break;
case CLOSE_DOOR:
closeDoor();
DPRINTLN("-> WAIT_FOR_LIGHT");
state = WAIT_FOR_LIGHT;
break;
}
}