#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include "RTClib.h"
// Wokwi simulation settings
#define SIMULATE_RTC true
// Device configuration
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo feederServo;
RTC_DS3231 rtc;
// Pin definitions
const int SERVO_PIN = 23;
const int BUTTON_PIN = 18;
const int LED_PIN = 19;
const int BUZZER_PIN = 5;
// Feeding settings
const int FEEDING_ANGLE = 90;
const int FEEDING_DURATION = 2000; // ms
const int FEEDING_TIMES[] = {8, 12, 18}; // 8AM, 12PM, 6PM
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// Variables
bool feedingInProgress = false;
unsigned long lastFeedTime = 0;
int lastFeedHour = -1;
void setup() {
Serial.begin(115200);
// Initialize components
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
feederServo.attach(SERVO_PIN);
feederServo.write(0);
lcd.init();
lcd.backlight();
// Initialize RTC
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
#if SIMULATE_RTC
// Set RTC to current time (for simulation)
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
#endif
// Connect to WiFi
WiFi.begin(ssid, password);
lcd.print("Connecting WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
lcd.clear();
lcd.print("WiFi connected");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP());
delay(2000);
lcd.clear();
}
void loop() {
DateTime now = rtc.now();
// Display current time
displayTime(now);
// Check scheduled feeding times
checkScheduledFeeding(now);
// Check manual feeding button
if (digitalRead(BUTTON_PIN) == LOW && !feedingInProgress) {
manualFeed();
}
delay(1000);
}
void displayTime(DateTime now) {
lcd.setCursor(0, 0);
lcd.print("Time: ");
if (now.hour() < 10) lcd.print("0");
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute());
lcd.print(":");
if (now.second() < 10) lcd.print("0");
lcd.print(now.second());
lcd.setCursor(0, 1);
lcd.print("Last feed: ");
if (lastFeedHour != -1) {
lcd.print(lastFeedHour);
lcd.print(":00");
} else {
lcd.print("Never");
}
}
void checkScheduledFeeding(DateTime now) {
for (int i = 0; i < sizeof(FEEDING_TIMES)/sizeof(FEEDING_TIMES[0]); i++) {
if (now.hour() == FEEDING_TIMES[i] && now.minute() == 0 &&
now.second() < 5 && lastFeedHour != now.hour()) {
scheduledFeed();
lastFeedHour = now.hour();
}
}
}
void scheduledFeed() {
lcd.clear();
lcd.print("Scheduled Feeding");
feedPet();
}
void manualFeed() {
lcd.clear();
lcd.print("Manual Feeding");
feedPet();
}
void feedPet() {
feedingInProgress = true;
digitalWrite(LED_PIN, HIGH);
tone(BUZZER_PIN, 1000, 500);
// Dispense food
feederServo.write(FEEDING_ANGLE);
delay(FEEDING_DURATION);
feederServo.write(0);
digitalWrite(LED_PIN, LOW);
lastFeedTime = millis();
feedingInProgress = false;
delay(1000);
lcd.clear();
}