This shows you the differences between two versions of the page.
|
pm:prj2026:theodor_ioan.buliga:140548 [2026/05/04 13:08] alexandru.neagu1006 |
pm:prj2026:theodor_ioan.buliga:140548 [2026/05/26 19:37] (current) alexandru.neagu1006 [Arhiva] |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Telecomandă Universală Hibridă (IR & RF) ====== | + | ====== Telecomanda Universala Hibrida (IR & RF) ====== |
| ===== Introducere ===== | ===== Introducere ===== | ||
| - | Proiectul constă în realizarea unei telecomenzi universale capabile să învețe, să stocheze și să reproducă semnale de control în Infraroșu (IR) și Radiofrecvență (RF 433MHz). | + | Proiectul consta in realizarea unei **telecomenzi universale hibride**, capabila sa **invete, sa stocheze si sa reproduca** semnale de control atat in **Infrarosu (IR)**, cat si in **Radiofrecventa (RF 433 MHz)**. Dispozitivul este construit in jurul microcontrollerului **ATmega328P** (Arduino Nano), beneficiind de un ecran OLED pentru interfata grafica si un encoder rotativ pentru navigare. |
| - | * **Scop:** Consolidarea tuturor telecomenzilor din casă (TV, benzi LED, lustre, prize inteligente cu cod fix) într-un singur dispozitiv portabil. | + | * **Scop:** Consolidarea tuturor telecomenzilor din casa (TV, benzi LED, lustre, prize inteligente cu cod fix) intr-un singur dispozitiv portabil si usor de utilizat. |
| - | * **Ideea de plecare:** Nevoia de a simplifica interacțiunea cu diversele aparate electrocasnice care folosesc tehnologii de comunicare diferite. | + | * **Motivatie:** Nevoia practica de a elimina multitudinea de telecomenzi fizice care folosesc tehnologii de comunicare diferite si incompatibile intre ele (IR vs. RF). |
| - | * **Utilitate:** Oferă confort utilizatorului prin eliminarea multiplelor telecomenzi fizice și reprezintă un exercițiu de programare bare-metal (gestiune Timere, Întreruperi și protocol I2C). | + | * **Relevanta academica:** Proiectul reprezinta un exercitiu complet de programare **bare-metal** pe ATmega328P, acoperind: gestionarea **intreruperilor externe si PCINT**, configurarea **timerelor hardware** (Timer 0 si Timer 1), implementarea **protocolului I2C (TWI)** nativ si utilizarea **memoriei EEPROM** pentru persistenta datelor. |
| - | ===== Descriere generală ===== | + | ===== Descriere Generala ===== |
| - | Dispozitivul este construit în jurul microcontrollerului ATmega328P. Schema bloc cuprinde: | + | Sistemul este impartit in patru module functionale principale care interactioneaza cu unitatea centrala de procesare (ATmega328P): |
| - | * **Unitatea centrală:** Arduino Nano (ATmega328P). | + | |
| - | * **Module de recepție:** VS1838B (IR) și SYN480 (RF superheterodină) pentru captura semnalelor. | + | {{ :pm:prj2026:theodor_Ioan.buliga:schema_bloc_telecomanda.png?800 }} |
| - | * **Module de emisie:** LED IR (modulat la 38kHz) și SYN115 (RF) pentru transmisie. | + | |
| - | * **Interfață:** Ecran OLED 0.96" (afișare meniuri) și Rotary Encoder (navigare/selecție). | + | |
| - | * **Alimentare:** Acumulator Li-ion 3.7V, încărcător TP4056 și ridicător de tensiune MT3608 (5V). | + | **Flux de functionare:** |
| + | |||
| + | - La pornire, se afiseaza un ecran de start, apoi se intra in **Meniul Principal**. | ||
| + | - Utilizatorul navigheaza cu **encoderul rotativ** (sus/jos) si confirma cu **butonul PUSH**. | ||
| + | - **Butonul KEY** (al doilea buton) serveste drept "Inapoi" in orice meniu. | ||
| + | - Sistemul trece printr-o masina de stari finita (FSM) cu 8 stari distincte: ''MENU_MAIN'', ''MENU_LEARN'', ''MENU_LEARN_SLOT'', ''LEARN_WAITING'', ''LEARN_SUCCESS'', ''MENU_SEND_SLOT'', ''SENDING_CMD'', ''MENU_DELETE_SLOT''. | ||
| ===== Hardware Design ===== | ===== Hardware Design ===== | ||
| - | Listă de piese: | + | ==== Lista de Componente ==== |
| - | * Microcontroller: Arduino Nano (ATmega328P-AU, FT232) | + | |
| - | * Display: OLED 0.96 inch I2C (Controller SSD1306) | + | |
| - | * Navigare: Modul Encoder Rotativ KY-040 | + | |
| - | * Infraroșu: Receptor VS1838B, LED IR 5mm, Tranzistor NPN 2N2222 (amplificare semnal) | + | |
| - | * Radio: Set Emițător/Receptor 433MHz (SYN115 / SYN480) + Antene 17.3cm | + | |
| - | * Energie: Acumulator Li-ion 523450 (3.7V), Modul TP4056 (Micro-USB/Type-C), Modul Step-Up MT3608 | + | |
| - | Conexiuni principale: | + | ^ Componenta ^ Model / Specificatii ^ Rol in sistem ^ |
| - | * OLED: A4 (SDA), A5 (SCL) - Interfața I2C | + | | Microcontroller | Arduino Nano (ATmega328P-AU, 16 MHz, 5V) | Unitate centrala de procesare | |
| - | * Receptor IR: D2 (INT0) - Întrerupere externă | + | | Afisaj | OLED 0.96" I2C, Controller SSD1306, 128x64 px | Interfata vizuala / meniuri | |
| - | * Receptor RF: D3 (INT1) - Întrerupere externă | + | | Encoder rotativ | KY-040 (cu buton integrat) | Navigare meniuri + confirmare | |
| - | * Emițător IR: D9 (OC1A) - Ieșire PWM 38kHz (Timer 1) | + | | Buton suplimentar | Buton tactil (KEY / Inapoi) | Revenire in meniu anterior | |
| - | * Emițător RF: D4 - Ieșire digitală (GPIO) | + | | Receptor IR | KY-022 (VS1838B, 38 kHz) | Capturare semnale IR de la telecomenzi | |
| - | * Encoder: D5, D6, D7 - Intrări digitale cu Pull-up | + | | Emitator IR | KY-005 (LED IR 5mm) + Tranzistor NPN 2N2222 | Emitere semnale IR modulate la 38 kHz | |
| + | | Receptor RF | SYN480R 433 MHz (4 pini, cu antena 17.3 cm) | Capturare semnale RF de la telecomenzi | | ||
| + | | Emitator RF | SYN115 433 MHz (3 pini) | Emitere semnale RF | | ||
| + | | Acumulator | Li-ion 523450 (3.7V, ~1000 mAh) | Sursa de energie portabila | | ||
| + | | Modul incarcare | TP4056 (Micro-USB sau Type-C) | Incarcare acumulator Li-ion cu protectie | | ||
| + | | Modul Step-Up | MT3608 (ajustabil, setat la 5V) | Ridicare tensiune 3.7V -> 5V pentru sistem | | ||
| + | |||
| + | ==== Conexiuni Principale (Pinout) ==== | ||
| + | |||
| + | ^ Periferic ^ Pin Arduino Nano ^ Functie hardware utilizata ^ | ||
| + | | OLED SDA | A4 (PC4) | TWI/I2C - linie date | | ||
| + | | OLED SCL | A5 (PC5) | TWI/I2C - linie ceas | | ||
| + | | Receptor IR (KY-022) | D11 (PB3) | Intrare digitala (polling IRremote)| | ||
| + | | Emitator IR (KY-005) | D3 (PD3) | PWM Timer 2 / GPIO (IRremote) | | ||
| + | | Receptor RF (SYN480R) | D2 (PD2) | INT0 - Intrerupere externa HW | | ||
| + | | Emitator RF (SYN115) | D10 (PB2) | GPIO digital output | | ||
| + | | Encoder A (click) | D8 (PB0) | PCINT0 - Pin Change Interrupt | | ||
| + | | Encoder B (directie) | D6 (PD6) | GPIO - citit in ISR PCINT0 | | ||
| + | | Buton PUSH | D4 (PD4) | PCINT20 - Pin Change Interrupt | | ||
| + | | Buton KEY (Inapoi) | D5 (PD5) | PCINT21 - Pin Change Interrupt | | ||
| + | |||
| + | **Note de proiectare:** | ||
| + | * Receptorul RF (SYN480R) este conectat pe **D2 (INT0)** - singura intrerupere externa hardware rapida disponibila, pentru maximizarea fiabilitatii la receptie RF. | ||
| + | * Encoderul si butoanele folosesc **PCINT (Pin Change Interrupts)** cu debouncing software de 50 ms (encoder) si 250 ms (butoane). | ||
| + | * Emitatorul IR foloseste biblioteca **IRremote** care configureaza intern **Timer 1** pentru purtatoarea de 38 kHz (mod Fast PWM). | ||
| + | * Alimentarea este complet autonoma: acumulatorul Li-ion este gestionat de **TP4056** (protectie la suprasincarcare/supradescalcare), iar **MT3608** furnizeaza un 5V stabil pentru intregul circuit. | ||
| ===== Software Design ===== | ===== Software Design ===== | ||
| - | * **Laboratoare:** | + | ==== Arhitectura Firmware-ului ==== |
| - | * **Laboratorul 2 (Întreruperi):** Folosite pentru capturarea precisă a fronturilor de semnal de la receptoarele IR/RF. ISR-urile măsoară durata pulsurilor. | + | |
| - | * **Laboratorul 3 (Timere, PWM):** Timer 1 este utilizat pentru generarea purtătoarei de 38kHz (modul Fast PWM) necesară pentru IR. Timer 0 este utilizat pentru baza de timp în măsurarea microsecundelor. | + | |
| - | * **Laboratorul 6 (I2C):** Implementarea protocolului TWI pentru comunicarea cu ecranul OLED fără librării externe. | + | |
| - | * **Structuri de date:** Vectori pentru stocarea timpilor de "high" și "low" ai semnalelor capturate, salvați ulterior în EEPROM. | + | Firmware-ul este scris in **C++ pentru Arduino (bare-metal ATmega328P)** si structurat ca o **masina de stari finita (FSM)** cu 8 stari. Bucla principala ``loop()`` citeste starea curenta si executa logica aferenta, inclusiv actualizarea afisajului OLED. |
| - | ===== Rezultate Obţinute ===== | + | <code cpp> |
| + | enum AppState { | ||
| + | MENU_MAIN, // Meniu principal (Emite / Invata / Sterge) | ||
| + | MENU_LEARN, // Sub-meniu: alege IR sau RF | ||
| + | MENU_LEARN_SLOT, // Alege slotul EEPROM de salvat (0-9) | ||
| + | LEARN_WAITING, // Asteapta semnal IR/RF de la telecomanda originala | ||
| + | LEARN_SUCCESS, // Confirmare vizuala (stare tranzitorie) | ||
| + | MENU_SEND_SLOT, // Alege slotul de emis (0-9) | ||
| + | SENDING_CMD, // Control activ: encoderul modifica comanda IR | ||
| + | MENU_DELETE_SLOT // Sterge un slot din EEPROM | ||
| + | }; | ||
| + | </code> | ||
| + | ==== Module Software Principale ==== | ||
| + | |||
| + | === 1. Intreruperi (PCINT & INT0) === | ||
| + | |||
| + | Toate intrarile utilizatorului sunt gestionate **exclusiv prin intreruperi**, fara polling in ``loop()``: | ||
| + | |||
| + | * **PCINT0_vect** (D8 - Encoder click + directie): Detecteaza frontul descendent pe pinul A al encoderului. Directia este determinata citind starea pinului B (D6) in momentul ISR-ului. Debouncing hardware de 50 ms prin ``millis()``. | ||
| + | * **PCINT2_vect** (D4, D5 - Butoane PUSH si KEY): Detecteaza apasarile cu debouncing de 250 ms. Seteaza flag-uri volatile (``btnPushPressed``, ``btnKeyPressed``) consumate in ``loop()``. | ||
| + | * **INT0** (D2 - Receptor RF): Gestionat intern de biblioteca **RCSwitch** pentru decodificarea semnalelor RF 433 MHz. | ||
| + | |||
| + | <code cpp> | ||
| + | // Configurare PCINT (fara librarii externe) | ||
| + | void setupPCINT() { | ||
| + | cli(); | ||
| + | PCICR |= (1 << PCIE0) | (1 << PCIE2); // Activare grupuri PCINT0 si PCINT2 | ||
| + | PCMSK0 |= (1 << PCINT0); // D8 = PB0 (Encoder A) | ||
| + | PCMSK2 |= (1 << PCINT20) | (1 << PCINT21) | (1 << PCINT22); // D4, D5, D6 | ||
| + | lastPortB = PINB; | ||
| + | lastPortD = PIND; | ||
| + | sei(); | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | === 2. Timere si PWM === | ||
| + | |||
| + | * **Timer 1 (16-bit):** Folosit de biblioteca **IRremote** pentru generarea purtatoarei IR de **38 kHz** in mod Fast PWM pe pinul D3 (OC2B conform librariei). Rezolutia inalta a Timer 1 asigura o frecventa precisa, critica pentru receptoarele IR (care au banda de trecere ingusta). | ||
| + | * **Timer 0 (8-bit):** Utilizat de ``millis()`` / ``micros()`` pentru baza de timp globala - esential pentru debouncing si masurarea duratei pulsurilor. | ||
| + | |||
| + | === 3. Protocol I2C (TWI Hardware) === | ||
| + | |||
| + | Comunicarea cu ecranul **OLED SSD1306** se realizeaza prin **magistrala I2C hardware** a ATmega328P (TWI), via biblioteca **U8g2** in modul **1-page buffer** (``_1_``), pentru a minimiza consumul de RAM: | ||
| + | |||
| + | <code cpp> | ||
| + | // Mod 1-page: foloseste ~128 bytes RAM in loc de ~1 KB (full-frame buffer) | ||
| + | U8G2_SSD1306_128X64_NONAME_1_HW_I2C display(U8G2_R0, U8X8_PIN_NONE); | ||
| + | </code> | ||
| + | |||
| + | Desenarea se face cu pattern-ul ``firstPage()`` / ``nextPage()``, care itereaza prin paginile ecranului una cate una, economisind memorie SRAM. | ||
| + | |||
| + | === 4. EEPROM - Persistenta Profilelor === | ||
| + | |||
| + | Sistemul poate stoca **10 profiluri de dispozitiv** (sloturi 0-9) direct in EEPROM-ul intern al ATmega328P (1 KB disponibil). Fiecare profil este o structura de **12 bytes**: | ||
| + | |||
| + | <code cpp> | ||
| + | struct DeviceProfile { | ||
| + | bool isUsed; // Slot ocupat? | ||
| + | bool isIR; // true = IR, false = RF | ||
| + | uint16_t protocol; // Protocol IR (NEC, SAMSUNG, etc.) sau RF | ||
| + | uint32_t address; // Adresa dispozitivului IR / Codul RF | ||
| + | uint16_t command; // Comanda IR (valoarea butonului) | ||
| + | uint16_t bitLength; // Lungimea codului RF in biti | ||
| + | }; | ||
| + | // 10 sloturi x 12 bytes = 120 bytes din 1024 bytes EEPROM | ||
| + | </code> | ||
| + | |||
| + | La pornire, daca un slot contine valori de ``0xFF`` (EEPROM proaspat/sters), este marcat automat ca ``isUsed = false``. | ||
| + | |||
| + | === 5. Protocoale IR Suportate === | ||
| + | |||
| + | Biblioteca **IRremote** este configurata sa decodifice si sa emita 9 protocoale: | ||
| + | |||
| + | * NEC, Samsung, Sony, Panasonic, JVC, LG, RC5, RC6, Distance-Width (generic) | ||
| + | |||
| + | Comanda IR este emisa cu ``IrSender.write(&irData, 0)`` unde ``irData`` contine protocolul, adresa si comanda decodificate la receptie si salvate in EEPROM. | ||
| + | |||
| + | === 6. Protocol RF (433 MHz) === | ||
| + | |||
| + | Gestionat de biblioteca **RCSwitch**, care suporta prize inteligente, intrerupatoare wireless si alte dispozitive cu **cod fix OOK (On-Off Keying)**. La receptie, se salveaza: valoarea codului (32-bit), lungimea in biti si protocolul RF. La emisie, se reproduce identic cu ``mySwitch.send()``. | ||
| + | |||
| + | ==== Biblioteci Utilizate ==== | ||
| + | |||
| + | ^ Biblioteca ^ Versiune (PlatformIO) ^ Utilizare ^ | ||
| + | | U8g2 | olikraus/U8g2 | Driver OLED SSD1306 (I2C, 1-page buffer) | | ||
| + | | IRremote | z3t0/IRremote | Receptie si emisie multi-protocol IR (38 kHz) | | ||
| + | | RCSwitch | sui77/rc-switch | Receptie si emisie RF 433 MHz (OOK, cod fix) | | ||
| + | | EEPROM | Built-in Arduino | Persistenta profilelor de dispozitiv | | ||
| + | | Wire | Built-in Arduino | Initializare magistrala I2C (utilizat de U8g2) | | ||
| + | |||
| + | ===== Rezultate Obtinute ===== | ||
| + | |||
| + | * **Receptie IR functionala:** Dispozitivul receptioneaza si decodifica corect semnale de la telecomenzi reale (testat cu telecomenzi TV Samsung, benzi LED NEC, lustre cu protocol RC5). Semnalele necunoscute sau zgomotul sunt filtrate (se afiseaza "EROARE IR - Semnal Necunoscut" si se reia ascultarea). | ||
| + | * **Emisie IR functionala:** Semnalele salvate sunt retrimise fidel cu aceeasi adresa si protocol. Encoderul permite modificarea interactiva a valorii **comenzii** (0-255) in timp real, direct din meniul de control - utila pentru controllere de intensitate LED. | ||
| + | * **Receptie si emisie RF functionale:** Codurile RF de la prize inteligente cu cod fix (433 MHz OOK) sunt capturate si retrimise corect, inclusiv cu protocolul si lungimea de biti corecte. | ||
| + | * **Interfata OLED fluida:** Meniurile se actualizeaza imediat la rotirea encoderului, cu evidentiierea elementului selectat prin "rounded box" inversat. Sloturile goale sunt marcate clar ca "[ GOL ]". | ||
| + | * **Persistenta EEPROM verificata:** Profilurile supravietuiesc resetarilor si deconectarilor de la alimentare. Functia de stergere curata complet un slot (scrie ``0xFF``). | ||
| + | * **Consum de memorie eficient:** Prin alegerea modului 1-page buffer al U8g2 si a string-urilor in ``F()`` (Flash), firmware-ul functioneaza stabil in limita a 2 KB SRAM disponibili pe ATmega328P. | ||
| ===== Concluzii ===== | ===== Concluzii ===== | ||
| + | Proiectul demonstreaza cu succes integrarea mai multor tehnologii de comunicatie fara fir si a tehnicilor de programare bare-metal pe un microcontroller de 8 biti cu resurse limitate: | ||
| + | |||
| + | * **Intreruperile (PCINT si INT0)** s-au dovedit esentiale pentru un input utilizator responsiv, fara a bloca bucla principala. Debouncing-ul implementat in ISR elimina zgomotul mecanic al butoanelor si encoderului. | ||
| + | * **Timer-ele hardware** (Timer 0 pentru baza de timp, Timer 1 pentru purtatoarea IR de 38 kHz) permit operare precisa a protocolului IR fara a solicita CPU-ul in polling. | ||
| + | * **I2C hardware (TWI)** si modul 1-page buffer al U8g2 permit o interfata grafica functionala pe un ecran OLED, consumand minimal din SRAM-ul restrictionat. | ||
| + | * **EEPROM** ofera persistenta datelor necesara unui dispozitiv practic, permitand utilizatorului sa "programeze" telecomanda o singura data si sa o foloseasca nelimitat. | ||
| + | * O dificultate intalnita a fost **conflictul de pini** intre IRremote, RCSwitch si PCINT - rezolvat prin alocare manuala atenta a pinilor si dezactivarea selectiva a receptiei RF cand nu este necesara (``mySwitch.disableReceive()``), pentru a evita interferenta cu INT0. | ||
| + | * Proiectul poate fi extins cu: suport pentru mai multe protocoale RF (rolling code), macro-uri (secvente de comenzi), conectivitate Bluetooth sau control prin aplicatie mobila. | ||
| + | ===== Arhiva ===== | ||
| - | ===== Bibliografie/Resurse ===== | + | Descarcare: |
| + | {{ :pm:prj2026:theodor_ioan.buliga:pm_telecomanda.rar }} | ||
| + | ===== Bibliografie / Resurse ===== | ||
| - | * OCW PM: https://ocw.cs.pub.ro/courses/pm | + | * [[https://ocw.cs.pub.ro/courses/pm|OCW PM - Cursuri si laboratoare]] |
| - | * ATmega328P Datasheet | + | * [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf|ATmega328P Datasheet (Microchip)]] |
| - | * Protocolul IR NEC | + | * [[https://github.com/Arduino-IRremote/Arduino-IRremote|Biblioteca IRremote (GitHub)]] |
| + | * [[https://github.com/sui77/rc-switch|Biblioteca RCSwitch (GitHub)]] | ||
| + | * [[https://github.com/olikraus/u8g2|Biblioteca U8g2 (GitHub)]] | ||
| + | * [[https://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol|Protocolul IR NEC - Referinta]] | ||
| + | * SSD1306 Datasheet (Solomon Systech) - Specificatii controller OLED | ||
| + | * SYN115 / SYN480R Datasheets - Specificatii module RF 433 MHz | ||