Acest proiect reprezintă implementarea practică a cunoștințelor acumulate la disciplina Proiectare cu Microprocesoare (PM). Scopul principal a fost dezvoltarea unui sistem embedded complex, mai exact un robot mobil autonom de tip Line Follower, echipat cu module periferice pentru detectarea obstacolelor și avertizare acustică, dar și cu un sistem independent de raportare a stării pe un ecran LCD.
Pentru a nu îngreuna bucla principală de control a robotului și pentru a evita latențele neplăcute induse de funcțiile de împrospătare a ecranului, am ales o abordare avansată: o arhitectură distribuită cu două microcontrollere independente (ATmega328P).
Prin acest montaj, am pus în practică direct tematicile studiate la laboratoarele de PM:
Pentru a asigura portabilitatea completă a robotului pe traseu, am proiectat o sursă de alimentare dintr-un pachet agregat de 8 baterii alcaline tip AA (fiecare având o tensiune nominală de 1.5V). Din punct de vedere structural, am folosit două adaptoare de plastic de câte 4 baterii, pe care le-am conectat electric în serie.
Calculul tensiunii totale de linie introduse în sistem: $$V_{in} = 8 \times 1.5\text{V} = 12\text{V}$$
Această magistrală principală de 12V alimentează direct terminalele de putere ale driverului de motoare L298N pentru a pune în mișcare motoarele de curent continuu.
Totuși, circuitele logice de control (atât placa Arduino Uno, cât și placa Arduino Nano și senzorii) au nevoie de o tensiune stabilă de 5V. Pentru a obține acest prag, am folosit regulatorul liniar de tensiune integrat pe modulul L298N (78M05). Acesta coboară cei 12V din baterii la 5V curați, pe care i-am distribuit în paralel către pinii de `5V` ai ambelor plăci Arduino.
Masele electrice (GND) de la adaptoarele de baterii, de la driverul L298N, de la Arduino Uno și de la Arduino Nano au fost unite într-un nod central de masă pentru a asigura un potențial de referință unitar de 0V.
⚠️ Regulă de Aur la Laborator (Siguranță): Pentru a evita distrugerea componentelor, deconectăm întotdeauna pachetul de baterii AA de pe robot atunci când conectăm cablurile USB la calculator pentru a încărca codul. Conflictul direct dintre alimentarea din USB și tensiunea debitată de regulatorul L298N poate arde porturile USB ale PC-ului sau cipurile de comunicare serială de pe plăcuțe.
Deoarece am separat sarcinile pe două microcontrollere diferite, organizarea pinilor a devenit mult mai curată și am eliminat riscul de coliziune a semnalelor.
Această placă se ocupă exclusiv de rularea algoritmului cinematic de urmărire a liniei, scanarea traseului prin ultrasunete și activarea alarmei în caz de urgență.
| Componentă Periferică | Pin Arduino Uno | Direcție (I/O) | Tip Semnal | Rolul în cadrul Robotului |
|---|---|---|---|---|
| Driver Motoare (L298N - ENA) | `D6` | OUTPUT | PWM | Control viteză Motor Stânga |
| Driver Motoare (L298N - ENB) | `D5` | OUTPUT | PWM | Control viteză Motor Dreapta |
| Driver Motoare (L298N - IN1) | `D7` | OUTPUT | Digital | Direcție Motor Stânga (Sens A) |
| Driver Motoare (L298N - IN2) | `D8` | OUTPUT | Digital | Direcție Motor Stânga (Sens B) |
| Driver Motoare (L298N - IN3) | `D9` | OUTPUT | Digital | Direcție Motor Dreapta (Sens A) |
| Driver Motoare (L298N - IN4) | `D10` | OUTPUT | Digital | Direcție Motor Dreapta (Sens B) |
| Senzor Infraroșu (IR Stânga) | `D12` | INPUT | Digital | Citire stare linie (0 = alb, 1 = negru) |
| Senzor Infraroșu (IR Dreapta) | `D11` | INPUT | Digital | Citire stare linie (0 = alb, 1 = negru) |
| Senzor Sonar (HC-SR04 - Trig) | `D3` | OUTPUT | Digital | Declanșare impuls ultrasonic (10 µs) |
| Senzor Sonar (HC-SR04 - Echo) | `D4` | INPUT | Digital | Captare timp zbor undă reflectată |
| Avertizor Acustic (Buzzer) | `D2` | OUTPUT | Digital | Activare alarmă sonoră (sirenă sacadată) |
Această placă secundară are un singur scop: preia textul și menține aprins ecranul LCD, rulând independent mașina de stări pentru mesaje fără a bloca resursele procesorului principal de pe Uno.
| Componentă Periferică | Pin Arduino Nano | Direcție (I/O) | Tip Semnal | Rolul în cadrul Afișajului |
|---|---|---|---|---|
| Ecran LCD 1602 (Pin 4 - RS) | `D12` | OUTPUT | Digital | Selecție regiștri (Data/Command) |
| Ecran LCD 1602 (Pin 6 - E) | `D11` | OUTPUT | Digital | Linie de Enable (Validare date) |
| Ecran LCD 1602 (Pins D4-D7) | `D5`, `D4`, `D3`, `D2` | OUTPUT | Digital | Magistrală tranzitorie de date (Mod 4 biți) |
| Ecran LCD 1602 (Pin 15 - BLA) | `D9` | OUTPUT | PWM | Controlul hardware al luminii de fundal |
Codul rulat pe placa Arduino Nano gestionează ecranul alfanumeric prin biblioteca `LiquidCrystal` în configurație de magistrală pe 4 biți (liniile de date inferioare D0-D3 ale ecranului rămân libere). Izolarea ecranului pe acest MCU ne permite să folosim instrucțiuni de tip `delay(2000)` pentru lizibilitatea textelor, lucru care pe o placă unică ar fi înghețat complet motoarele robotului pe pistă.
Pentru a asigura stabilitatea pixelilor și a elimina suprapunerile de caractere, am introdus o latență de 20 ms imediat după comanda `lcd.clear()`, oferind timp controllerului HD44780 să își reseteze regiștrii interni înainte de a primi un nou set de date.
#include <LiquidCrystal.h> // Inițializăm pinii ecranului în ordinea: RS, E, D4, D5, D6, D7 LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int pinLumina = 9; void setup() { pinMode(pinLumina, OUTPUT); // Aprindem lumina de fundal la maximum din semnalul PWM analogWrite(pinLumina, 255); lcd.begin(16, 2); lcd.clear(); delay(50); } void loop() { // Menținem intensitatea luminoasă activă analogWrite(pinLumina, 255); // --- Starea 1: Identificare Numar --- lcd.clear(); delay(20); lcd.setCursor(0, 0); lcd.print("BR 09 BIC BOSS"); lcd.setCursor(0, 1); lcd.print("BR 09 BIC BOSS"); delay(2000); // --- Starea 2: Evaluare Proiect --- lcd.clear(); delay(20); lcd.setCursor(0, 0); lcd.print("NOTA 10"); lcd.setCursor(0, 1); lcd.print("NOTA 10"); delay(2000); // --- Starea 3: Disciplina PM --- lcd.clear(); delay(20); lcd.setCursor(0, 0); lcd.print(" LINE FLW"); lcd.setCursor(0, 1); lcd.print(" PROIECT PM "); delay(2000); }
Placa Arduino Uno rulează algoritmul principal cu o frecvență ridicată de eșantionare. În cadrul buclei `loop()`, prioritatea absolută o are modulul de evitare a coliziunilor.
Funcția `citesteDistanta()` generează un trigger digital scurt de 10 microsecunde către senzorul HC-SR04, determinând emisia unui pachet de unde sonore la 40 kHz. Microcontrolerul contorizează durata pulsului întors pe pinul `Echo` cu ajutorul funcției `pulseIn()`. Distanța se calculează pe baza vitezei sunetului în aer ($\approx 0.0343\text{ cm/µs}$): $$distanta = \frac{durata \times 0.0343}{2}$$
Dacă distanța scade sub pragul critic de 20 cm, execuția codului de navigare este întreruptă forțat prin comanda `return;`. Robotul oprește punțile H și trece în starea de alertă, activând buzzerul într-o cadență de tip sirenă (100 ms pornit / 100 ms oprit). Când traseul este eliberat, robotul revine la citirea senzorilor infraroșu și corectează deplasarea pe linie folosind pinii de direcție ai driverului.
// Alocare pini driver motoare L298N const int ENA = 6; const int IN1 = 7; const int IN2 = 8; const int ENB = 5; const int IN3 = 9; const int IN4 = 10; // Alocare pini senzori optici reflectivi const int IRSensorLeft = 12; const int IRSensorRight = 11; // Alocare pini senzor ultrasonic si alarma acustica const int trigPin = 3; const int echoPin = 4; const int buzzerPin = 2; // Setare constante viteza prin factor de umplere PWM #define s 80 #define t 80 void setup() { pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(IRSensorLeft, INPUT); pinMode(IRSensorRight, INPUT); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(buzzerPin, OUTPUT); Serial.begin(9600); } void loop() { // 1. Prioritate Siguranta: Verificare obstacole long distanta = citesteDistanta(); if (distanta > 0 && distanta < 20) { stopMotors(); // Alarma sacadata de proximitate digitalWrite(buzzerPin, HIGH); delay(100); digitalWrite(buzzerPin, LOW); delay(100); return; // Blocam restul executiei din loop } else { digitalWrite(buzzerPin, LOW); } // 2. Algoritm urmarire linie neagra bool leftSensor = digitalRead(IRSensorLeft); bool rightSensor = digitalRead(IRSensorRight); if (leftSensor == HIGH && rightSensor == HIGH) { moveForward(); } else if (leftSensor == HIGH && rightSensor == LOW) { turnRight(); } else if (leftSensor == LOW && rightSensor == HIGH) { turnLeft(); } else { stopMotors(); } delay(50); } long citesteDistanta() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long durata = pulseIn(echoPin, HIGH, 30000); // Timeout la 30ms return durata * 0.034 / 2; } void moveForward() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); analogWrite(ENA, s); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENB, s); } void turnRight() { digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); analogWrite(ENA, t); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); analogWrite(ENB, 0); } void turnLeft() { digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); analogWrite(ENA, 0); digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); analogWrite(ENB, t); } void stopMotors() { digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); analogWrite(ENA, 0); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); analogWrite(ENB, 0); }
Pentru a asigura stabilitatea sistemului dual-MCU și a valida alegerea regulatorului hardware, am întocmit bilanțul energetic teoretic pe bara de alimentare de 5V în starea de sarcină maximă:
Calculul curentului cumulat pe magistrala de 5V: $$I_{total} = I_{uno} + I_{nano} + I_{logic\_lcd} + I_{backlight} + I_{sonar} + I_{ir} + I_{buzzer}$$ $$I_{total} = 45 + 30 + 1.1 + 100 + 15 + 20 + 15 = 226.1\text{ mA}$$
Regulatorul liniar intern (78M05) aflat pe driverul L298N reduce potențialul pachetului complet de baterii AA în serie ($12\text{V}$) la nivelul stabilizat de $5\text{V}$, preluând diferența de potențial și transformând-o în căldură. Puterea disipată ($P_d$) se determină cu formula studiată la curs:
$$P_d = (V_{in} - V_{out}) \times I_{total}$$
Înlocuind valorile parametrilor hardware folosiți în proiect: $$P_d = (12\text{V} - 5\text{V}) \times 0.2261\text{ A}$$ $$P_d = 7\text{V} \times 0.2261\text{ A} = 1.582\text{ W}$$
Valoarea de 1.582 W confirmă faptul că regulatorul în capsulă DPAK de pe placa driverului L298N lucrează în parametri siguri, fără risc de supraîncălzire critică sau intrare în protecție termică automată. Structurarea proiectului pe două microcontrollere oferă un avantaj major: izolarea completă a ecranului LCD garantează că zgomotul parazit inductiv generat de pornirea/oprirea motoarelor pe linia de alimentare nu va corupe datele trimise pe magistrala afișajului.