#include <LiquidCrystal_I2C.h>
#include "EncButton.h"
#include <EEPROM.h>
#include <RTClib.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Клик - внеочередная кормёжка
// Удержание - задаём размер порции
const byte feedTime[][2] = {
{7, 0}, // часы, минуты. НЕ НАЧИНАТЬ ЧИСЛО С НУЛЯ
{12, 0},
{17, 0},
{21, 0},
};
#define EE_RESET 12 // любое число 0-255. Измени, чтобы сбросить настройки и обновить время
#define FEED_SPEED 3000 // задержка между шагами мотора (мкс)
#define BTN_PIN 4 // кнопка
#define STEPS_FRW 18 // шаги вперёд
#define STEPS_BKW 10 // шаги назад
const byte drvPins[] = {3, 4, 5, 6}; // драйвер (фазаА1, фазаА2, фазаВ1, фазаВ2)
#define ECHO_PIN 22
#define TRIG_PIN 23
RTC_DS1307 rtc;
EncButton<BTN_PIN> btn;
int feedAmount = 100;
void setup() {
Serial.begin(9600);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
lcd.init(); // initialize the lcd
lcd.backlight();
Wire.begin(); // Инициализация I2C для ESP32
rtc.begin();
lcd.print("OK");
Serial.println("LCD ok");
EEPROM.begin(512); // Инициализация EEPROM для ESP32 (размер можно изменить)
if (EEPROM.read(0) != EE_RESET) { // первый запуск
EEPROM.write(0, EE_RESET);
EEPROM.put(1, feedAmount);
EEPROM.commit();
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
EEPROM.get(1, feedAmount);
for (byte i = 0; i < 4; i++) pinMode(drvPins[i], OUTPUT); // пины выходы
}
void loop() {
static uint32_t tmr = 0;
if (millis() - tmr > 500) { // два раза в секунду
static byte prevMin = 0;
tmr = millis();
DateTime now = rtc.now();
if (prevMin != now.minute()) {
prevMin = now.minute();
for (byte i = 0; i < sizeof(feedTime) / 2; i++) // для всего расписания
if (feedTime[i][0] == now.hour() && feedTime[i][1] == now.minute()) // пора кормить
feed();
}
}
btn.tick();
if (btn.isClick()) {
feed();
}
if (btn.isHold()) {
int newAmount = 0;
while (btn.isHold()) {
btn.tick();
oneRev();
newAmount++;
}
feedAmount = newAmount;
EEPROM.put(1, feedAmount);
EEPROM.commit();
}
}
float readDistanceCM() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
int duration = pulseIn(ECHO_PIN, HIGH);
lcd.setCursor(0,0);
lcd.print("Inches");
return duration * 0.034 / 2;
}
void feed() {
for (int i = 0; i < feedAmount; i++) oneRev(); // крутим на количество feedAmount
for (byte i = 0; i < 4; i++) digitalWrite(drvPins[i], 0); // выключаем ток на мотор
readDistanceCM();
}
void oneRev() {
static uint16_t val = 0;
for (byte i = 0; i < STEPS_FRW; i++) runMotor(val++);
for (byte i = 0; i < STEPS_BKW; i++) runMotor(val--);
}
void runMotor(int thisStep) {
static const byte steps[] = {0b1010, 0b0110, 0b0101, 0b1001};
for (byte i = 0; i < 4; i++)
digitalWrite(drvPins[i], bitRead(steps[thisStep & 0b11], i));
delayMicroseconds(FEED_SPEED);
}