#include <Wire.h>
#include <RTClib.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
// Instâncias
RTC_DS1307 rtc;
Servo servoMotor;
LiquidCrystal_I2C lcd(0x27, 20, 4); // Endereço padrão do LCD I2C para 20x4
// Configurações do sistema
const int incButtonPin = 2; // Botão para incrementar valores
const int navButtonPin = 3; // Botão para navegar
const int confirmButtonPin = 4; // Botão para confirmar
const int cancelButtonPin = 5; // Botão para cancelar
const int servoPin = 9;
// Variáveis
int currentMenu = 0; // 0: Apresentação, 1: Hora atual, 2: Alimentação 1, 3: Alimentação 2, 4: Alimentação 3
int selectedOption = 0; // Opção selecionada dentro de um menu (0 = horas, 1 = minutos)
bool adjusting = false; // Indica se está ajustando valores
unsigned long lastButtonPress = 0; // Para debounce
const unsigned long debounceDelay = 300; // Tempo para debounce
int feedingTimes[3][2] = { {8, 0}, {12, 0}, {18, 0} }; // Horários das alimentações (hh:mm)
bool feedingTriggered[3] = { false, false, false }; // Indica se a alimentação já foi acionada para o dia
void setup() {
pinMode(incButtonPin, INPUT_PULLUP);
pinMode(navButtonPin, INPUT_PULLUP);
pinMode(confirmButtonPin, INPUT_PULLUP);
pinMode(cancelButtonPin, INPUT_PULLUP);
servoMotor.attach(servoPin);
if (!rtc.begin()) {
Serial.println("RTC não encontrado!");
while (1);
}
if (!rtc.isrunning()) {
Serial.println("RTC não está funcionando, configurando...");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
servoMotor.write(0);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 1);
lcd.print("***Inicializando:***");
delay(2000);
lcd.clear();
Serial.begin(9600);
carregarHorarios();
exibirApresentacao();
}
void loop() {
// Leitura dos botões com debounce
if (digitalRead(navButtonPin) == LOW && millis() - lastButtonPress > debounceDelay) {
lastButtonPress = millis();
if (adjusting) {
selectedOption = (selectedOption + 1) % 2; // Alterna entre horas (0) e minutos (1)
} else {
currentMenu = (currentMenu + 1) % 5;
}
atualizarMenu();
}
if (digitalRead(confirmButtonPin) == LOW && millis() - lastButtonPress > debounceDelay) {
lastButtonPress = millis();
if (currentMenu > 1) {
adjusting = !adjusting; // Alterna o estado de ajuste
if (!adjusting) {
salvarHorarios(); // Salva os horários na EEPROM ao sair do ajuste
}
atualizarMenu();
}
}
if (digitalRead(incButtonPin) == LOW && millis() - lastButtonPress > debounceDelay) {
lastButtonPress = millis();
if (adjusting) {
if (currentMenu > 1) {
feedingTimes[currentMenu - 2][selectedOption]++;
if (selectedOption == 0 && feedingTimes[currentMenu - 2][selectedOption] >= 24)
feedingTimes[currentMenu - 2][selectedOption] = 0;
if (selectedOption == 1 && feedingTimes[currentMenu - 2][selectedOption] >= 60)
feedingTimes[currentMenu - 2][selectedOption] = 0;
}
atualizarMenu();
}
}
if (digitalRead(cancelButtonPin) == LOW && millis() - lastButtonPress > debounceDelay) {
lastButtonPress = millis();
if (adjusting) {
adjusting = false; // Sai do modo de ajuste
atualizarMenu();
}
}
verificarAlimentacao();
}
void atualizarMenu() {
lcd.clear();
switch (currentMenu) {
case 0:
exibirApresentacao();
break;
case 1:
exibirHoraAtual();
break;
case 2:
case 3:
case 4:
exibirMenuAlimentacao(currentMenu - 1);
break;
}
}
void exibirApresentacao() {
lcd.setCursor(0, 0);
lcd.print(" Edy Eletronica ");
lcd.setCursor(0, 1);
lcd.print(" Bem-vindo! ");
lcd.setCursor(0, 2);
lcd.print( "Use os botoes para ");
lcd.setCursor(0, 3);
lcd.print(" navegar nos menus. ");
}
void exibirHoraAtual() {
DateTime now = rtc.now();
lcd.setCursor(0, 0);
lcd.print(" Hora Atual ");
lcd.setCursor(0, 2);
lcd.print("Data: ");
lcd.print(now.day());
lcd.print("/");
lcd.print(now.month());
lcd.print("/");
lcd.print(now.year());
lcd.setCursor(0, 3);
lcd.print("Hora: ");
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10) lcd.print("0");
lcd.print(now.minute());
}
void exibirMenuAlimentacao(int index) {
lcd.setCursor(0, 0);
lcd.print("Ajuste Alimentacao ");
lcd.print(index);
if (adjusting) {
lcd.setCursor(0, 1);
lcd.print("Horario:");
lcd.setCursor(9, 1);
lcd.print(feedingTimes[index - 1][0]); // Hora
lcd.print(":");
if (feedingTimes[index - 1][1] < 10) lcd.print("0");
lcd.print(feedingTimes[index - 1][1]); // Minutos
lcd.setCursor(0, 2);
if (selectedOption == 0) {
lcd.print("Ajustando: Hora");
} else {
lcd.print("Ajustando: Minuto");
}
} else {
lcd.setCursor(0, 1);
lcd.print(" Horario Ajustado: ");
lcd.setCursor(8, 2);
lcd.print(feedingTimes[index - 1][0]);
lcd.print(":");
if (feedingTimes[index - 1][1] < 10) lcd.print("0");
lcd.print(feedingTimes[index - 1][1]);
lcd.setCursor(0, 3);
lcd.print("Aperte OK P/ Editar");
}
}
void verificarAlimentacao() {
DateTime now = rtc.now();
for (int i = 0; i < 3; i++) {
if (now.hour() == feedingTimes[i][0] && now.minute() == feedingTimes[i][1]) {
if (!feedingTriggered[i]) {
acionarServo();
feedingTriggered[i] = true; // Garante que só executa uma vez por horário
}
} else {
feedingTriggered[i] = false; // Reseta o gatilho após o minuto passar
}
}
}
void acionarServo() {
servoMotor.write(90); // Abre o compartimento de alimentação
delay(3000); // Aguarda 3 segundos
servoMotor.write(0); // Fecha o compartimento
}
void salvarHorarios() {
for (int i = 0; i < 3; i++) {
EEPROM.write(i * 2, feedingTimes[i][0]); // Salva hora
EEPROM.write(i * 2 + 1, feedingTimes[i][1]); // Salva minuto
}
}
void carregarHorarios() {
for (int i = 0; i < 3; i++) {
feedingTimes[i][0] = EEPROM.read(i * 2); // Lê hora da EEPROM
feedingTimes[i][1] = EEPROM.read(i * 2 + 1); // Lê minuto da EEPROM
// Validação dos dados lidos
if (feedingTimes[i][0] >= 24) feedingTimes[i][0] = 0;
if (feedingTimes[i][1] >= 60) feedingTimes[i][1] = 0;
}
}