// Fish Feeder
// By _Hash_
// Function: Feeds my fish at regular intervals (2hrs) and when motion is detected (fish swims close when its hungry).
// Additional Function: Logs the exact time and date of feeding and displays live time and status in a LCD.
// Working: PIR Motion Sensor detects fish near feeding spot. Servo motor dispenses small quantity of food for 5 seconds.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Servo.h>
const int servoPin = 9;
const int pirSensorPin = 8;
Servo myservo; // Servo object
RTC_DS1307 RTC; // RTC object
LiquidCrystal_I2C lcd(0x27, 20, 4); // LCD object (address: 0x27, 20x4 display)
int motionDetected = 0;
int feedingInterval = 2 * 60 * 60; // 2 hours in seconds
unsigned long lastFeedingTime = 0; // Last feeding timestamp
void setup() {
Serial.begin(9600); // initialize serial communication
myservo.attach(servoPin); // Attach servo motor to pin 9
pinMode(pirSensorPin, INPUT); // Set PIR pin as input
// Initialize RTC
if (!RTC.begin()) {
Serial.println("RTC not found.");
while (1); // if RTC not found stops
}
lcd.init(); // Initialize the LCD
lcd.backlight(); // Turn on LCD backlight
lcd.setCursor(0, 0);
lcd.print("Fish Feeder Ready");
delay(2000); // Show initial message
}
void loop() {
motionDetected = digitalRead(pirSensorPin); // Read PIR sensor value
displayTime(); // Display live time on LCD
dispenseFood(); // Check and dispense food
delay(1000); // 1-second delay
}
void displayTime() {
DateTime now = RTC.now(); // Get current time from RTC
lcd.clear(); // Clear previous display
lcd.setCursor(0, 0);
lcd.print("Time:");
lcd.setCursor(6, 0);
lcd.print(now.hour());
lcd.print(":");
lcd.print(now.minute());
lcd.print(":");
lcd.print(now.second());
lcd.setCursor(0, 1);
lcd.print("Feeding Log Active");
}
void dispenseFood() {
DateTime now = RTC.now(); // get current time from RTC
unsigned long currentTime = now.unixtime(); // get in seconds
// Check if feeding interval has passed or motion is detected
if ((currentTime - lastFeedingTime >= feedingInterval) || motionDetected == HIGH) {
myservo.write(90); // Open food dispenser
delay(5000); // Dispense food for 5 seconds
myservo.write(0); // Close food dispenser
lastFeedingTime = currentTime; // Update last feeding time
// Log feeding the to Console
Serial.print("Fed at: ");
if (now.hour() < 10) Serial.print("0");
Serial.print(now.hour());
Serial.print(":");
if (now.minute() < 10) Serial.print("0");
Serial.print(now.minute());
Serial.print(":");
if (now.second() < 10) Serial.print("0");
Serial.println(now.second());
// Log feeding time on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Fed at:");
lcd.setCursor(0, 1);
lcd.print(now.hour());
lcd.print(":");
lcd.print(now.minute());
lcd.print(":");
lcd.print(now.second());
delay(2000);
}
}