Created
April 18, 2019 14:51
Fat Pet Feeder battery button version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Servo.h> | |
#include <LowPower.h> | |
#include <EventManager.h> | |
#include <ThreeWire.h> | |
#include <RtcDS1302.h> | |
#define EI_NOTINT0 | |
#define EI_NOTINT1 | |
#define EI_ARDUINO_INTERRUPTED_PIN | |
#include <EnableInterrupt.h> | |
#define minute 60 | |
#define hour 3600 | |
#define timerDelta 10000 | |
#define servoPin 9 | |
#define servoPowerPin 10 | |
#define buttonDispensePin 7 | |
#define buttonMinusPin 6 | |
#define buttonPlusPin 8 | |
#define buttonPin 5 | |
#define ledPin 13 | |
#define limit10m 2 | |
#define limit24h 6 | |
#define minMoveTime 130 | |
#define minServing 300 | |
EventManager eventManager; | |
Servo servo; | |
ThreeWire myWire(A1,A2,A0); // DAT, CLK, RST | |
RtcDS1302<ThreeWire> Rtc(myWire); | |
int servingTime = 800; // 1000 – 9g, 2000 – 18g, 3000 – 27g, 3500 – 31g, 4000 - 36g | |
int jerkPeriod = 800; // 1000/1000 – 9g, 1000/500 – 7g, 1400/700 – 12g | |
int servingDelta = 150; | |
int times10m = 0; | |
int times24h = 0; | |
uint32_t lastFeeding=0; | |
void setup() | |
{ | |
pinMode(buttonDispensePin, INPUT_PULLUP); | |
pinMode(buttonMinusPin, INPUT_PULLUP); | |
pinMode(buttonPlusPin, INPUT_PULLUP); | |
pinMode(buttonPin, INPUT_PULLUP); | |
pinMode(servoPowerPin, OUTPUT); | |
pinMode(ledPin, OUTPUT); | |
digitalWrite(ledPin, LOW); | |
servoDetach(); | |
enableInterrupt(buttonPin, interruptHandler, FALLING); | |
eventManager.addListener( buttonPin, buttonListener ); | |
Serial.begin(9600); | |
setupTime(); | |
buzz(); | |
} | |
void setupTime() | |
{ | |
Rtc.Begin(); | |
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); | |
Serial.print("Compiled: "); | |
printDateTime(compiled); | |
Serial.println(); | |
Serial.print("RTC: "); | |
RtcDateTime now = Rtc.GetDateTime(); | |
printDateTime(now); | |
Serial.println(); | |
if (Rtc.GetIsWriteProtected()) | |
{ | |
Serial.println("RTC was write protected, enabling writing now"); | |
Rtc.SetIsWriteProtected(false); | |
} | |
if (!Rtc.GetIsRunning()) | |
{ | |
Serial.println("RTC was not actively running, starting now"); | |
Rtc.SetIsRunning(true); | |
} | |
if (now < compiled) | |
{ | |
Serial.println("RTC is older than compile time! (Updating DateTime)"); | |
Rtc.SetDateTime(compiled); | |
} | |
else if (now > compiled) | |
{ | |
Serial.println("RTC is newer than compile time. (this is expected)"); | |
} | |
else if (now == compiled) | |
{ | |
Serial.println("RTC is the same as compile time! (not expected but all is fine)"); | |
} | |
} | |
#define countof(a) (sizeof(a) / sizeof(a[0])) | |
void printDateTime(const RtcDateTime& dt) | |
{ | |
char datestring[20]; | |
snprintf_P(datestring, | |
countof(datestring), | |
PSTR("%02u/%02u/%04u %02u:%02u:%02u"), | |
dt.Month(), | |
dt.Day(), | |
dt.Year(), | |
dt.Hour(), | |
dt.Minute(), | |
dt.Second() ); | |
Serial.print(datestring); | |
} | |
void interruptHandler() | |
{ | |
eventManager.queueEvent(arduinoInterruptedPin, 0); | |
} | |
void buttonListener(int, int) | |
{ | |
RtcDateTime nowT = Rtc.GetDateTime(); | |
// Serial.print("Event: "); | |
// printDateTime(nowT); | |
// Serial.println(); | |
uint32_t now = nowT.TotalSeconds(); | |
if(now-lastFeeding < 5) | |
return; // Simple debouncer | |
if(now-lastFeeding > 10*minute) | |
times10m = 0; | |
if(now-lastFeeding > 24*hour) | |
times24h = 0; | |
bool allowed = times10m<limit10m && times24h<limit24h; | |
// Serial.print(times10m); | |
// Serial.print(" "); | |
// Serial.print(times24h); | |
// Serial.print(" "); | |
// Serial.print(now); | |
// Serial.print(" "); | |
// Serial.println(allowed); | |
if(!allowed) return; | |
lastFeeding = now; | |
dispense(servingTime); | |
times10m++; | |
times24h++; | |
} | |
void loop() { | |
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_ON); | |
eventManager.processAllEvents(); | |
} | |
void servoAttach() | |
{ | |
servo.attach(servoPin); | |
digitalWrite(servoPowerPin, HIGH); | |
delay(200); | |
} | |
void servoDetach() | |
{ | |
pinMode(servoPin, INPUT); | |
digitalWrite(servoPowerPin, LOW); | |
} | |
void dispense(int dispenseTime) | |
{ | |
servoAttach(); | |
for(;dispenseTime>0;dispenseTime-=jerkPeriod){ | |
servo.write(100); | |
delay(dispenseTime>=jerkPeriod ? jerkPeriod : dispenseTime%1000); | |
jerk(); | |
} | |
stop(); | |
} | |
void jerk() | |
{ | |
servo.write(0); | |
delay(minMoveTime); | |
servo.write(180); | |
delay(minMoveTime); | |
} | |
void stop() | |
{ | |
servo.write(90); | |
delay(100); | |
servoDetach(); | |
} | |
void buzz() | |
{ | |
servoAttach(); | |
servo.write(0); | |
delay(50); | |
jerk(); | |
jerk(); | |
stop(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment