I made a cat feeder. The old one started running constantly so I replaced the main board with an Arduino Duemilanove. Any feedback would be appreciated. I’ll add another picture once I get it all put back together.
//#define DEBUG_ON_SERIAL
//#define FEED_NOW
#include <Wire.h>
#include <SparkFunDS1307RTC.h>
#include "Arduino.h"
/*
Pin out: Duemilanove
A4 - SDA
A5 - SCL
2 - Rd Feed Sensor
3 - Wr Motor Run Switch
4 - Rd Button for extra/immediate food
*/
// Const's
const int SENSOR_PIN = 2; // feed sensor
const int BUTTON_PIN = 3; // button to manual feed
const int MOTOR_PIN = 4; // NPN transistor to run feeder motor
const int LED_PIN = 13; // Onboard LED
// Variables
int timeTillNextFeeding = 719; // old diff
int timeFromLastFeeding = 50;
int motorRunning = 0;
int feedAmount = 6;
class myTime
{
/*
To easily compare two times
*/
public:
myTime();
myTime(int, int, int);
myTime(uint8_t, uint8_t, uint8_t);
bool operator<(const myTime &rhs) const
{
if (this->getH() < rhs.getH())
return true;
else if (this->getH() == rhs.getH() && this->getM() < rhs.getM())
return true;
else if (this->getH() == rhs.getH() && this->getM() == rhs.getM() && this->getS() < rhs.getS())
return true;
return false;
};
bool operator==(const myTime &rhs) const
{
if (this->getH() == rhs.getH() && this->getM() == rhs.getM() && this->getS() == rhs.getS())
return true;
return false;
};
/* bool operator>(const myTime &rhs) const
{
if (this < rhs || this == rhs)
return false;
return true;
};
*/
/* void printVars2(myTime &rhs)
{
Serial.print("-->");
Serial.print(String(this->getH()) + ":");
if (this->getM() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.print(String(this->getM())); // Print minute
Serial.print(" | ");
Serial.print(String(rhs.getH()) + ":");
if (rhs.getM() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.println(String(rhs.getM())); // Print minute
};*/
int timeDiffT(myTime &rhs)
{
// returns the minutes diff between this time and passed time
int first, secnd;
first = (this->getH() * 60) + this->getM();
secnd = (rhs.getH() * 60) + rhs.getM();
timeTillNextFeeding = secnd - first;
if (timeTillNextFeeding > 720)
first = first + 1440;
if (timeTillNextFeeding < -720)
secnd = secnd + 1440;
timeTillNextFeeding = first - secnd;
delay(500);
return timeTillNextFeeding;
};
void setH(int h) { H = h; };
void setM(int m) { M = m; };
void setS(int s) { S = s; };
void setMyTime(uint8_t h, uint8_t m, uint8_t s) { setMyTime(int(h), int(m), int(s)); };
void setMyTime(int h, int m, int s)
{
setH(h);
setM(m);
setS(s);
};
int getH() { return H;};
int getM() { return M;};
int getS() { return S;};
private:
int H;
int M;
int S;
};
void pulseLED();
myTime::myTime() { setMyTime(0, 0, 0); }
myTime::myTime(int h, int m, int s) { setMyTime(h, m, s); }
myTime::myTime(uint8_t h, uint8_t m, uint8_t s) { setMyTime(h, m, s); }
myTime feedTime;
myTime currTime;
myTime lastFeedTime;
int timeDiff(myTime &lhs, myTime &rhs)
{
// returns the minutes diff between two passed times
int first, secnd, diff;
first = (lhs.getH() * 60) + lhs.getM();
secnd = (rhs.getH() * 60) + rhs.getM();
diff = secnd - first;
if (diff > 720)
first = first + 1440;
if (diff < -720)
secnd = secnd + 1440;
diff = first - secnd;
//delay(500);
return diff;
}
bool timeToFeed()
{
timeFromLastFeeding = timeDiff(lastFeedTime, currTime);
timeTillNextFeeding = timeDiff(feedTime, currTime);
#ifdef DEBUG_ON_SERIAL
Serial.print("timeToFeed --> L: - ");
Serial.print(timeFromLastFeeding);
Serial.print(" -> N: - ");
Serial.println(timeTillNextFeeding);
#endif
if (timeFromLastFeeding < 5)
return false;
if (timeTillNextFeeding < 5 && timeTillNextFeeding > -5)
return true;
return false;
}
void feedTheCat()
{
#ifdef DEBUG_ON_SERIAL
Serial.print("feedTheCat --> ");
Serial.println(motorRunning);
#endif
if (timeToFeed())
{
motorRunning = feedAmount;
digitalWrite(MOTOR_PIN, HIGH);
}
while (motorRunning > 0)
{
delay(2000);
//--motorRunning; // backup in case the interupt isn't working
}
digitalWrite(MOTOR_PIN, LOW);
}
void setup()
{
#ifdef DEBUG_ON_SERIAL
Serial.begin(9600);
while (!Serial) { ; } // wait for serial port to connect. Needed for native USB port only
#endif
// initialize input / output pins:
pinMode(LED_PIN, INPUT);
digitalWrite(LED_PIN,HIGH);
pinMode(MOTOR_PIN, OUTPUT);
//digitalWrite(SENSOR_PIN,HIGH);
pinMode(SENSOR_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(SENSOR_PIN), increment, FALLING);
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), interuptFeedNow, FALLING);
rtc.begin(); // starts clock
//rtc.autoTime(); // should never need to be run again
//rtc.setTime(s, m, h, day, date, month, year)
//rtc.setTime(0, 11, 23, 7, 11, 8, 18);
feedTime.setMyTime(7,30,0); // hrs, min, sec
}
void loop()
{
int i = 0;
rtc.update(); // Update RTC data
currTime.setMyTime(rtc.hour(), rtc.minute(), rtc.second());
#ifdef DEBUG_ON_SERIAL
#ifdef FEED_NOW
feedTime = currTime;
#endif
#endif
if (timeToFeed())
{
#ifdef DEBUG_ON_SERIAL
Serial.println("**** FEEDING ****");
delay(1000);
#endif
feedTheCat();
}
#ifdef DEBUG_ON_SERIAL
printTime();
printVars();
#endif
// pulseLED();
if (timeTillNextFeeding < 0 && timeFromLastFeeding > 0)
{
//sleep for 60
#ifdef DEBUG_ON_SERIAL
Serial.println("**** SLEEPING for 60 mins ****");
delay(2000);
#else
// what do do in real time
#endif
}
else if (timeTillNextFeeding > 30)
{
//sleep for 30
#ifdef DEBUG_ON_SERIAL
Serial.println("**** SLEEPING for 30 mins ****");
delay(2000);
#else
// what do do in real time
#endif
}
else if (timeTillNextFeeding <= 30 && timeTillNextFeeding > 5)
{
//sleep for 3
#ifdef DEBUG_ON_SERIAL
Serial.println("**** SLEEPING for 3 mins ****");
delay(2000);
#else
// what do do in real time
#endif
}
else if (timeTillNextFeeding <= 5)
{
//sleep for 3
#ifdef DEBUG_ON_SERIAL
Serial.println("**** SLEEPING for 15 s ****");
delay(1000);
#else
// what do do in real time
#endif
}
}
void increment() // Really a decrement... shuts down the motor when the counter gets to less than zero
{
#ifdef DEBUG_ON_SERIAL
Serial.print("**** Interupt 1 **** Cups left to feed: ");
#endif
delay(50);
--motorRunning;
if (motorRunning < 0)
digitalWrite(MOTOR_PIN, LOW);
#ifdef DEBUG_ON_SERIAL
Serial.println(motorRunning);
#endif
}
void interuptFeedNow() // Really a decrement... shuts down the motor when the counter gets to less than zero
{
#ifdef DEBUG_ON_SERIAL
Serial.print("**** Interupt 2 ****");
#endif
delay(50);
digitalWrite(MOTOR_PIN, HIGH);
motorRunning = feedAmount;
increment();
#ifdef DEBUG_ON_SERIAL
Serial.println();
#endif
}
#ifdef DEBUG_ON_SERIAL
void printTime()
{
Serial.print(String(rtc.hour()) + ":"); // Print hour
if (rtc.minute() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.print(String(rtc.minute()) + ":"); // Print minute
if (rtc.second() < 10)
Serial.print('0'); // Print leading '0' for second
Serial.print(String(rtc.second())); // Print second
if (rtc.is12Hour()) // If we're in 12-hour mode
{
// Use rtc.pm() to read the AM/PM state of the hour
if (rtc.pm()) Serial.print(" PM"); // Returns true if PM
else Serial.print(" AM");
}
Serial.print(" | ");
// Few options for printing the day, pick one:
Serial.print(rtc.dayStr()); // Print day string
//Serial.print(rtc.dayC()); // Print day character
//Serial.print(rtc.day()); // Print day integer (1-7, Sun-Sat)
Serial.print(" - ");
Serial.print(String(rtc.month()) + "/" + // Print month
String(rtc.date()) + "/"); // Print date
Serial.print(String(rtc.year())); // Print year
Serial.print(" .. ");
Serial.print(timeTillNextFeeding);
Serial.println();
}
void printVars()
{
Serial.print("-> ");
Serial.print(String(feedTime.getH()) + ":");
if (feedTime.getM() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.print(String(feedTime.getM())); // Print minute
Serial.print(" | ");
Serial.print(String(currTime.getH()) + ":");
if (currTime.getM() < 10)
Serial.print('0'); // Print leading '0' for minute
Serial.println(String(currTime.getM())); // Print minute
}
#endif