This shows you the differences between two versions of the page.
|
pm:prj2026:vlad.radulescu2901:sebastian.barbu2707 [2026/05/24 13:46] sebastian.barbu2707 [Software Design] |
pm:prj2026:vlad.radulescu2901:sebastian.barbu2707 [2026/05/24 14:43] (current) sebastian.barbu2707 [Hardware Design] |
||
|---|---|---|---|
| Line 128: | Line 128: | ||
| ^ Buton ^ Pin ATmega328P ^ Funcție ^ Justificare ^ | ^ Buton ^ Pin ATmega328P ^ Funcție ^ Justificare ^ | ||
| | HOLD | PD2 | Run/Stop captură | Pin INT0 — întrerupere externă dedicată pentru reacție instantă la oprirea capturii. | | | HOLD | PD2 | Run/Stop captură | Pin INT0 — întrerupere externă dedicată pentru reacție instantă la oprirea capturii. | | ||
| - | | MODE | PD3 | Schimbare mod trigger | Pin INT1 — întrerupere externă dedicată pentru schimbare rapidă a modului. | | + | | MODE | PD3 | Ciclare formă de undă | Pin INT1 — întrerupere externă dedicată pentru schimbare rapidă a modului. | |
| | TIME_P | PD4 | Mărire time/div | Pin GPIO cu suport PCINT20 pentru debouncing prin întrerupere. | | | TIME_P | PD4 | Mărire time/div | Pin GPIO cu suport PCINT20 pentru debouncing prin întrerupere. | | ||
| | TIME_M | PD5 | Micșorare time/div | Pin GPIO cu suport PCINT21, alăturat lui TIME_P pentru rutare ușoară. | | | TIME_M | PD5 | Micșorare time/div | Pin GPIO cu suport PCINT21, alăturat lui TIME_P pentru rutare ușoară. | | ||
| Line 138: | Line 138: | ||
| ^ Pin pot. ^ Conectat la ^ Funcție ^ Justificare ^ | ^ Pin pot. ^ Conectat la ^ Funcție ^ Justificare ^ | ||
| | 1 | GND | Capăt minim | Stabilește limita inferioară a domeniului de tensiune (0V). | | | 1 | GND | Capăt minim | Stabilește limita inferioară a domeniului de tensiune (0V). | | ||
| - | | 2 (wiper) | PC1 (A1) | Tensiune variabilă | Pin ADC1 al MCU citește tensiunea wiper-ului ca nivel de trigger ajustabil. | | + | | 2 (wiper) | PC1 (A1) | Tensiune variabilă | Pin ADC1 al MCU citește tensiunea wiper-ului ca cursor de măsurare pe |
| + | axa X. | | ||
| | 3 | +5V | Capăt maxim | Stabilește limita superioară a domeniului (5V), egală cu VREF al ADC. | | | 3 | +5V | Capăt maxim | Stabilește limita superioară a domeniului (5V), egală cu VREF al ADC. | | ||
| Line 155: | Line 156: | ||
| | PB5 | SCK | SPI | | | PB5 | SCK | SPI | | ||
| | PC0 | Semnal intrare | ADC0 | | | PC0 | Semnal intrare | ADC0 | | ||
| - | | PC1 | Trigger level | ADC1 | | + | | PC1 | Cursor de măsurare | ADC1 | |
| | PC4 | SDA | I²C | | | PC4 | SDA | I²C | | ||
| | PC5 | SCL | I²C | | | PC5 | SCL | I²C | | ||
| Line 197: | Line 198: | ||
| C3 (100nF) montate fizic lângă pinii VDD ai op-amp-ului și DAC-ului. | C3 (100nF) montate fizic lângă pinii VDD ai op-amp-ului și DAC-ului. | ||
| - | ===== Progres Actual ===== | + | ===== Progres Actual(pentru Milestone 2) ===== |
| {{ :pm:prj2026:vlad.radulescu2901:cablajfizic.jpeg?300 |}} | {{ :pm:prj2026:vlad.radulescu2901:cablajfizic.jpeg?300 |}} | ||
| Line 255: | Line 256: | ||
| ^ Concept laborator ^ Unde e folosit în proiect ^ Justificare ^ | ^ Concept laborator ^ Unde e folosit în proiect ^ Justificare ^ | ||
| - | | **GPIO** | Configurare pini CS/DC display, pini butoane cu pull-up intern | Controlul chip-select pe busul SPI partajat | | + | | GPIO | Pini CS/DC display, butoane cu pull-up intern | Controlul chip-select pe busul SPI partajat | |
| - | | **UART** | Debug serial la 57600 baud (uart.c) | Monitorizare valori ADC în timp real în faza de calibrare | | + | | UART | Debug serial la 57600 baud | Monitorizare valori ADC în timp real | |
| - | | **Întreruperi externe** | INT0 (HOLD), INT1 (MODE), PCINT0/PCINT2 (VOLT/TIME) | Butoanele sunt responsibile instant indiferent de cât durează draw_frame (~1s) | | + | | Întreruperi externe | INT0 (HOLD), INT1 (MODE), PCINT (VOLT/TIME) | Butoanele răspund instant indiferent de durata draw_frame | |
| - | | **Timer1 CTC** | timer1_ctc_init/reset/wait în capture_frame() | Cadență precisă a capturii: OCR1A × 4µs/tick = perioadă fixă per eșantion | | + | | Timer1 CTC | Funcțiile timer1_init/reset/wait în capture_frame | Cadență precisă: OCR1A × 4µs = perioadă fixă per eșantion | |
| - | | **ADC** | Canal 0 = semnal (ieșire op-amp), Canal 1 = potențiometru | Conversie analog-digital pentru ambele intrări analogice | | + | | ADC | Canal 0 (ieșire op-amp), Canal 1 (potențiometru) | Conversie analog-digital pentru ambele intrări | |
| - | | **SPI** | Display ILI9341 + DAC MCP4921 pe același bus | Transfer rapid de date (8 MHz) cu chip-select separat per periferic | | + | | SPI | Display ILI9341 + DAC MCP4921 pe același bus | Transfer rapid 8 MHz, chip-select separat per periferic | |
| - | | **I²C** | EEPROM AT24C256 la adresa 0x50 | Stocare persistentă; I²C e potrivit pentru memorii externe cu viteză mică | | + | | I²C | EEPROM AT24C256 la adresa 0x50 | Stocare persistentă; potrivit pentru memorii externe | |
| + | |||
| + | === Scheletul proiectului și interacțiunea dintre funcționalități === | ||
| + | |||
| + | **Bucla principală (main.c):** | ||
| + | |||
| + | <code c> | ||
| + | while (1) { | ||
| + | // 1. Citire potențiometru → cursor_x (mapare liniară cu calibrare hardware) | ||
| + | // 2. Procesare flaguri ISR (mode/hold/volt/time) → update stare + EEPROM | ||
| + | // 3. dacă !hold: | ||
| + | // capture_frame() → warm-up 128 iter. (OCR=35) + 240 eșantioane (OCR=200) | ||
| + | // draw_frame() → grilă + cursor + semnal coloană cu coloană | ||
| + | // draw_cursor_label() → tensiune la cursor, lângă linie | ||
| + | // draw_status_bar() → mod, T/div, V/div, HOLD | ||
| + | // draw_stats_panel() → Vpp, Vavg, T/div, CUR | ||
| + | // 4. dacă hold: | ||
| + | // detectare schimbare cursor_x → redesenare frame din buffer (fără captură) | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | **Fluxul de date:** | ||
| + | DAC (MCP4921) -> semnal analogic -> condensator cuplaj AC 10µF | ||
| + | -> op-amp MCP6002 (buffer unitar, protecție diode) -> ADC canal 0 | ||
| + | -> sample_buffer[240] -> calcul Vpp/Vavg/CUR -> display ILI9341 | ||
| + | |||
| + | **Sincronizarea DAC–ADC în capture_frame():** | ||
| + | - Timer1 CTC resetat la începutul fiecărei perioade | ||
| + | - DAC scrie eșantionul → _delay_us(5) settling → ADC citit → așteptare OCR1A | ||
| + | - Perioadă fixă: 200 × 4µs = 800µs/eșantion → rata de captură ~1.25 kHz | ||
| + | |||
| + | **Validare funcționalități:** | ||
| + | * **ADC + DAC:** semnal generat intern trimis și citit înapoi prin ADC; varianță < 20mV confirmată prin UART (uart_send_uint16 în faza de debug) | ||
| + | * **Butoane:** testate prin apăsare individuală — flagurile pending_* setate din ISR și procesate în bucla principală; debounce prin condiția ''if (!pending_x) pending_x = 1'' | ||
| + | * **EEPROM:** verificat prin cicluri de scoatere/rebranșare USB — setările (mod, amplitudine, timebase) restaurate corect; magic byte 0xAB la adresa 0x0000 previne încărcarea de date corupte | ||
| + | * **Timer1 CTC:** confirmat vizual — forma de undă stabilă la rata corectă de eșantionare | ||
| + | * **Cursor:** validat în modul HOLD — potențiometrul mută cursorul lin, CUR în statistici se actualizează în timp real | ||
| + | |||
| + | === Calibrarea elementelor de senzoristica === | ||
| + | **Potențiometru (ADC canal 1):** | ||
| + | |||
| + | Potențiometrul fizic nu acoperă întregul rang teoretic 0–1023 al ADC-ului. | ||
| + | Valorile reale au fost măsurate prin UART în faza de debug: | ||
| + | |||
| + | * Capăt minim fizic: ADC ≈ 173 | ||
| + | * Capăt maxim fizic: ADC ≈ 954 | ||
| + | |||
| + | Aceste valori sunt definite ca constante ''POT_MIN = 173'' și ''POT_MAX = 954''. | ||
| + | Formula de calibrare cu clamp: | ||
| + | |||
| + | <code c> | ||
| + | pot_clamped = (pot_raw <= POT_MIN) ? 0 : | ||
| + | (pot_raw >= POT_MAX) ? (POT_MAX - POT_MIN) : | ||
| + | (pot_raw - POT_MIN); | ||
| + | cursor_x = 1 + (uint32_t)pot_clamped * (SAMPLE_COUNT - 2) / (POT_MAX - POT_MIN); | ||
| + | </code> | ||
| + | |||
| + | Rezultat: la capătul minim fizic → cursor la x=1, la capătul maxim → cursor la x=239. | ||
| + | Fără calibrare, ultimul sfert al cursei rămânea fără efect vizibil. | ||
| + | |||
| + | **Scalarea tensiunii (ADC → Volți):** | ||
| + | |||
| + | ADC 10-bit cu Vref = 5V → 1 LSB = 5V/1023 ≈ 4.89 mV. | ||
| + | Vpp și Vavg sunt calculate direct din valorile ADC brute: | ||
| + | |||
| + | <code c> | ||
| + | vpp_x10 = (uint32_t)(vmax - vmin) * 50 / 1023; // zecimi de volt | ||
| + | vavg_x10 = (uint32_t)vavg * 50 / 1023; | ||
| + | </code> | ||
| + | |||
| + | **Consistența afișaj–calcul:** | ||
| + | |||
| + | Funcția ''adc_to_y()'' mapează ADC 0→fundul grilei, ADC 1023→vârful grilei, | ||
| + | fără margini de compresie — grila de 6 diviziuni × 36px corespunde exact cu | ||
| + | 5V / 6 ≈ 0.83V/div, consistent cu valorile numerice afișate. | ||
| + | |||
| + | === Optimizări === | ||
| + | |||
| + | **1. Font în PROGMEM (Flash, nu RAM)** | ||
| + | |||
| + | Tabelul font 5×7 (59 caractere × 5 bytes = 295 bytes) este declarat cu atributul | ||
| + | ''PROGMEM'' și citit cu ''pgm_read_byte()''. ATmega328P are doar 2KB SRAM — | ||
| + | fără această optimizare, fontul ar ocupa ~15% din SRAM-ul disponibil. | ||
| + | |||
| + | **2. Warm-up cu 128 iterații (artefact triunghi)** | ||
| + | |||
| + | Problema: condensatorul de cuplaj AC (10µF, RC ≈ 50ms) nu se poate stabili rapid | ||
| + | dacă DAC-ul face un salt brusc de la warm-up la captură. Soluția: 128 iterații de | ||
| + | warm-up cu OCR=35 (rapid, 140µs/pas) garantează că ''phase = 0'' la final pentru | ||
| + | orice ''phase_step'' din intervalul 1–4, deoarece ''128 × k mod 64 = 0'' ∀k. | ||
| + | Astfel nu există salt DAC la tranziția warm-up → captură. | ||
| + | |||
| + | **3. Desenare coloană cu coloană (fără buffer de ecran)** | ||
| + | |||
| + | ATmega328P nu are suficient RAM pentru un framebuffer complet (240×320×2 = 150KB). | ||
| + | Soluția: ''draw_frame()'' procesează ecranul coloană cu coloană — șterge coloana, | ||
| + | desenează grila, desenează semnalul. Se evită flickerul global și se elimină | ||
| + | necesitatea unui buffer secundar. | ||
| + | |||
| + | **4. ISR minim + flaguri volatile** | ||
| + | |||
| + | ISR-urile de butoane nu fac nimic altceva decât să seteze un flag: | ||
| + | ''if (!pending_x) pending_x = 1''. Procesarea efectivă (UART, display, EEPROM) | ||
| + | se face în bucla principală. Astfel ISR-ul durează < 10 cicli, minimizând | ||
| + | latența pentru alte întreruperi. | ||
| + | |||
| + | **5. SPI bus partajat DAC + Display** | ||
| + | |||
| + | Ambele periferice SPI (ILI9341 și MCP4921) partajează MOSI/SCK; chip-select | ||
| + | separat (CS_DAC pe PB2, CS_DISPLAY pe PD7) permite comunicație fără conflicte | ||
| + | și elimină necesitatea unui al doilea controler SPI. | ||
| ===== Rezultate Obţinute ===== | ===== Rezultate Obţinute ===== | ||
| - | <note tip> | + | Filmare care demonstreaza modul de functionare al Osciloscopului: |
| - | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | https://youtube.com/shorts/OEblZLtn7qA |
| - | </note> | + | |
| - | ===== Concluzii ===== | ||