This shows you the differences between two versions of the page.
|
pm:prj2026:vlad.radulescu2901:sebastian.barbu2707 [2026/05/24 13:51] 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 283: | Line 284: | ||
| **Fluxul de date:** | **Fluxul de date:** | ||
| - | DAC (MCP4921) → semnal analogic → condensator cuplaj AC 10µF | + | DAC (MCP4921) -> semnal analogic -> condensator cuplaj AC 10µF |
| - | → op-amp MCP6002 (buffer unitar, protecție diode) → ADC canal 0 | + | -> op-amp MCP6002 (buffer unitar, protecție diode) -> ADC canal 0 |
| - | → sample_buffer[240] → calcul Vpp/Vavg/CUR → display ILI9341 | + | -> sample_buffer[240] -> calcul Vpp/Vavg/CUR -> display ILI9341 |
| **Sincronizarea DAC–ADC în capture_frame():** | **Sincronizarea DAC–ADC în capture_frame():** | ||
| Line 293: | Line 294: | ||
| **Validare funcționalități:** | **Validare funcționalități:** | ||
| - | * **ADC + DAC:** semnal generat intern trimis și citit înapoi prin ADC; | + | * **ADC + DAC:** semnal generat intern trimis și citit înapoi prin ADC; varianță < 20mV confirmată prin UART (uart_send_uint16 în faza de debug) |
| - | 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'' |
| - | * **Butoane:** testate prin apăsare individuală — flagurile pending_* setate din ISR | + | * **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 |
| - | ș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 | * **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 | + | * **Cursor:** validat în modul HOLD — potențiometrul mută cursorul lin, CUR în statistici se actualizează în timp real |
| - | 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 ===== | ||