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:
    • cyclePhase 0: dispensing (servo deschis 1 secundă)
    • cyclePhase 1: closing (servo închis instantaneu)
  • 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

  • Am comandat Kit Plusivo Microcontroller Starter de la Optimus Digital si senzorul pentru detectarea obstacolelor

29.04.2025

  • Am comandat niste breadboarduri pentru proiect si am facut rost de un display de la un prieten ce avea mai multe displayuri disponibile

30.04.2025

  • Am creat proiectul “Dispensor de Mancare Multipurpose” folosind PlatformIO. Oficial, pot spune ca am inceput sa lucrez la proiect

05.05.2025

  • Am cumparat fire tata-tata si fire mama-tata pentru proiect

07.05.2025

  • Am inceput sa testez la laboratorul de PM functionalitatea fiecarui component. La display au fost niste probleme, dar le-am rezolvat acasa

08.05.2025

  • Incep sa scriu logica de cod pentru fiecare functionalitate in parte (cel putin pentru display si servo-motor)

11.05.2025

  • Primul “prototip” al proiectului este gata. Are implementata o versiune simplificata a codului actual

  • Il ducem la un unchiul meu si imi spune ca trebuie folosite alte butoane decat cele venite din kit. Are un kit intreg de butoane ce erau folosite la borduri de avioane. Aleg acest buton pentru proiect. Este primul lucru pe care il sudez in acest proiect.

12.05.2025

  • Mai iau 2 mini breadboarduri, dupa ce imi dau seama ca nu ar incapea un breadboard mare in proiectul nostru
  • Conectez intregul proiect pe 3 breadboarduri

14.05.2025

  • Prezint partea de hardware a proiectului. Servo-motorul nu mergea bine, nu stiam de ce :((

17.05.2025

  • Mergem din nou la unchiul meu, sa punem componentele intr-o cutie de prim ajutor. Vopsim capacul cutiei cu vopsea. Se usuca repede
  • Folosesc o carioca pentru a marca gaurile si folosesc o bormasina pentru a face gaurile
  • Am folosit o pila ca sa mai finisam din gauri (in special cea de la display si portul USB)
  • Am sudat si celelalte 2 butoane si am acoperit pinii cu banda adeziva
  • Rezultatul final, dupa 4 ore de munca (si dupa inca o jumatate de ora sa reconectez firele la componente):

21.05.2025

  • Prezint partea software la laboratorul de PM. Imi dau seama de ce nu mergea servo-motorul (trebuia sa le conectez direct la placuta)

23.05.2025

  • Evrika! Stiu cum sa fac trapa. Trapa va functiona ca o solnita. Facem trapa dintr-o bucata circulara de plastic
  • Ne dam seama ca nu avem cum sa atasam servo-motorul de un recipient cu palnie (folosim un recipient standard, in care stau cereale)

25.05.2025

  • Cumparam un raft de plastic de la Dedeman, mergem pentru ultima data la unchiul meu, mai fac doua gauri in spatele raftului ca sa prind cutia de raft, dupa fac gauri si pentru cutie si pentru recipient.
  • Atasam servo-motorul in recipient
  • Rezultatul final dupa inca vreo 3 ore de munca:

26.05.2025

  • Imi dau seama ca proiectul mai are doua probleme mari: detectarea distantei si modul cum dadea mancarea
  • La detectarea distantei, mi-am dat repede seama de ce nu mergea bine: emitorul era blocat de perete si detecta la o distanta mult mai mica (bormasina strikes again)
  • La modul cu mancarea, mi-am dat seama ca cel mai usor mod de a da de mancare este de a face cicluri rapide de open si close la servo-motor, in asa fel incat sa dea destula mancare pe fiecare categorie (de 5 ori la LOW, de 10 ori la MED si de 15 ori la HIGH)
  • Rezultatul final dupa 2 ore de retusuri: un client fericit

27.05.2025

  • Am facut pagina de Github a proiectului si am modificat putin pagina de OCW
  • Am adaugat acest jurnal, ca si amintire a acestei perioade intense

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

Timpul petrecut:

  • ~25 de ore - scris si retusat codul
  • 10 ore - testarea componentelor, asamblarea proiectului si orice retusuri la proiect
  • 6 ore - scrierea acestei pagini + crearea a unei scheme de tip bloc si a unei scheme electrice
  • 1 ora - creacrea paginii de Github
pm/prj2025/vstoica/andrei_vlad.racolta.1748384437.txt.gz · Last modified: 2025/05/28 01:20 by andrei_vlad.racolta
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0