This shows you the differences between two versions of the page.
|
pm:prj2026:atoader:anicolaescu2602 [2026/05/16 23:42] anicolaescu2602 [Software Design] |
pm:prj2026:atoader:anicolaescu2602 [2026/05/25 10:39] (current) anicolaescu2602 [Download] |
||
|---|---|---|---|
| Line 13: | Line 13: | ||
| {{ :pm:prj2026:atoader:anicolaescu2602_schema_bloc.png?300 |}} | {{ :pm:prj2026:atoader:anicolaescu2602_schema_bloc.png?300 |}} | ||
| + | |||
| + | Demo video: [[https://youtu.be/plcSe06cdxU|youtube.com]] | ||
| ===== Descriere generală ===== | ===== Descriere generală ===== | ||
| Line 85: | Line 87: | ||
| **Magistrala I2C — A4 (SDA) și A5 (SCL)** | **Magistrala I2C — A4 (SDA) și A5 (SCL)** | ||
| - | Pinii A4/A5 sunt **singurii pini hardware I2C** ai ATmega328P (interfața TWI), | + | Pinii A4/A5 si SDA/SCL sunt pini hardware I2C ai ATmega328P, |
| - | ceea ce permite comunicarea simultană cu trei dispozitive pe aceeași magistrală: | + | ceea ce permit comunicarea simultană cu trei dispozitive pe aceeași magistrală: |
| ^ Dispozitiv ^ Adresă I2C ^ | ^ Dispozitiv ^ Adresă I2C ^ | ||
| Line 140: | Line 142: | ||
| **ADC — A3** | **ADC — A3** | ||
| Senzorul TEMT6000 produce o tensiune analogică proporțională cu luminozitatea. | Senzorul TEMT6000 produce o tensiune analogică proporțională cu luminozitatea. | ||
| - | A3 este ales liber, A4 și A5 fiind ocupați de magistrala I2C. | ||
| - | Configurarea ADC în firmware: | ||
| <code c> | <code c> | ||
| Line 172: | Line 172: | ||
| celălalt capăt la GND. | celălalt capăt la GND. | ||
| - | **LED-urile** (rândurile 1–10) au rezistențe de 470Ω în serie pe fiecare | + | **LED-urile** au rezistențe de 470Ω în serie pe fiecare |
| anod, limitând curentul la ~10mA la 5V. | anod, limitând curentul la ~10mA la 5V. | ||
| - | **Buzzerul pasiv** (rândul 29–33) este conectat direct la D5 cu GND comun. | + | **Buzzerul pasiv** este conectat direct la D5 cu GND comun. |
| - | **TEMT6000** (rândul 20–22) are ieșirea analogică conectată la A3. | + | **TEMT6000** are ieșirea analogică conectată la A3. |
| - | ===== 5. Dovezi de funcționare ===== | + | **5. Dovezi de funcționare** |
| Schema din Cirkit Designer confirmă conectarea corectă a tuturor componentelor. | Schema din Cirkit Designer confirmă conectarea corectă a tuturor componentelor. | ||
| Line 193: | Line 193: | ||
| lcd_print("Nicolaescu Alex"); | lcd_print("Nicolaescu Alex"); | ||
| delay(1500); | delay(1500); | ||
| - | </code> | + | </code>{{ :pm:prj2026:atoader:anicolaescu2602_functionare1.jpeg?300 |}}{{ :pm:prj2026:atoader:anicolaescu2602_functionare2.jpeg?300 |}} |
| - | ===== Software Design ===== | + | ====== Software Design ====== |
| - | **1. Mediu de dezvoltare** | + | ===== 1. Mediu de dezvoltare ===== |
| - | + | [[https://github.com/alexsilviu26/pm-project|GITHUB]] | |
| - | Proiectul a fost dezvoltat utilizând **PlatformIO** (în cadrul VS Code) și framework-ul **Arduino**, dar cu o abordare orientată către programarea la nivel de regiștri specifică **AVR-GCC**. Această combinație a permis utilizarea unor funcții utilitare de sistem (precum `millis()`), păstrând în același timp controlul total asupra perifericelor microcontrolerului ATmega328P. | + | Proiectul a fost dezvoltat utilizând **PlatformIO** (în cadrul VS Code) și framework-ul **Arduino**, dar cu o abordare orientată către programarea la nivel de regiștri specifică **AVR-GCC**. Această combinație a permis utilizarea unor funcții utilitare de sistem (precum ''millis()''), păstrând în același timp controlul total asupra perifericelor microcontrolerului ATmega328P. |
| - | + | ||
| - | ** 2. Librării și surse 3rd-party** | + | |
| + | ===== 2. Librării și surse 3rd-party ===== | ||
| Pentru a maximiza eficiența și a reduce amprenta de memorie, codul **nu utilizează biblioteci comerciale grele** (precum cele de la Adafruit sau SparkFun). În schimb, s-au folosit: | Pentru a maximiza eficiența și a reduce amprenta de memorie, codul **nu utilizează biblioteci comerciale grele** (precum cele de la Adafruit sau SparkFun). În schimb, s-au folosit: | ||
| + | * **avr/interrupt.h:** Pentru gestionarea vectorilor de întrerupere (butoane). | ||
| + | * **avr/eeprom.h:** Pentru stocarea permanentă a pragurilor de alertă în mod eficient prin ''eeprom_read_block'' și ''eeprom_update_block''. | ||
| + | * **math.h:** Pentru implementarea formulelor logaritmice (punct de rouă) și a puterilor (altitudine). | ||
| + | * **Driver I2C Custom:** Implementare proprie pentru protocolul Two-Wire Interface (TWI) pentru comunicarea cu senzorii și LCD-ul, bazată pe manipularea directă a regiștrilor ''TWDR'', ''TWCR'', ''TWSR''. | ||
| - | **avr/interrupt.h**: Pentru gestionarea vectorilor de întrerupere (butoane). | + | ===== 3. Algoritmi și structuri de date ===== |
| - | **avr/eeprom.h**: Pentru stocarea permanentă a pragurilor de alertă. | + | * **Filtru de Medie Mobilă (Moving Average):** Implementat în funcția ''smooth_pressure'' folosind un buffer circular de 10 eșantioane pentru a stabiliza citirile barometrice și a evita fluctuațiile cauzate de zgomot. |
| - | **math.h**: Pentru implementarea formulelor logaritmice (punct de rouă) și a puterilor (altitudine). | + | * **Algoritmul Magnus-Tetens:** Utilizat pentru calcularea punctului de rouă pe baza temperaturii și umidității. |
| - | **Drivre I2C Custom**: Implementare proprie pentru protocolul Two-Wire Interface (TWI) pentru comunicarea cu senzorii și LCD-ul, bazată pe manipularea directă a regiștrilor `TWDR`, `TWCR`, `TWSR`. | + | * **Formula Barometrică:** Calculul altitudinii relative folosind raportul dintre presiunea curentă și o presiune de referință ($P_0$). |
| - | + | * **Structura DeviceSettings:** O structură de date care grupează toate pragurile de mediu și un ''Magic Number'' (0x44) pentru validarea integrității datelor citite din EEPROM la startup. | |
| - | ** 3. Algoritmi și structuri de date** | + | * **Mapare PWM Proporțională:** Un algoritm care calculează severitatea abaterii termice și ajustează factorul de umplere (Duty Cycle) pentru buzzer și culorile LED-ului RGB. |
| - | + | ||
| - | **Filtru de Medie Mobilă (Moving Average):** Implementat în funcția `smooth_pressure` folosind un buffer circular de 10 eșantioane pentru a stabiliza citirile barometrice și a evita fluctuațiile cauzate de zgomot. | + | |
| - | + | ||
| - | **Algoritmul Magnus-Tetens:** Utilizat pentru calcularea punctului de rouă pe baza temperaturii și umidității. | + | |
| - | + | ||
| - | **Formula Barometrică:** Calculul altitudinii relative folosind raportul dintre presiunea curentă și o presiune de referință ($P_0$). | + | |
| - | + | ||
| - | **Structura `DeviceSettings`:** O structură de date care grupează toate pragurile de mediu și un "Magic Number" (0x44) pentru validarea integrității datelor citite din EEPROM la startup. | + | |
| - | + | ||
| - | **Mapare PWM Proporțională:** Un algoritm care calculează severitatea abaterii termice și ajustează factorul de umplere (Duty Cycle) pentru buzzer și culorile LED-ului RGB. | + | |
| - | + | ||
| - | ** 4. Surse și funcții implementate (Etapa 3) ** | + | |
| + | ===== 4. Surse și funcții implementate ===== | ||
| Codul este modularizat pe funcționalități cheie, cele mai importante fiind: | Codul este modularizat pe funcționalități cheie, cele mai importante fiind: | ||
| - | ** Gestionarea Hardware (Low-Level) ** | + | ==== Gestionarea Hardware (Low-Level) ==== |
| + | * ''i2c_init()'', ''i2c_start()'', ''i2c_write()'', ''i2c_read()'': Setul de funcții care gestionează magistrala I2C la frecvența de 100kHz. | ||
| + | * ''lcd_send()'', ''lcd_init()'': Driverul pentru ecranul LCD 1602, care traduce comenzile în nibbles (4 biți) pentru interfața I2C a modulului PCF8574. | ||
| + | * **Timere (PWM):** Configurare manuală a ''Timer0'' (pentru Buzzer și Blue LED) și ''Timer1'' (pentru Red și Green LED) în modul Fast PWM. | ||
| - | `i2c_init()`, `i2c_start()`, `i2c_write()`, `i2c_read()`: Setul de funcții care gestionează magistrala I2C la frecvența de 100kHz. | + | ==== Achiziție și Procesare Date ==== |
| - | `lcd_send()`, `lcd_init()`: Driverul pentru ecranul LCD 1602, care traduce comenzile în nibbles (4 biți) pentru interfața I2C a modulului PCF8574. | + | * ''bmp_read_calibration()'': Funcție critică ce citește coeficienții unici de calibrare din memoria senzorului BMP280. |
| - | **Timere (PWM):** Configurare manuală a `Timer0` (pentru Buzzer și Blue LED) și `Timer1` (pentru Red și Green LED) în modul Fast PWM. | + | * ''bmp_compensate_temp()'' & ''bmp_compensate_pressure()'': Implementarea calculelor matematice pe 32 și 64 de biți conform specificațiilor Bosch pentru obținerea datelor brute. |
| + | * ''update_leds(t, h)'': Logica de control a culorilor, care decide tranziția între albastru-verde-roșu în funcție de confortul termic. | ||
| + | * ''dynamic_buzzer(t, lux)'': Funcția de siguranță care modulează sunetul și verifică starea de Mute (manuală sau nocturnă). | ||
| - | ** Achiziție și Procesare Date ** | + | ==== Interfață și Întreruperi ==== |
| + | * ''ISR(INT1_vect)'': Gestionează butonul de "Plus / Mute". | ||
| + | * ''ISR(PCINT2_vect)'': Gestionează butonul de "Minus / Schimbare Unități". | ||
| + | * **Logică Meniu:** Implementată în ''loop()'', gestionează starea de Long Press (2 secunde) pe pinul D2 pentru a comuta între modul de afișare și cel de editare a pragurilor salvate în EEPROM. | ||
| - | `bmp_read_calibration()`: Funcție critică ce citește coeficienții unici de calibrare din memoria senzorului BMP280. | + | ==== Fluxul Principal (loop) ==== |
| - | `bmp_compensate_temp()` & `bmp_compensate_pressure()`: Implementarea calculelor matematice pe 32 și 64 de biți conform specificațiilor Bosch pentru obținerea datelor brute. | + | Programul urmează o structură de tip mașină de stări: |
| - | `update_leds(t, h)`: Logica de control a culorilor, care decide tranziția între albastru-verde-roșu în funcție de confortul termic. | + | 1. Verifică starea butoanelor (prin întreruperi). |
| - | `dynamic_buzzer(t, lux)`: Funcția de siguranță care modulează sunetul și verifică starea de "Mute" (manuală sau nocturnă). | + | 2. Achiziționează date de la AHT20, BMP280 și ADC (LDR). |
| + | 3. Procesează datele (filtrare, conversii). | ||
| + | 4. Actualizează ieșirile PWM (LED-uri, Buzzer). | ||
| + | 5. Actualizează afișajul LCD în funcție de pagina selectată sau meniul activ. | ||
| - | ** Interfață și Întreruperi ** | + | --- |
| - | `ISR(INT1_vect)`: Gestionează butonul de "Plus / Mute". | + | ===== 5. Stadiul actual al implementării software ===== |
| - | `ISR(PCINT2_vect)`: Gestionează butonul de "Minus / Schimbare Unități". | + | Implementarea firmware-ului pentru ministația meteo este **completă și complet funcțională**. Toate modulele software descrise sunt integrate într-o mașină de stări stabilă, de tip non-blocking. Achiziția de la senzori, algoritmul de filtrare a datelor, calculul punctului de rouă, controlul PWM proporțional pentru LED/Buzzer, interfața de navigare prin pagini și meniul interactiv cu salvare în EEPROM rulează asincron, fără blocaje ale buclei principale. |
| - | **Logicã Meniu:** | + | ===== 6. Elementul de noutate al proiectului ===== |
| - | Implementată în `loop()`, gestionează starea de "Long Press" (2 secunde) pe pinul D2 pentru a comuta între modul de afișare și cel de editare a pragurilor salvate în EEPROM. | + | Spre deosebire de stațiile meteo convenționale de nivel hobby care doar afișează valori brute, acest proiect aduce ca elemente de noutate: |
| + | * **Feedback-ul acustic și vizual proporțional:** Intensitatea buzzer-ului și tranzițiile cromatice ale LED-ului RGB nu sunt binare (ON/OFF), ci sunt mapate matematic utilizând gradul de severitate al abaterii termice față de limitele de confort. | ||
| + | * **Sistemul Smart Mute adaptiv:** Dispozitivul integrează o funcție autonomă de diminuare a deranjului fonic; dacă senzorul TEMT6000 indică o valoare sub 10 lx (**Mod Noapte**), buzzerul se dezactivează automat, prioritatea trecând pe indicarea optică. | ||
| + | * **Meniu de calibrare hardware persistent:** Permite calibrarea offset-ului de altitudine direct din butoane, fără necesitatea rescrierii firmware-ului. | ||
| - | ** Fluxul Principal (`loop`) ** | + | ===== 7. Justificarea utilizării funcționalităților din laborator ===== |
| - | Programul urmează o structură de tip mașină de stări: | + | ^ Laborator ^ Funcționalitate în Proiect ^ Justificare Tehnică ^ |
| + | | **GPIO** | Direcția pinilor și pull-up | Configurația directă a regiștrilor ''DDRB'', ''DDRD'' și ''PORTD'' pentru controlul LED-urilor discrete de umiditate și activarea pull-up-urilor interne pentru butoane. | | ||
| + | | **Întreruperi** | ''INT1'' și ''PCINT2'' | Folosite pentru detectarea apăsării butoanelor de pe pinii D3 și D4. Asigură comutarea unităților și modificarea pragurilor în mod asincron, cu debouncing software de 250ms. | | ||
| + | | **I2C (TWI)** | Comunicație master-slave | Implementarea mașinii de stări pentru controlul magistralei hardware (regiștrii ''TWCR'', ''TWDR'', ''TWSR'') la 100kHz pentru citirea senzorilor și scrierea datelor pe LCD-ul cu expandor PCF8574. | | ||
| + | | **PWM & Timere** | Fast PWM pe 8 biți | Utilizarea ''Timer0'' (canalele A și B pentru Blue LED și Buzzer) și ''Timer1'' (canalele A și B pentru Red și Green LED) în mod Fast PWM pentru controlul intensității și al culorilor. | | ||
| + | | **ADC** | Citire analogică | Configurat pe pinul A3 (regiștrii ''ADMUX'', ''ADCSRA'') cu prescaler de 128 pentru conversia semnalului generat de TEMT6000 în unități de luxi. | | ||
| - | 1. Verifică starea butoanelor (prin întreruperi). | + | ===== 8. Scheletul proiectului și interacțiunea funcționalităților ===== |
| + | Sistemul este structurat sub forma unei arhitecturi conduse de evenimente combinată cu o mașină de stări ciclică. Interacțiunea se realizează astfel: | ||
| + | * **Gestiunea intrărilor (Evenimente):** Apăsarea butoanelor generează întreruperi care modifică variabilele globale volatile (''temp_unit'', ''display_page'', ''manual_mute'') sau modifică pragurile în mod direct dacă ''in_menu'' este activ. | ||
| + | * **Mașina de stări din loop:** Dacă ''in_menu'' este activ, sistemul oprește citirea senzorilor și afișează interfața de editare. La ieșire, se apelează automat ''save_to_eeprom()''. Dacă ''in_menu'' este fals, se inițiază secvențial citirea I2C. Datele de presiune sunt trimise către filtrul ''smooth_pressure()'', iar temperatura și umiditatea sunt folosite ca argumente pentru ''calculate_dew_point()''. | ||
| + | * **Controlul ieșirilor:** Datele procesate sunt trimise către ''update_leds()'' și ''dynamic_buzzer()'' care modifică regiștrii de comparare PWM (''OCR0A'', ''OCR0B'', ''OCR1A'', ''OCR1B''), în timp ce ecranul LCD este actualizat cu string-urile formatate prin ''dtostrf()''. | ||
| - | 2. Achiziționează date de la AHT20, BMP280 și ADC (LDR). | + | **Validarea funcționării:** Sistemul a fost validat prin monitorizarea datelor trimise în paralel pe un port serial virtual, cât și prin introducerea stației în medii cu parametri controlați (sursă de căldură pentru testarea tranziției RGB în rosu și pornirea buzzerului, respectiv acoperirea senzorului LDR pentru validarea modului de noapte). |
| - | 3. Procesează datele (filtrare, conversii). | + | ===== 9. Calibrarea elementelor de senzoristică ===== |
| + | Pentru a asigura acuratețea datelor afișate și a compensa erorile de poziționare sau toleranțele componentelor hardware, s-au implementat trei niveluri de calibrare: | ||
| + | * **Calibrare software fixă (Offsets):** S-au definit constantele ''AHT20_T_OFFSET = -0.8f'' (pentru a corecta căldura radiată de componentele din jur pe breadboard) și ''BMP280_P_OFFSET = 600.0f'' (pentru alinierea cu presiunea stației de referință). | ||
| + | * **Compensare dinamică din Datasheet (BMP280):** În funcția ''bmp_read_calibration()'', la pornirea sistemului sunt citiți din memoria nevolatilă a senzorului cei 11 coeficienți unici de calibrare din fabrică (''dig_T1-T3'', ''dig_P1-P9''). Funcțiile ''bmp_compensate_temp()'' și ''bmp_compensate_pressure()'' aplică ecuațiile de compensare pe 32 și 64 de biți conform specificațiilor Bosch. | ||
| + | * **Calibrare interactivă (Altitudine):** Deoarece presiunea la nivelul mării se modifică zilnic, s-a introdus în meniu parametrul ''altitude_offset'', permițând utilizatorului să introducă altitudinea exactă a locației curente pentru calibrarea punctului zero al algoritmului barometric. | ||
| - | 4. Actualizează ieșirile PWM (LED-uri, Buzzer). | + | ===== 10. Optimizări realizate ===== |
| + | * **I2C și LCD:** Înlocuirea funcțiilor din biblioteca standard Arduino cu funcții custom bazate pe manipulare de biți și așteptare pe flag-ul hardware ''TWINT''. **De ce:** Reduce dimensiunea codului compilat (Flash) cu aproximativ 4KB și mărește viteza de reîmprospătare a ecranului. | ||
| + | * **Funcțiile de afișare:** Înlocuirea funcției standard ''sprintf'' (care conține un overhead imens pentru parsarea tipurilor float) cu funcția de sistem mult mai rapidă ''dtostrf()'' pentru conversia valorilor float în siruri de caractere. **De ce:** Microcontrolerul nu are unitate de calcul în virgulă flotantă (FPU) hardware; optimizarea reduce semnificativ timpul de execuție al buclei. | ||
| + | * **Scrierea în EEPROM:** Utilizarea funcției ''eeprom_update_block'' în loc de ''eeprom_write_block''. **De ce:** Funcția de update verifică dacă noua valoare diferă de cea deja salvată și efectuează scrierea doar dacă este necesar, protejând durata de viață a celulelor EEPROM (limitate la 100.000 de cicluri de scriere). | ||
| - | 5. Actualizează afișajul LCD în funcție de pagina selectată sau meniul activ. | + | ===== 11. Demo Video Proiect ===== |
| + | Deoarece site-ul este public, prezentarea video și demonstrarea funcționalităților complete au fost încărcate în platforma securizată de stocare a facultății. | ||
| + | **Explicații conținut video:** | ||
| + | - **Inițializare:** Se observă afișarea ecranului de bun venit timp de 1.5 secunde. | ||
| + | - **Navigare:** Se prezintă apăsarea scurtă a butonului D2 pentru a trece prin cele 3 pagini de date. | ||
| + | - **Schimbarea unităților:** Se demonstrează apăsarea butonului D4 care schimbă unitățile (C/F/K, respectiv mmHg/hPa). | ||
| + | - **Meniu de setări:** Se evidențiază apăsarea lungă (2s) pe D2, modificarea pragului ''T_max'' folosind butoanele D3 și D4, urmată de salvarea automată în EEPROM. | ||
| + | - **Declanșarea alertelor:** Se apropie o sursă de căldură de senzor; se observă tranziția fluidă a LED-ului RGB din verde în roșu și intensificarea sunetului PWM pe măsură ce temperatura depășește pragul limită. Apăsarea butonului Mute oprește imediat alerta acustică (apare indicatorul ''[M]''). | ||
| ====== Rezultate Obținute ====== | ====== Rezultate Obținute ====== | ||