/* ******************************************************** Copyright (c) 2010 Rik Sagar - http://sagar/org ******************************************************** */ /* **************** Hardware setup **************** */ int ledPin = 13; // LED connected to digital pin 13 int feederPin = 12; int detectorPin = 11; /* **************** Features related to the feeding rate **************** */ unsigned long one_day = 1L*24*60*60*1000; #define DAYS(_x) ((_x)*one_day) #define SECONDS(_x) ((_x)*1L*1000) #define MINUTES(_x) ((_x)*1L*1000*60) unsigned long FEED_INTERVAL = DAYS(2); unsigned long MAX_DELIVERY_DURATION = SECONDS(20); /* **************** state machine/main loop control **************** */ unsigned int LOOP_DELAY = 100; /* ********************** App variables ********************** */ unsigned long next_feeding; unsigned long feeding_timer; typedef enum { waiting_for_feeding, delivering_food, finishing_feeding } FeedState; FeedState feed_state; boolean motorDetect; boolean lastMotorDetect; // Used to count one second unsigned int loop_counter; void setup(){ // sets some digital pins as output pinMode(ledPin, OUTPUT); pinMode(feederPin, OUTPUT); pinMode(detectorPin, INPUT); digitalWrite(detectorPin, HIGH); // Initialize the feed time and app 'statemachine' next_feeding = millis()+SECONDS(10); feed_state = waiting_for_feeding; loop_counter = 0; // open the serial port at 9600 bps: Serial.begin(9600); } void loop(){ delay(LOOP_DELAY); if (1 == loop_counter){ digitalWrite(ledPin, HIGH); // sets the LED on } else if (2 == loop_counter) { digitalWrite(ledPin, LOW); // sets the LED off } else if ( (loop_counter*LOOP_DELAY) >= SECONDS(1)){ loop_counter = 0; } ++loop_counter; switch(feed_state){ case waiting_for_feeding: if (millis() > next_feeding){ Serial.print("deliverying..."); lastMotorDetect = digitalRead(detectorPin); feeding_timer = millis() + MAX_DELIVERY_DURATION; feed_state = delivering_food; digitalWrite(feederPin, HIGH); } break; case delivering_food: Serial.print("."); motorDetect = digitalRead(detectorPin); Serial.print("Motor detect: ");Serial.println(motorDetect?"true":"false"); if (!lastMotorDetect && motorDetect){ // +ve transition feed_state = finishing_feeding; } else { // No change or -ve transition lastMotorDetect = motorDetect; } // Fail safe - if motor has failed or sensor has failed, don't attempt to run forever. // timeout fater MAX_DELIVERY_DURATION seconds if (millis() > feeding_timer){ feed_state = finishing_feeding; } break; case finishing_feeding: digitalWrite(feederPin, LOW); next_feeding += FEED_INTERVAL; feed_state = waiting_for_feeding; Serial.print("Finished feeding: "); Serial.println(millis()); break; default: // Something got messed-up! setup(); break; } }