#include "HX711.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Stepper.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define DOUT 11
#define CLK 10
#define BT1 A0
#define BT2 A1
#define BT3 A2
#define BT4 A3
#define STEPS 2048
Stepper stepper(STEPS, 6, 8, 7, 9);
HX711 scale;
RTC_DS1307 rtc;
int mode = 0;
int setHour = 0;
int setMinute = 0;
int setgrams = 0;
bool alarmTriggered = false;
unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;
unsigned long lastDebounceTime3 = 0;
unsigned long lastDebounceTime4 = 0;
const unsigned long debounceDelay = 300;
unsigned long lastLCDUpdate = 0;
const unsigned long lcdUpdateInterval = 1000;
bool lcdOn = false;
DateTime now;
void feedMotor(int grams) {
int stepsPerGram = 20;
int steps = grams * stepsPerGram;
stepper.setSpeed(10);
stepper.step(steps);
delay(200);
}
void print_hour() {
lcd.setCursor(0, 3);
lcd.print(" ");
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.print(" ");
}
void setup() {
scale.begin(DOUT, CLK);
pinMode(BT1, INPUT_PULLUP);
pinMode(BT2, INPUT_PULLUP);
pinMode(BT3, INPUT_PULLUP);
pinMode(BT4, INPUT_PULLUP);
if (!rtc.begin()) {
lcd.setCursor(0, 0);
lcd.print("RTC Error");
while (1);
}
}
void loop() {
now = rtc.now();
if (digitalRead(BT4) == LOW && (millis() - lastDebounceTime4) > debounceDelay) {
lcdOn = !lcdOn;
if (lcdOn) {
lcd.init();
lcd.backlight();
lcd.clear();
} else {
lcd.noBacklight();
lcd.clear();
}
lastDebounceTime4 = millis();
}
if (!lcdOn) {
delay(100);
return;
}
if (digitalRead(BT1) == LOW && millis() - lastDebounceTime1 > debounceDelay) {
mode = (mode + 1) % 4;
lcd.clear();
lastDebounceTime1 = millis();
}
if (digitalRead(BT2) == LOW && millis() - lastDebounceTime2 > debounceDelay) {
if (mode == 1) {
setHour = (setHour + 1) % 24;
} else if (mode == 2) {
setMinute = (setMinute + 1) % 60;
} else if (mode == 3) {
setgrams += 1;
}
lastDebounceTime2 = millis();
}
if (digitalRead(BT3) == LOW && millis() - lastDebounceTime3 > debounceDelay) {
if (mode == 1) {
setHour = (setHour - 1 + 24) % 24;
} else if (mode == 2) {
setMinute = (setMinute - 1 + 60) % 60;
} else if (mode == 3) {
setgrams--;
if (setgrams < 0) setgrams = 0;
}
lastDebounceTime3 = millis();
}
if (millis() - lastLCDUpdate > lcdUpdateInterval) {
lastLCDUpdate = millis();
if (scale.is_ready()) {
float weight = scale.get_units() * 2.380952380952381;
int intWeight = int(weight);
int percent = (intWeight * 2.0) / 100;
if (mode == 0) {
lcd.setCursor(0, 0);
if (intWeight == 0) {
lcd.print("Please refill! ");
} else if (intWeight < 500) {
lcd.print("Below 500g ");
} else {
lcd.print("Weight: ");
lcd.print(weight / 1000.0, 2);
lcd.print("kg ");
}
lcd.setCursor(0, 1);
lcd.print("Grams: ");
lcd.print(intWeight);
lcd.print(" g ");
lcd.setCursor(0, 2);
lcd.print("Level: ");
lcd.print(percent);
lcd.print("% ");
print_hour();
if (now.hour() == setHour && now.minute() == setMinute) {
if (!alarmTriggered) {
feedMotor(setgrams);
alarmTriggered = true;
}
} else {
alarmTriggered = false;
}
} else if (mode == 1) {
lcd.setCursor(0, 0);
lcd.print("Set Feed Hour: ");
lcd.setCursor(0, 1);
lcd.print("Hour: ");
if (setHour < 10) lcd.print("0");
lcd.print(setHour);
lcd.setCursor(0, 2);
lcd.print("Press -> confirm");
print_hour();
} else if (mode == 2) {
lcd.setCursor(0, 0);
lcd.print("Set Feed Minute: ");
lcd.setCursor(0, 1);
lcd.print("Minute: ");
if (setMinute < 10) lcd.print("0");
lcd.print(setMinute);
lcd.setCursor(0, 2);
lcd.print("Press -> confirm");
print_hour();
} else if (mode == 3) {
lcd.setCursor(0, 0);
lcd.print("Set Food Amount: ");
lcd.setCursor(0, 1);
lcd.print(setgrams);
lcd.print(" g ");
lcd.setCursor(0, 2);
lcd.print("Press -> confirm");
print_hour();
}
} else {
lcd.setCursor(0, 0);
lcd.print("HX711 Error ");
lcd.setCursor(0, 1);
lcd.print("Check wiring ");
}
}
}