Descrierea sumara a modulelor si a modului de interactiune
1. Descrierea modulelor hardware:
2. Modul de interactiune (Fluxul de functionare):
Sistemul interactioneaza printr-o bucla continua de tip Achizitie date → Procesare → Actiune. Pachetul de baterii alimenteaza intregul ansamblu. In timpul rularii, senzorii colecteaza date din mediu si le transmit catre microcontroler sub forma de impulsuri sau niveluri de tensiune. ATmega328P analizeaza aceste intrari si, pe baza algoritmului de decizie, trimite semnale de control (PWM si directie logica) catre driverul L298N. Driverul actioneaza ca un amplificator, cupland motoarele la curentul bateriei pentru a executa deplasarea. In paralel, microcontrolerul raporteaza constant starea sistemului (baterie, distante, decizii de viraj) prin intermediul modulului Bluetooth.
Pentru realizarea acestui proiect, a fost utilizată următoarea configurație hardware, axată pe un echilibru între eficiența energetică și acuratețea senzorilor:
Pentru a vizualiza interconectarea componentelor, se va consulta schema electrică de ansamblu de mai jos. *(Notă tehnică: Alimentarea logicii de 5V a microcontrolerului se face prin pinul de +5V al modulului L298N, acesta coborând tensiunea de 6V a bateriei printr-un regulator integrat).*
Tabelul Conexiunilor Hardware (Pinout Map): Pentru interfațarea senzorilor cu perifericele interne ale ATmega328P s-a utilizat următoarea mapare:
| Modul Extern | Pin Modul | Conexiune ATmega328P | Rol / Periferic Utilizat |
|---|---|---|---|
| Modul HC-05 | TX | PB0 | Comunicație Serială (USART) |
| Modul HC-05 | RX | PB1 | Comunicație Serială (USART) |
| L298N (Driver) | ENA | PD5 | Control Viteză Motor Stânga (PWM Hardware) |
| L298N (Driver) | ENB | PD6 | Control Viteză Motor Dreapta (PWM Hardware) |
| L298N (Driver) | IN1, IN2 | PD4, PD7 | Control Direcție Motor Stânga (GPIO) |
| L298N (Driver) | IN3, IN4 | PB2, PB3 | Control Direcție Motor Dreapta (GPIO) |
| Divizor Tensiune | Vout (Intersecție) | PC0 (A0) | Monitorizare nivel baterie (ADC) |
| TCRT5000 | A0 | PC1 (A1) | Detecție analogică margine / podea (ADC) |
| HC-SR04 (Față) | Trig, Echo | PD2, PD3 | Măsurare distanță față (GPIO) |
| HC-SR04 (Stânga) | Trig, Echo | PC2 (A2), PC3 (A3) | Măsurare distanță stânga (ADC folosit ca GPIO) |
| HC-SR04 (Dreapta) | Trig, Echo | PC4 (A4), PC5 (A5) | Măsurare distanță dreapta (ADC folosit ca GPIO) |
Pentru interfațarea corectă a perifericelor s-au analizat următoarele semnale cheie:
A. Diagrama de semnal pentru senzorii HC-SR04 (Time-of-Flight) Microcontrolerul emite un impuls logic HIGH de 10µs pe pinul Trigger. Senzorul răspunde cu un semnal HIGH pe pinul Echo, a cărui durată este proporțională cu distanța. Această durată este măsurată hardware folosind întreruperile externe și un Timer.
B. Diagrama semnalului PWM pentru L298N Controlul locomoției și aplicarea metodei de “Soft Start” se realizează prin modularea lățimii impulsurilor (PWM) aplicate pe pinii ENA și ENB ai driverului, dictând astfel cuplul și viteza motoarelor.
Pentru scrierea, compilarea si incarcarea codului pe microcontroler (ATmega328P), am renuntat la clasicul Arduino IDE in favoarea Visual Studio Code (VS Code) impreuna cu extensia PlatformIO.
Aceasta alegere ne-a oferit un flux de lucru mult mai profesional. PlatformIO permite impartirea codului in mai multe fisiere (cum ar fi separarea logicii de Bluetooth in hc05_comm.hpp), ofera un sistem de autocomplete mult mai destept si gestioneaza automat compilarea fara sa ne incurcam in setari ascunse. Desi folosim framework-ul Arduino pentru usurinta, mediul VSC + PlatformIO ne-a permis sa scriem un cod mult mai curat si modular.
Ca sa pastram o viteza de reactie maxima a robotului si sa nu incarcam memoria procesorului cu cod inutil, am decis sa limitam la extrem folosirea librariilor externe. Astfel, am folosit doar:
millis(), analogRead(), digitalWrite()).main.cpp.Nu am folosit librarii terte (gen NewPing) pentru senzorii ultrasonici tocmai pentru a putea controla manual timpii de asteptare si a preveni blocarea procesorului.
Programul a fost gandit pe o arhitectura 100% non-blocanta. Asta inseamna ca nu exista nicio instructiune de tip delay() in bucla principala, permitand robotului sa citeasca senzorii, sa conduca motoarele si sa trimita telemetrie pe telefon in acelasi timp.
Logica principala se bazeaza pe doua mari concepte:
stareRobot) care ii dicteaza ce face in orice moment:istoricDecizii[10]. Acesta memoreaza ultimele 10 directii alese. Cand robotul da de un obstacol, algoritmul alege directia de viraj pe baza senzorilor laterali, dar timpul de rotire este generat aleatoriu (intre 400 si 900 milisecunde). Daca memoria detecteaza ca robotul face prea multe viraje in aceeasi directie sau se loveste de prea multe ori intr-un timp scurt, declanseaza o masura de urgenta: sterge memoria si executa o rotatie foarte lunga, tot aleatorie, pentru a evada din acel colt al camerei.Pentru a pune in practica algoritmii de mai sus, codul a fost impartit in cateva functii vitale si puternic optimizate hardware:
setup() si loop(): In setup() initiem pinii si generam un randomSeed() citind “zgomotul” de pe un pin analogic liber (A6), asigurandu-ne ca deciziile robotului sunt diferite la fiecare pornire. In loop() se ruleaza Masina de Stari si se trimite telemetria spre telefon (voltaj, distanta) la fiecare 1000 de milisecunde, calculat via millis().getDistanta(): Aceasta este functia senzorilor ultrasonici. Secretul ei sta in parametrul de timeout modificat la 3500 microsecunde. Astfel, procesorul nu asteapta dupa ecouri venite de la 4 metri distanta, ci inchide ascultarea la aprox. 60 cm. Asta a eliberat procesorul si a reparat complet lag-ul de pe comenzile Bluetooth.citesteVccReal(): Functia care masoara voltajul real al bateriei LiPo folosind referinta interna de 1.1V a cipului. Aici am folosit tehnica de “Double Dummy Read” (citire in gol a pinilor analogici) pentru a da timp condensatorului intern din microcontroler sa se goleasca, evitand astfel combinarea valorilor de la senzorul de podea cu cele de la baterie.salveazaDecizie(): Functia care gestioneaza memoria circulara de 10 pozitii, adaugand noul viraj (Stanga sau Dreapta) in vector si mentinand logica de evadare alerta.mergiInainteIncet(), rotesteStangaIncet() etc.): Setari rapide de stare logica (HIGH/LOW) si PWM pe pinii L298N pentru a controla puntea H fara a aglomera bucla principala.Proiectul ne-a demonstrat ca o placuta simpla cu microcontroler ATmega328P poate sa gestioneze multi senzori si sa ia decizii destul de destepte, daca codul este scris eficient si curat.
Cea mai mare lectie invatata a fost legata de functiile blocante. Pentru un robot care trebuie sa reactioneze in timp real si sa asculte si de comenzi prin Bluetooth, instructiunile de tip delay() sau timeout-urile prea mari la senzori sunt complet interzise. De asemenea, am vazut ca limitarile fizice ale cipului (cum ar fi un singur voltmetru intern impartit la toti pinii) pot fi pacalite usor prin trucuri software, cum sunt citirile duble.
Din punct de vedere al traseului, am realizat ca daca lasam robotul sa faca doar viraje fixe (de exemplu, mereu la 90 de grade), acesta va ramane blocat rapid intr-o bucla infinita pe acelasi traseu. Introducerea algoritmului cu timpi de viraj aleatori si stocarea istoricului de decizii au fost cheia pentru a obtine un comportament mult mai inteligent si o acoperire foarte buna a intregii camere.
13.05.2025 - Au fost lipite cu cositor firele care duc la motoare si la divizorul de tensiune. Dovada ca etapa hardware a fost indeplinita este transmiterea pe serial Bluetooth a citiriilor senzorilor, si rotirea motoarelor.
Link test roti: https://drive.google.com/file/d/1JDcxumcGRbAPboI4evX0atG_J3Q3IFuz/view?usp=drivesdk
20.05.2026 - Am rezolvat problema uriasa de lag de pe Bluetooth, din cauza careia trebuia sa apasam de multe ori pe telefon ca sa prindem comanda de Start sau Stop. Problema era de la pulseIn(), care bloca procesorul timp de 25 de milisecunde pentru fiecare senzor ultrasonic cand robotul era in spatiu deschis. Am scazut timeout-ul la 3500 microsecunde (suficient pentru vreo 60cm in fata), iar acum aplicatia de pe telefon raspunde instant, din prima.
22.05.2026 - Am reparat citirea divizorului de tensiune pentru baterie. Dupa ce am scos delay-urile din cod, telemetria incepuse sa arate aiurea o valoare blocata in jur de 3V, desi la multimetru aveam 8.4V. Bug-ul era cauzat de schimbarile extrem de rapide de pe multiplexorul ADC intre senzorul de podea (A1) si baterie (A0). Am rezolvat prin adaugarea unei “citiri in gol” (dummy read) si a unei micro-pauze de stabilizare hardware, curatand condensatorul intern al ADC-ului. Acum tensiunea afisata este stabila si corecta.
24.05.2026 - Am imbunatatit radical algoritmul de acoperire a camerei. Am renuntat la timpii ficsi de viraj care invarteau robotul in aceleasi zone si am trecut pe timpi de rotire complet aleatori (intre 400ms si 900ms). In plus, am activat si memoria ultimelor 10 decizii salvate intr-un vector. Daca robotul se loveste des in acelasi loc sau face aceeasi intoarcere la nesfarsit, sistemul isi da seama ca e blocat, reseteaza istoricul si forteaza o manevra lunga de evadare (U-Turn) ca sa iasa din colturi. Link Demo: https://drive.google.com/file/d/1l5hyUvKaTeUjokgSLg2P7t9O1l73x-RN/view?usp=drivesdk
===== Resurse Software =====