Placa de dezvoltare ESP32 acționează ca unitate de control principală. Aceasta gestionează toate componentele periferice, inclusiv servo motorul pentru distribuirea hranei, afișajul OLED, buzzer-ul, LED-urile de stare și butoanele de control. De asemenea, comunică cu un modul RTC (ceas în timp real) pentru programarea automată a hrănirii și poate salva evenimentele pe un card SD pentru jurnalizare.
Comunicarea cu afișajul OLED și modulul RTC se face prin protocolul I²C, utilizând pinii hardware ai ESP32. În plus, un senzor de vibrații este utilizat pentru a detecta eventualele mișcări sau lovituri ale hrănitorului, ca formă de interacțiune sau alertă.
Funcționalitate generală:
Componente de control și interacțiune:
Alimentare:
Dispozitivul este alimentat dintr-un modul cu 2 baterii Li-Ion 18650 conectate în paralel, printr-un modul TP4056 pentru încărcare și protecție. Tensiunea este stabilizată la 5V cu ajutorul unui modul step-up/down YL-46, care alimentează ESP32 și restul componentelor.
Funcționare:
La pornire, ESP32 inițializează ceasul RTC. La fiecare interval prestabilit sau la apăsarea butonului de hrănire, servo-ul distribuie hrană. După fiecare activare, contorul se incrementează și LED-urile se actualizează. Feedback-ul este oferit atât vizual (LED), cât și auditiv (buzzer). Afișajul OLED arată starea curentă a sistemului și istoricul recent al hrănirilor.
Totodată, interfața web integrată permite monitorizarea obiceiurilor alimentare ale pisicii, oferind o experiență completă și accesibilă de la distanță.
1. Servomotor SG90
Legături: * Semnal (portocaliu) → GPIO 26, pin PWM hardware, potrivit pentru controlul unui servo, nu interferează cu alte periferice * VCC (roșu) → VIN (5V), servo-ul necesită alimentare de 5V * GND (negru/maro) → GND
2. Afișaj OLED 0.96” (I2C)
Legături: * SDA → GPIO 21, pin I2C hardware standard * SCL → GPIO 22, pin I2C hardware standard * VCC → 3.3V, tensiunea recomandată pentru modulul OLED * GND → GND
3. RTC DS3231
Legături: * SDA → GPIO 21, partajat cu OLED, I2C permite mai multe dispozitive pe aceiași pini * SCL → GPIO 22 * VCC → 3.3V, compatibil cu ESP32 * GND → GND
4. Modul microSD (SPI)
Legături: * CS → GPIO 5, pin digital liber utilizat ca chip select * MOSI → GPIO 23, pin SPI hardware standard * MISO → GPIO 19, pin SPI hardware standard * SCK → GPIO 18, pin SPI hardware standard * VCC → 3.3V, unele module SD nu au regulator intern * GND → GND
5. Senzor de vibrații SW-420
Legături: * DO → GPIO 32, pin digital liber, bun pentru citiri simple * VCC → 3.3V, compatibil cu ESP32 * GND → GND
6. Buzzer activ
Legături: * + → GPIO 27, pin digital folosit pentru semnal simplu HIGH * – → GND
7. Butoane
Buton hrănire: * Un capăt → GND * Celălalt → GPIO 4, pin digital liber, configurat cu INPUT_PULLUP Buton resetare: * Un capăt → GND * Celălalt → GPIO 33, pin digital cu INPUT_PULLUP, stabil în această configurație Buton log: * Un capăt → GND * Celălalt → GPIO 34, pin digital citit direct (nu suportă INPUT_PULLUP), verificat cu gpio_get_level()
8. LED-uri (indicatori)
Verde: * Anod → GPIO 12, pin digital simplu * Catod → GND prin rezistor Galben: * Anod → GPIO 13, pin digital simplu * Catod → GND prin rezistor Roșu: * Anod → GPIO 14, pin digital simplu * Catod → GND prin rezistor
1. Mediul de dezvoltare
Aplicatia este dezvoltata in Arduino IDE , compatibil cu platforma ESP32 DevKit v1, utilizata in proiect. Codul este scris in limbajul C++, iar incarcarea pe placa se realizeaza prin port USB. Serial Monitor-ul este folosit pentru debug si afisarea mesajelor in timpul executiei.
2. Librarii si surse third-party utilizate
Biblioteca | Scop |
Wire.h | Comunicare I2C cu RTC si display OLED |
ESP32Servo.h | Controlul servo motorului prin PWM specific ESP32 |
RTClib.h | Gestionarea modulului RTC DS3231 (ora si data) |
Adafruit\_SSD1306.h | Afisare text pe display OLED monocrom |
SPI.h | Comunicare SPI cu modulul microSD |
SD.h | Scriere si citire fisiere pe cardul microSD |
driver/gpio.h | Acces direct la registrele GPIO pentru citire/scriere eficienta |
3. Algoritmi si structuri implementate
Codul foloseste o structura bazata pe evenimente (interuperi hardware) si verificari ciclice in bucla principala loop(). Bucla loop() verifica constant:
Hrana este eliberata automat la orele 08:00, 14:00 si 18:00, pe baza valorii returnate de modulul RTC.
Hrana poate fi eliberata si manual, prin apasarea butonului conectat pe GPIO4. Acesta genereaza o intrerupere externa configurata cu attachInterrupt(), care seteaza un flag ce este tratat in loop().
Evenimentele importante sunt inregistrate pe cardul microSD, in fisierul log.txt. Acestea includ:
Display-ul OLED conectat prin I2C afiseaza ora curenta si, temporar, mesaje precum “Contor resetat” sau ultimul eveniment logat.
LED-urile indica nivelul estimativ al rezervorului de mancare:
Servo motorul este controlat prin PWM pentru a elibera mancarea. Buzzer-ul este controlat prin registre (GPIO.out_w1ts / GPIO.out_w1tc) si emite un sunet scurt la fiecare hranire.
Senzorul de vibratii este verificat periodic. Daca se detecteaza vibratii (nivel LOW) si a trecut timpul de ignorare (10 secunde dupa hranire), se considera ca pisica a mancat si se logheaza evenimentul.
4. Surse si functii implementate
Functie / Structura | Descriere |
`setup()` | Initializeaza componentele hardware: servo, RTC, SD, OLED, GPIO, |
LED-uri, si seteaza intreruperile | |
`loop()` | Executa periodic verificarile: ora curenta, butoane, senzori, etc. |
`onFeedInterrupt()` | Functie ISR pentru tratarea intreruperii de la butonul de hranire |
`feed(String source)` | Porneste servo-ul, suna buzzer-ul, logheaza actiunea si actualizeaza |
contorul si LED-urile | |
`resetFeed()` | Reseteaza contorul de hraniri, actualizeaza LED-urile si logheaza |
`updateLEDs()` | Activeaza LED-ul corespunzator in functie de numarul de hraniri |
`displayTime(DateTime)` | Afiseaza ora curenta pe OLED sau mesajul temporar de reset |
`logSimple(String)` | Scrie o intrare in `log.txt` si verifica scrierea pe cardul SD |
`showLastLog()` | Citeste si afiseaza ultima intrare din `log.txt` pe display OLED |
`printSDLog()` | Afiseaza in consola toate intrarile din `log.txt` |
Notiuni din laborator
1. GPIO (driver/gpio.h – pentru control pini digitali)
gpio_set_direction((gpio_num_t)BUTTON_FEED, GPIO_MODE_INPUT); gpio_set_pull_mode((gpio_num_t)BUTTON_FEED, GPIO_PULLUP_ONLY); gpio_set_direction((gpio_num_t)BUTTON_RESET, GPIO_MODE_INPUT); gpio_set_pull_mode((gpio_num_t)BUTTON_RESET, GPIO_PULLUP_ONLY); gpio_set_direction((gpio_num_t)BUTTON_LOG, GPIO_MODE_INPUT); gpio_set_direction((gpio_num_t)BUZZER_PIN, GPIO_MODE_OUTPUT); gpio_set_direction((gpio_num_t)VIBRATION_PIN, GPIO_MODE_INPUT); if (!gpio_get_level((gpio_num_t)BUTTON_RESET)) { resetFeed(); delay(300); } if (gpio_get_level((gpio_num_t)BUTTON_LOG)) { showLastLog(); delay(300); } if (millis() > vibrationIgnoreUntil && !gpio_get_level((gpio_num_t)VIBRATION_PIN)) { // log event }
2. PWM (ESP32Servo.h – control servo motor)
servo.setPeriodHertz(50); servo.attach(SERVO_PIN, 500, 2400); servo.write(180); delay(500); servo.write(0);
3. SPI (SPI.h + SD.h – pentru cardul microSD)
#include <SPI.h> #include <SD.h> #define SD_CS 5 if (!SD.begin(SD_CS)) Serial.println("Eroare card SD!"); File f = SD.open("/log.txt", FILE_APPEND); if (f) { f.println(logEntry); f.close(); } File fRead = SD.open("/log.txt"); if (fRead) { while (fRead.available()) { lastLine = fRead.readStringUntil('\n'); } fRead.close(); }
4. I2C (Wire.h – folosit implicit pentru RTC și OLED)
#include <Wire.h> #include <RTClib.h> #include <Adafruit_SSD1306.h> RTC_DS3231 rtc; Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); if (!rtc.begin()) Serial.println("Eroare RTC!"); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("Eroare OLED!"); DateTime now = rtc.now(); display.clearDisplay(); display.setCursor(...); display.println(...); display.display();
5. Intreruperi (hardware interrupt pe butonul de hranire)
volatile bool feedInterrupt = false; void IRAM_ATTR onFeedInterrupt() { feedInterrupt = true; } attachInterrupt(digitalPinToInterrupt(BUTTON_FEED), onFeedInterrupt, FALLING); // in loop(): noInterrupts(); bool shouldFeed = feedInterrupt; feedInterrupt = false; interrupts(); if (shouldFeed) { feed("manuala"); }
07.05.2025 - Alegerea temei
07.05.2025 - Introducere si Descriere generală si Schema Bloc
15.05.2025 - Completarea secțiunii Hardware Design si Schema electrica
18.05.2025 - Scrierea codului