This shows you the differences between two versions of the page.
|
pm:prj2025:fstancu:cristina.drinciu [2025/05/25 17:34] cristina.drinciu [Software Design] |
pm:prj2025:fstancu:cristina.drinciu [2025/05/30 13:42] (current) cristina.drinciu [Hardware Design] |
||
|---|---|---|---|
| Line 103: | Line 103: | ||
| {{:pm:prj2025:fstancu:poza2_amp.jpg?350 |}} {{:pm:prj2025:fstancu:poza4_amp.jpg?350|}} | {{:pm:prj2025:fstancu:poza2_amp.jpg?350 |}} {{:pm:prj2025:fstancu:poza4_amp.jpg?350|}} | ||
| {{:pm:prj2025:fstancu:poza3_amp.jpg?350 |}} {{:pm:prj2025:fstancu:poza1_amp.jpg?350|}} | {{:pm:prj2025:fstancu:poza3_amp.jpg?350 |}} {{:pm:prj2025:fstancu:poza1_amp.jpg?350|}} | ||
| + | {{:pm:prj2025:fstancu:final_project1.jpeg?350|}} {{:pm:prj2025:fstancu:final_project.jpeg?350|}} | ||
| Link catre poze si video demonstrativ: [[https://drive.google.com/drive/folders/1RUL_uXa5XXPFie1JvUg6ljKmbEH5EQQS | aici ]] | Link catre poze si video demonstrativ: [[https://drive.google.com/drive/folders/1RUL_uXa5XXPFie1JvUg6ljKmbEH5EQQS | aici ]] | ||
| Line 143: | Line 144: | ||
| === I2C (TWI) === | === I2C (TWI) === | ||
| __//Rol://__ Interfața I²C (TWI) generică, folosită pentru a comunica cu DAC-ul MCP4725 la ~400 kHz. | __//Rol://__ Interfața I²C (TWI) generică, folosită pentru a comunica cu DAC-ul MCP4725 la ~400 kHz. | ||
| + | |||
| + | {{:pm:prj2025:fstancu:amp_twcr.png?500|}} | ||
| Ce face fiecare functie: | Ce face fiecare functie: | ||
| Line 196: | Line 199: | ||
| === Efecte === | === Efecte === | ||
| - | __//Rol://__ : Procesarea semnalului convertit in digital, aplicand efectele stabilite: **distorsiune, tremolo, delay** | + | __//Rol://__ Procesarea semnalului convertit in digital, aplicand efectele stabilite: **distorsiune, tremolo, delay** |
| == Distortion == | == Distortion == | ||
| Line 226: | Line 229: | ||
| asigurând conversia corectă pe 12 biţi. | asigurând conversia corectă pe 12 biţi. | ||
| - | |||
| - | '' | ||
| - | uint16_t apply_distortion(int16_t sample) { | ||
| - | float x = sample / 2048.0f; // normalizează \\ | ||
| - | x = x * (0.7f + 0.3f * fabsf(x)); // pre-emphasis \\ | ||
| - | float d = tanhf(50.0f * x); // soft-clip \\ | ||
| - | d = (d > 0.8f ? 0.8f : (d < -0.8f ? -0.8f : d)); \\ | ||
| - | int32_t v = (int32_t)(d * 2047.0f); \\ | ||
| - | return (uint16_t)(v + 2048); // 0..4095 \\ | ||
| - | } | ||
| - | '' | ||
| == Tremolo == | == Tremolo == | ||
| Line 244: | Line 236: | ||
| Generăm un LFO sinusoidal pe 16 biți de fază si modulam aplitudinea cu factorul 2 pentru a compensa atenuarea la min(LFO). | Generăm un LFO sinusoidal pe 16 biți de fază si modulam aplitudinea cu factorul 2 pentru a compensa atenuarea la min(LFO). | ||
| + | Vom modifica periodic volumul semnalului audio pentru a crea un efect de „pulsare”. | ||
| + | În cod ținem o variabilă de fază pe 16 biți care se crește constant de fiecare dată când vine un eşantion nou. | ||
| - | ===== Rezultate Obţinute ===== | + | La fiecare eşantion, din această fază calculăm o valoare între 0 și 1 (LFO) care oscilează la frecvența tremolo-ului (de exemplu 5 pulsuri pe secundă). |
| - | <note tip> | + | Apoi multiplicăm semnalul de intrare cu un amestec între volumul original și valoarea LFO: |
| - | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | |
| - | </note> | + | |
| - | ===== Concluzii ===== | + | Dacă LFO este aproape de 1, semnalul are volum aproape normal. |
| - | ===== Download ===== | + | Dacă LFO este aproape de 0, semnalul este atenuat (mai silențios). |
| - | <note warning> | + | Prin schimbarea „adâncimii” (depth) poți controla cât de puternică este această variație de volum. |
| - | O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului: surse, scheme, etc. Un fişier README, un ChangeLog, un script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-). | + | |
| - | Fişierele se încarcă pe wiki folosind facilitatea **Add Images or other files**. Namespace-ul în care se încarcă fişierele este de tipul **:pm:prj20??:c?** sau **:pm:prj20??:c?:nume_student** (dacă este cazul). **Exemplu:** Dumitru Alin, 331CC -> **:pm:prj2009:cc:dumitru_alin**. | + | Totul se întâmplă foarte rapid (mii de ori pe secundă), astfel încât urechea percepe un „vibrato de volum” constant și sincronizat, fără distorsiuni suplimentare. |
| - | </note> | + | |
| + | == Delay == | ||
| + | __//Rol://__ acest efect functioneaza ca un ecou, deci a fost nevoie de un buffer pentru a memora semnalul, deci memorie RAM. | ||
| + | |||
| + | Stocăm fiecare eşantion de semnal într-un buffer circular de mărime fixă (de exemplu 980 poziții). | ||
| + | |||
| + | Când procesăm un eşantion nou, citim din buffer eşantionul aflat cu un anumit „pas” înapoi (de exemplu, 800 poziții) — acesta este semnalul întârziat. | ||
| + | |||
| + | Combinăm semnalul întârziat cu semnalul curent: o parte din ecou (feedback) se adaugă peste semnalul nou. | ||
| + | |||
| + | Scriem în buffer valoarea rezultatului (semnal direct + ecou) pentru ca, la următoarea trecere, să putem crea ecouri în buclă. | ||
| + | |||
| + | Prin ajustarea mărimii buffer-ului (delay time) și a procentului de feedback, controlăm cât de lung și cât de intens este ecoul. | ||
| + | |||
| + | Practic, buffer-ul reţine „urmele” semnalului și le redă cu întârziere, creând senzația de reverberație și ecou. | ||
| + | |||
| + | === ADC === | ||
| + | |||
| + | __//Rol://__ Preluare continuă de semnal analogic și declanșare ISR pentru procesare. | ||
| + | |||
| + | {{:pm:prj2025:fstancu:amp_admux.png?500|}} | ||
| + | |||
| + | {{:pm:prj2025:fstancu:amp_adcsra.png?500|}} | ||
| + | |||
| + | {{:pm:prj2025:fstancu:amp_adcsrb.png?500|}} | ||
| + | |||
| + | |||
| + | Avem urmatoarele setari pentru registre: | ||
| + | |||
| + | * ''ADMUX = (1<<REFS0);'' - REFS0=1 → referință AVcc, canal ADC0 | ||
| + | * ''ADCSRA = ADEN|ADIE|ADATE|(ADPS2|ADPS1);'' care este responsabil de: | ||
| + | |||
| + | ''ADEN = enable ADC'' | ||
| + | |||
| + | ''ADIE = enable ADC interrupt'' | ||
| + | |||
| + | ''ADATE = auto-trigger → modul Free-Running'' | ||
| + | '' | ||
| + | ADPS2:1 = prescaler 64 → ADC clock ~250 kHz'' | ||
| + | |||
| + | * ''ADCSRB = 0;'' → Free-Run | ||
| + | * ''DIDR0 = (1<<ADC0D)''; → dezactivează intrare digitală pe ADC0 | ||
| + | * ''ADCSRA |= (1<<ADSC);'' → pornește prima conversie | ||
| + | |||
| + | Intreruperile folosite: | ||
| + | |||
| + | ''**ISR(ADC_vect)**'' | ||
| + | |||
| + | * Citește ADC (0–1023), recentrează la ±512 | ||
| + | * | ||
| + | * Normalizează la ±1.0 | ||
| + | * | ||
| + | * Aplică efectele active | ||
| + | * | ||
| + | * Clamp și convert la 0–4095 → mcp4725_write() | ||
| + | |||
| + | De ce Free-Running? Vrem eșantionare continuă la frecvență fixă, fără să declanșăm singur fiecare conversie. Asa obtinem eficienta mai buna. | ||
| + | |||
| + | === Butoane === | ||
| + | //__Rol:__// Gestionare butoane cu PCINT + debounce cu Timer0. De asemnea va trata si activarea butoanelor. | ||
| + | |||
| + | Acestea functioneaza pe modul activer low, deci 0 activate, 1 dezactivate. | ||
| + | |||
| + | **ISR(PCINT2_vect) (Pin Change)** | ||
| + | * Setat pe PD2..PD4 (PCINT18..20) | ||
| + | * La trecerea HIGH→LOW pornește counter deb once | ||
| + | * eficient pentru ca nu asteptam intr-un loop apasarea butoanelor, doar intra rutina de tratare a intreruperilor pentru a schimba starea butoanelor si a LED-urilor. | ||
| + | |||
| + | **ISR(TIMER0_COMPA_vect)** | ||
| + | * (apelat in functia main), aceasta rutina va apela procesarea semnalului prin efecte, in functie daca au fost activate sau nu | ||
| + | * Timer0 CTC: prescaler 64, OCR0A=249 → 1 kHz interrupt | ||
| + | * decrementeaza counterele, iar la zero toggle LED și flag efect | ||
| + | |||
| + | De ce PCINT + timer? Detectăm rapid schimbarea de buton și facem debounce fără blocări în bucla principală. | ||
| + | |||
| + | === Main === | ||
| + | Inițializează toate modulele și intră în buclă infinită. | ||
| + | |||
| + | Flux general: | ||
| + | |||
| + | * Butoane → PCINT + Timer0 → update flags | ||
| + | |||
| + | * ADC Free-Run → ISR(ADC_vect) → apply_effects → DAC | ||
| + | |||
| + | * DAC → ieșire audio analogic | ||
| + | |||
| + | ===== Rezultate Obţinute si Performanta ===== | ||
| + | |||
| + | Amplificatorul functioneaza destul de bine, putand sa genereze un semnal audio destul de bun. | ||
| + | Chiar daca am incercat sa lucrez la o frecventa destul de ridicata pentru a avea un sample rate cat mai mare, notele joase sunt redate foarte clar iar cele mai inalte sunt redate o idee mai prost, avand o frecventa destul de mare si masuratorile nu sunt atat de accurate. | ||
| + | |||
| + | === Optimizarile folosite pentru a obtine performante si imbunatiri care pot fi adaugate === | ||
| + | |||
| + | **1) Free-Running ADC** | ||
| + | |||
| + | * Folosim ADC în Free-Running Mode pentru conversii continue la rata stabilită de prescaler, fără a reporni manual conversia la fiecare eşantion. | ||
| + | |||
| + | * Avantaj: latență minimă între eşantioane și utilizare eficientă a CPU în ISR | ||
| + | |||
| + | |||
| + | **2) Intreruperi** | ||
| + | |||
| + | * toată logica de procesare audio (distorsiune, tremolo, delay) se execută în ISR(ADC_vect), eliminând buclele de polling | ||
| + | |||
| + | * debounce butoane și toggle LED se fac în ISR-uri separate (PCINT2 si TIMER0), evitând blocarea buclei principale. | ||
| + | |||
| + | |||
| + | **3) Math Library** | ||
| + | |||
| + | * Tremolo folosește sinf() din <math.h>, costisitor în cicluri CPU | ||
| + | |||
| + | * Pentru o versiune și mai rapidă, se poate înlocui cu un tabel de valori pre-calculate (lookup table) pentru LFO. | ||
| + | |||
| + | |||
| + | **4) Buffer Circular Fix-Size pentru Delay** | ||
| + | |||
| + | * Delay folosește un buffer circular simplu, cu indexare modulară, pentru acces și scriere în timp constant (O(1)). | ||
| + | * Dimensiunea buffer-ului (980) este un compromis între intârziere perceptibilă și consum de memorie SRAM (≈2 KB). | ||
| + | |||
| + | === Frecvente ale proiectului === | ||
| + | |||
| + | **1) Rata de eşantionare ADC: ~10 kHz** | ||
| + | |||
| + | Prescaler ADC = 64 la 16 MHz → ADC clock ≈ 250 kHz → 25 cicluri pe conversie → ~10 k conversii/s, fiind suficient pentru frecventele relevante ala chitarii. | ||
| + | |||
| + | **2) LFO Tremolo: 5 Hz** | ||
| + | |||
| + | Frecvență perceptibilă plăcută de modulare de volum. Phase increment pre-calculatează saltul de fază pe eşantion, fără recalcule de frecvență în timp real. | ||
| + | |||
| + | **3) Timer Debounce: 1 kHz (1 ms tick)** | ||
| + | |||
| + | Asigură o rata de debounce robustă în maxim 50 ms fără pierderi de evenimente. | ||
| + | |||
| + | **4) I2C (TWI): ~400 kHz** | ||
| + | |||
| + | Comunicarea cu DAC la fast-mode pentru a corespunde celor 10 k eşantioane/s și overhead-ul I2C. | ||
| + | |||
| + | === Estimarea Consumului de Putere === | ||
| + | |||
| + | * Microntroller ATmega328P in mod normal (16 MHz, Vcc = 5 V): ~10–20 mA | ||
| + | | ||
| + | * DAC MCP4725: ~0.5 mA | ||
| + | | ||
| + | * LM358: fiecare canal ~0.7 mA | ||
| + | |||
| + | * LED-uri și Butoane: LED-uri aprinse (3 × 2 mA) = ~6 mA maxim | ||
| + | | ||
| + | **Total:** | ||
| + | I_total≈15mA (MCU)+1mA (DAC)+2mA (LM358)+6mA (LED)**≈24mA** | ||
| + | |||
| + | **Putere:** | ||
| + | P=V×I≈5V×24mA=**120mW** | ||
| + | |||
| + | |||
| + | ===== Concluzii ===== | ||
| + | |||
| + | Acest proiect a fost o modalitate perfecta de a aprofunda cunostiintele atat de proiectarea microprocesoarelor, a laboratoarelor de la aceasta materie, cat si mai important, cunostiintele de electronica. Constructia partii de HARDWARE a fost o provocare. In final, sunt multumita de outcome. :-D | ||
| ===== Jurnal ===== | ===== Jurnal ===== | ||
| Line 268: | Line 414: | ||
| 18 Mai: Descriere detaliata pentru hardware si modificare liste de componente. | 18 Mai: Descriere detaliata pentru hardware si modificare liste de componente. | ||
| + | 25 Mai: Decriere detaliata Software + estimarea puterii consumate si optimizarile facute | ||
| ===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
| - | <note> | + | Datasheet LM358: [[https://www.onsemi.com/download/data-sheet/pdf/lm358-d.pdf | LINK]] |
| - | Listă cu documente, datasheet-uri, resurse Internet folosite, eventual grupate pe **Resurse Software** şi **Resurse Hardware**. | + | |
| - | </note> | + | Datasheet MCP4725: [[https://ww1.microchip.com/downloads/en/devicedoc/22039d.pdf | LINK]] |
| + | |||
| + | Datasheet ArduinoUno ATmega328p: [[https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf | LINK]] | ||
| <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | <html><a class="media mediafile mf_pdf" href="?do=export_pdf">Export to PDF</a></html> | ||
| + | |||
| + | {{:pm:prj2025:fstancu:pm_amp.zip| Arhiva aici}} | ||