PIR Sensor for Fish Tank Feeding Reminder

Project Overview

This project creates a smart feeding reminder for your aquarium. When you approach the fish tank, the system checks if it’s time to feed and plays a voice reminder if needed. It also tracks the last feeding time and prevents overfeeding.

Difficulty: Beginner
Estimated time: 1-2 hours
Estimated cost: $20-30

How It Works

A PIR sensor detects when someone approaches the fish tank. The ESP32 checks the current time against a feeding schedule. If it’s within the feeding window and the last feeding was more than 8 hours ago, it plays a voice reminder. A button can be pressed to mark feeding as done.

Materials Needed

  • ESP32 or Arduino (1)
  • HC-SR501 PIR sensor (1)
  • DFPlayer Mini MP3 module (1)
  • MicroSD card (with feeding reminder audio)
  • Small speaker (3W)
  • Push button (to mark feeding done)
  • LEDs (optional, for status)
  • Resistors (220Ω)
  • Jumper wires
  • Power supply (5V 1A)

Circuit Diagram

Connection Table

Arduino Code

// Fish Tank Feeding Reminder
#include <WiFi.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <time.h>

SoftwareSerial mySoftwareSerial(16, 17);
DFRobotDFPlayerMini myDFPlayer;

const int pirPin = 4;
const int buttonPin = 5;
const int greenLedPin = 2;
const int redLedPin = 15;

// RTC via NTP
const char* ntpServer = "pool.ntp.org";
const long gmtOffset = 0;
const int daylightOffset = 0;

// Feeding schedule (hour, minute)
struct FeedingTime {
  int hour;
  int minute;
};
FeedingTime feedTimes[] = {
  {8, 0},   // 8:00 AM
  {18, 0}   // 6:00 PM
};
const int numFeedTimes = 2;

// State variables
unsigned long lastFeedTime = 0;
bool fedToday[2] = {false, false};
unsigned long lastReminderTime = 0;
const unsigned long reminderCooldown = 3600000; // 1 hour

void setup() {
  Serial.begin(115200);
  
  pinMode(pirPin, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(greenLedPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  
  digitalWrite(greenLedPin, LOW);
  digitalWrite(redLedPin, LOW);
  
  // Connect to Wi-Fi for time
  WiFi.begin("YourSSID", "YourPassword");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  configTime(gmtOffset, daylightOffset, ntpServer);
  
  // Initialize DFPlayer
  mySoftwareSerial.begin(9600);
  if (!myDFPlayer.begin(mySoftwareSerial)) {
    Serial.println("DFPlayer error");
  }
  myDFPlayer.volume(20);
  
  Serial.println("Fish Tank Feeder Ready");
  delay(30000); // PIR warm-up
}

bool isTimeToFeed(int currentHour, int currentMinute, int feedHour, int feedMinute) {
  // Check if within 30-minute window after feeding time
  int currentMinutes = currentHour * 60 + currentMinute;
  int feedMinutes = feedHour * 60 + feedMinute;
  return (currentMinutes >= feedMinutes && currentMinutes < feedMinutes + 30);
}

void markFed(int feedIndex) {
  fedToday[feedIndex] = true;
  lastFeedTime = millis();
  digitalWrite(greenLedPin, HIGH);
  myDFPlayer.play(3); // "Thank you!" message
  delay(2000);
  digitalWrite(greenLedPin, LOW);
}

void playReminder(int feedIndex) {
  if (feedIndex == 0) {
    myDFPlayer.play(1); // "Time to feed the fish"
  } else {
    myDFPlayer.play(2); // "Evening feeding time"
  }
  digitalWrite(redLedPin, HIGH);
  delay(2000);
  digitalWrite(redLedPin, LOW);
}

void resetDaily() {
  // Reset feeding flags at midnight
  struct tm timeinfo;
  if (getLocalTime(&timeinfo)) {
    if (timeinfo.tm_hour == 0 && timeinfo.tm_min == 0) {
      for (int i = 0; i < numFeedTimes; i++) {
        fedToday[i] = false;
      }
      Serial.println("Daily flags reset");
    }
  }
}

void loop() {
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo)) return;
  
  resetDaily();
  
  bool motion = digitalRead(pirPin) == HIGH;
  bool buttonPressed = digitalRead(buttonPin) == LOW;
  
  if (buttonPressed) {
    delay(50);
    if (digitalRead(buttonPin) == LOW) {
      // Manual feed button - find current feeding time
      for (int i = 0; i < numFeedTimes; i++) {
        if (isTimeToFeed(timeinfo.tm_hour, timeinfo.tm_min, 
                         feedTimes[i].hour, feedTimes[i].minute)) {
          markFed(i);
          break;
        }
      }
      while (digitalRead(buttonPin) == LOW) delay(10);
    }
  }
  
  if (motion && (millis() - lastReminderTime > reminderCooldown)) {
    // Check each feeding time
    for (int i = 0; i < numFeedTimes; i++) {
      if (isTimeToFeed(timeinfo.tm_hour, timeinfo.tm_min, 
                       feedTimes[i].hour, feedTimes[i].minute) && !fedToday[i]) {
        lastReminderTime = millis();
        playReminder(i);
        break;
      }
    }
  }
  
  delay(100);
}

Voice Prompt Files

Create MP3 files on SD card (folder "01"):

  • 001.mp3: "It's time to feed the fish. Please give them some food."
  • 002.mp3: "Evening feeding time. Don't forget to feed your fish."
  • 003.mp3: "Thank you for feeding the fish. They appreciate it!"

Installation Steps

  1. Mount PIR sensor: Place near fish tank, angled to detect approach.
  2. Position speaker: Place where reminder can be heard clearly.
  3. Mount button: Place near fish tank for easy access after feeding.
  4. Assemble electronics: Enclose ESP32 and DFPlayer in small box.
  5. Set feeding times: Adjust feedTimes array in code to match your schedule.
  6. Test: Approach tank at feeding time, verify reminder plays.

Project Extensions

  • Automatic feeder: Add servo to dispense food automatically.
  • Wi-Fi dashboard: View feeding history on web page.
  • Mobile notifications: Send push notification when feeding is missed.
  • Water temperature: Add DS18B20 to monitor tank temperature.
  • LED lighting: Add LED strip to simulate sunrise/sunset.

Troubleshooting

  • No reminder: Check Wi-Fi connection (for time). Verify feeding times in code.
  • No audio: Check DFPlayer wiring and SD card files.
  • False triggers: Adjust PIR sensitivity. Ensure not facing windows.
  • Time incorrect: Ensure ESP32 has Wi-Fi to sync time. Add backup RTC module for reliability.

Conclusion

This fish tank feeding reminder ensures your aquatic pets are fed on schedule, even when you're busy. With voice reminders, you'll never forget feeding time again.

Leave a Reply

Your email address will not be published. Required fields are marked *

Component Pin ESP32 Pin
PIR Sensor OUT GPIO 4 DFPlayer Mini TX GPIO 16 DFPlayer Mini RX GPIO 17 Push Button One side GPIO 5 Push Button Other side GND Green LED Anode GPIO 2 Red LED Anode GPIO 15