This is an old revision of the document!
Dispensor de Mancare Multipurpose
Racolta Andrei-Vlad, 334CD
Introducere
Acest dispenser de mâncare detectează când un animal/o persoană se află la distanța potrivită și da mâncare într-o cantitate controlată prin deschiderea repetată a unei trape acționate de un servo-motor.
Scopul acestui dispozitiv este de a da mâncare la cerere, fiind util pentru persoane ce au animale de companie sau persoane ce vor să aibă un “snack machine” în casă.
Ideea dispensorului a venit de la faptul că am animale de companie în casă, în cazul meu o pisică și un câine, și am gândit acest proiect pentru a nu mai trebui să mă ridic de fiecare dată de la birou, că să îi dau pisicii mele de mâncare. De asemenea, acesta poate fi folosit că și un dispozitiv ce dă mâncare (arahide, bomboane, covrigei etc.) pentru cine are nevoie sau la evenimente ca petreceri.
Utilitatea acestui proiect vine din două perspective:
pentru mine, este un mod util de a implementa idei și concepte de la laboratorul de Proiectarea Microprocesoarelor pe un proiect ce îmi poate fi util și cu mult timp după facultate
pentru alți, e o soluție utilă pentru a da mâncare animalelor de companie sau pentru a ține snacksuri într-un recipient distractiv și unic
Descriere generala
Hardware Design
Proiectul dispune de următoarele componente:
1x Placă compatibilă cu Arduino Uno R3
1x Senzor infra-roșu de detectare a obstacolelor (Distanța: 2-180 cm)
1x Servo-Motor SG90 pentru mișcarea trapei
1x Display LCD I2C pentru a prezenta situația automatului
3x Butoane pentru a seta automatul
3x Breadboarduri
Cutie de prim ajutor (ce conține toate componentele de mai sus, cu excepția servo-motorului)
Recipient de plastic cu gaura (ce conține servo-motorul)
Trapa de plastic (de tip solniță)
Raft de plastic (de care sunt prinse cutia și recipientul)
Un suport de plastic pentru a prinde servo-motorul de recipient
Șuruburi și piulițe pentru prinderea componentelor (recipientul, cutia, componentele electronice, servo motorul)
Software Design
Mediu de dezvoltare
AVR-GCC cu toolchain standard pentru microcontrolere AVR
Compatibil cu Arduino IDE sau PlatformIO
Target: ATmega328P (Arduino Uno/Nano)
Biblioteci și surse 3rd-party folosite
avr/io.h - registre și definții hardware AVR
avr/interrupt.h - gestionare întreruperi
util/delay.h - funcții de întârziere precisă
stdint.h - tipuri de date standard
Implementare proprie (fără biblioteci externe)
Protocol I2C pentru comunicația cu LCD-ul
Control PWM manual pentru servomotor
Interfață UART pentru debugging
Algoritmi și structuri implementate
1. Structuri de date
typedef enum {
MODE_HUMAN = 0, // Mod pentru hrănirea umană (cu opțiune fără cooldown)
MODE_ANIMAL // Mod pentru hrănirea animale (cooldown obligatoriu)
} DispenseMode;
typedef enum {
FOOD_LOW = 0, // 5 cicluri de dispensare
FOOD_MEDIUM, // 10 cicluri de dispensare
FOOD_HIGH // 15 cicluri de dispensare
} FoodAmount;
// Setări cooldown pentru umani (în minute) - cu opțiunea NONE
const uint16_t humanCooldowns[] = {0, 5, 10, 15, 30, 45, 60};
#define HUMAN_COOLDOWN_COUNT 7
// Setări cooldown pentru animale (în minute) - fără opțiunea NONE
const uint16_t animalCooldowns[] = {30, 60, 120, 240, 480, 720};
#define ANIMAL_COOLDOWN_COUNT 6
// Configurare cicluri de dispensare
const uint8_t foodCycles[] = {5, 10, 15}; // Numărul de cicluri pentru LOW, MEDIUM, HIGH
const uint16_t dispenseTimes[] = {1000, 1000, 1000}; // Timp per ciclu în ms (1 secundă)
#define CYCLE_TIME 1000 // Timp per ciclu în ms
// Variabile globale de sistem
DispenseMode currentMode = MODE_HUMAN;
FoodAmount currentAmount = FOOD_LOW;
uint8_t cooldownIndex = 0;
uint8_t servoActive = 0;
uint8_t cooldownActive = 0;
uint8_t currentCycle = 0;
uint8_t totalCycles = 1;
uint8_t cyclePhase = 0; // 0 = dispensing (open), 1 = closing
2. Algoritmi de control îmbunătățiți
Sistem de dispensare multi-ciclu:
LOW: 5 cicluri × 1 secundă = 5 secunde totale
MEDIUM: 10 cicluri × 1 secundă = 10 secunde totale
HIGH: 15 cicluri × 1 secundă = 15 secunde totale
Pattern: open(1s) → close(instant) → open(1s) → close(instant)…
Control servo pentru SG90:
Unghi deschis la 90 de grade
Generare PWM manuală cu 10 repetiții pentru stabilitate
Închidere instantanee între cicluri pentru eficiență
Sistem de cooldown cu opțiune specială:
Pentru oameni: 0 (NONE), 5, 10, 15, 30, 45, 60 minute
Pentru animale: 30, 60, 120, 240, 480, 720 minute (fără opțiunea NONE)
Timer bazat pe bucla principală (increment la 10ms)
3. Arhitectura sistemului modernizată
Mașină de stări cu cicluri:
IDLE - sistem pregătit, afișează setări
MULTI-CYCLE DISPENSING - alternează între open/close cu progres afișat
COOLDOWN - sistem blocat pentru un interval de timp (vizibil pe LCD)
Interfață utilizator:
Button 1: Mode switching (HUMAN ↔ ANIMAL)
Button 2: Food amount (LOW → MED → HIGH → LOW…)
Button 3: Cooldown time (specific fiecărui mod)
LCD 16×2: Status real-time și progres operațiuni
Proximity sensor: Activare automată prin detectare obiect
Funcții și module implementate
Comunicație I2C
i2c_init() - configurare TWI la 100kHz
i2c_start(), i2c_stop(), i2c_write() - protocul I2C complet
lcd_send_i2c() - transmisie către LCD
Driver LCD cu I2C expander (HD44780)
lcd_init() - secvență de inițializare 4-bit
lcd_command(), lcd_write() - comenzi și date
lcd_print(), lcd_print_number() - funcții utilitare
lcd_set_cursor(), lcd_clear() - control cursor și display
Control servomotor SG90
servo_set_angle() - poziționare precisă 0-90°
Calibrare pentru SG90: optimizat pentru 5V
PWM manual: 20ms perioada, 1-2ms lățime puls
Stabilitate: 10 repetiții per comandă
Sistem multi-ciclu de dispensare
open_trap() - inițializează secvența de cicluri
Logică în bucla principală pentru gestionarea fazelor:
Progres LCD: actualizare în timp real “Cycle: X/Y”
Gestionare cooldown
Pentru MODE_HUMAN: opțiunea “0” = fără cooldown
Pentru MODE_ANIMAL: cooldown obligatoriu (minimum 30 min)
get_current_cooldown() - returnează timpul în funcție de mod
Afișare LCD: “No cooldown” sau “Cooldown: Xm”
Interfață utilizator
handle_buttons() - debouncing și edge detection
Reset automat: cooldown-ul se oprește la schimbarea modului
update_display() - afișare condiționată pe starea sistemului
Feedback UART: logging detaliat pentru debug
Detectare proximitate
check_proximity() - citire senzor cu pull-up intern
Edge detection: activare pe front descrescător (1→0)
Filtrare zgomot: prin variabila lastProximityState
Algoritm principal
// Bucla principală - gestionare completă sistem
while (1) {
handle_buttons(); // Procesează interfața utilizator
if (!cooldownActive && !servoActive) {
// Detectare proximitate doar când sistemul este gata
if (edge_detected) open_trap();
}
if (servoActive) {
// Cicluri de dispensare cu timing precis
if (cyclePhase == 0) { // Dispensing phase
if (time > 1_second) → close_servo, switch_to_closing
} else { // Closing phase
increment_cycle;
if (cycle <= total) → open_servo, restart_dispensing
else → finish_all_cycles
}
}
if (cooldownActive) {
// Countdown cu afișare progres
if (cooldown_expired) → system_ready
}
delay_ms(10); // Control rata execuție: 100Hz
}
Caracteristici ale sistemului
Flexibilitate operațională
Modul HUMAN: acces rapid fără cooldown pentru testare/demonstrații
Modul ANIMAL: control strict cu cooldown-uri lungi pentru programare
Comutare instantanee între moduri cu reset automat al stării
Performanță
Închidere instantanee între cicluri (fără întârzieri inutile)
Timer software eficient pentru operațiuni lungi
Gestionare precisă a resurselor fără întreruperi
Rata execuție: 100Hz pentru răspuns rapid
Siguranță și robustețe
Reset automat la schimbarea modurilor
Debouncing hardware și software pentru toate butoanele
Sistem fail-safe cu monitorizare UART continuă
Validare intrări și limitări hardware
Interfață completă
Feedback vizual: LCD cu progres în timp real
Monitoring remote: UART logging pentru toate operațiunile
Control intuitiv: 3 butoane pentru acces la toate funcțiile
Diagnosticare: mesaje detaliate pentru troubleshooting
Cod sursă
Jurnal
28.04.2025
29.04.2025
30.04.2025
05.05.2025
07.05.2025
08.05.2025
11.05.2025
Rezultate
Dispensorul este capabil sa dea mancare pentru pisica mea. Nu e perfect (se mai intampla ca trapa sa nu se miste la capacitate maxima daca e blocata o bobita pe sub ea), dar in principal:
senzorul functioneaza si se activeaza daca vede un obiect pe o raza de aproximativ 10 cm
displayul afiseaza ce e necesar (modul, cata mancare trebuie sa dea, cooldownul, arata x/y cicluri cand e pornit servo motorul)
butoanele functioneaza si interactioneaza perfect cu displayul si placuta