Treat dispencer (with a twist)

April 14, 2025
Description
This special treat dispencer lets your pet enjoy they most beloved treats, but to a certain point. if they will eat too much, they will have to wait, and if they will still try to get more, they will recieve an amount of water to their face.
The project logic:
- Every time the button is pushed - a treat is being dispenced.
- If the button was pressed 3 times without a 5 minute difference between the presses - Overfed mode turns on.
- while in overfed mode, a red led is blinking. If the button is pressed while overfed mode Is on, instead of treat dispence - water will be sprayed.
- After 30 after overfed mode started, it will end, and pushing the button will dispence treats again.
component | amount |
Arduino uno | 1 |
Small 5v pump | 1 |
Servo motor | 1 |
Red led | 2 |
push button | 1 |
330 ohm resistor | 1 |
Software:
i used Fusion360 to desing this project.
Code:
code was written in the arduino IDE software, the code:
#include <Servo.h>
// Pins
const int leverPin = 7; // Lever sensor (button/microswitch)
const int ledPin = 8; // Red LED (changed to pin 8)
const int waterPin = 5; // Water spray relay
const int servoPin = 6; // Treat dispenser servo
// Timing settings
const unsigned long treatWindow = 300000; // 5 minutes in ms
const unsigned long cooldownTime = 1800000; // 30 minutes in ms (adjust up to 60 min if needed)
const unsigned long sprayDuration = 150; // 0.2 second spray
const unsigned long leverDebounce = 500; // ms to prevent double-counting pulls
const unsigned long ledBlinkInterval = 500; // Blink interval for LED in ms
Servo treatServo;
// Tracking variables
int treatCount = 0;
unsigned long firstTreatTime = 0;
bool overfed = false;
unsigned long overfedStart = 0;
unsigned long lastBlinkTime = 0;
bool ledState = false;
void setup() {
pinMode(leverPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
pinMode(waterPin, OUTPUT);
treatServo.attach(servoPin);
treatServo.write(78);
digitalWrite(ledPin, LOW);
digitalWrite(waterPin, LOW);
Serial.begin(9600);
}
void loop() {
// Read lever state (active LOW if using pullup)
if (digitalRead(leverPin) == LOW) {
delay(leverDebounce); // debounce
handleLeverPull();
while (digitalRead(leverPin) == LOW); // wait until released
}
// Handle blinking LED while overfed
if (overfed) {
if (millis() - lastBlinkTime >= ledBlinkInterval) {
ledState = !ledState;
digitalWrite(ledPin, ledState ? HIGH : LOW);
lastBlinkTime = millis();
}
}
// Reset overfed state after cooldown
if (overfed && millis() - overfedStart >= cooldownTime) {
overfed = false;
treatCount = 0;
digitalWrite(ledPin, LOW);
ledState = false;
Serial.println("Cooldown complete. System reset.");
}
}
void handleLeverPull() {
Serial.println("Lever pulled");
// If in overfed state, spray water
if (overfed) {
Serial.println("Overfed: spraying water");
sprayWater();
return;
}
// Dispense treat
dispenseTreat();
unsigned long now = millis();
// If first treat, start the window
if (treatCount == 0) {
firstTreatTime = now;
treatCount = 1;
Serial.println("First treat");
} else if (now - firstTreatTime <= treatWindow) {
treatCount++;
Serial.print("Treat count in window: ");
Serial.println(treatCount);
if (treatCount >= 3) {
overfed = true;
overfedStart = now;
lastBlinkTime = now;
digitalWrite(ledPin, HIGH);
ledState = true;
Serial.println("Overfed state activated. Red LED blinking.");
}
} else {
// Outside of time window, reset count
firstTreatTime = now;
treatCount = 1;
Serial.println("Time window expired. Restarting count.");
}
}
void dispenseTreat() {
treatServo.write(115); // Open position (adjust as needed)
delay(500);
treatServo.write(75); // Close position
Serial.println("Treat dispensed.");
}
void sprayWater() {
digitalWrite(waterPin, HIGH);
delay(sprayDuration);
digitalWrite(waterPin, LOW);
Serial.println("Water spray complete.");
}
3D print:
- I used PLA this project, for all the parts.
- infill was around 15% every print.
- support changes according to the part.