This is an old revision of the document!
Acest proiect constă în proiectarea și realizarea unui sintetizator digital autonom, bazat pe microcontrolerul ATmega328P. Dispozitivul este un instrument muzical electronic capabil să genereze sunete prin tehnica DDS (Direct Digital Synthesis).
Sintetizatorul primește comenzi de note muzicale prin interfața serială (de la tastatura unui laptop) și permite modelarea sunetului în timp real folosind o interfață hardware compusă din 5 potențiometre și un buton multifuncțional. Vizualizarea parametrilor se realizează prin intermediul unui ecran OLED de 0.96 inch.
Scopul principal este crearea unui sistem integrat care să demonstreze capacitățile de procesare digitală de semnal ale unui microcontroler de 8 biți. Proiectul urmărește:
Ideea a luat naștere din dorința de a dezvălui modul în care funcționează sintetizatoarele comerciale scumpe. Am pornit de la conceptul de “Digital Audio Workstation (DAW) in a box”, dorind să transfer controlul sunetului din mediul virtual al mouse-ului într-un mediu tactil, unde fiecare modulație a sunetului este rezultatul unei modificări fizice de tensiune prin potențiometre. A fost o provocare de a optimiza codul pentru a obține o latență minimă și o fidelitate audio acceptabilă pe un hardware limitat.
Proiectarea hardware a fost realizată având în vedere două obiective principale: fidelitatea semnalului audio (reducerea zgomotului digital) și ergonomia interfeței de control. Dispozitivul este construit modular, separând etajul de procesare digitală de etajul de amplificare analogică.
| Componentă | Specificații Tehnice | Cantitate | Rol în Proiect |
|---|---|---|---|
| Microcontroler | ATmega328P | 1 | Creierul sistemului, sinteză DDS |
| Display1) | OLED 0.96” I2C (SSD1306) | 1 | Feedback vizual parametri ADSR/Wave |
| Amplificator2) | PAM8403 Stereo 2x3W | 1 | Amplificare semnal audio la nivel de boxe |
| Potențiometre3) | 10kΩ Liniare (B10K) | 5 | Control Attack, Decay, Sustain, Release, Pitch |
| Difuzoare4) | 4Ω, 3W, 40mm | 2 | Redare audio stereo |
| Rezistență | 1kΩ | 1 | Parte a filtrului Low-Pass (RC) |
| Condensator | 100nF (Ceramic 104) | 1 | Filtrare zgomot PWM (Filtru RC) |
| Condensator | 10μF (Electrolitic) | 1 | Cuplaj audio (DC Blocking) |
| Condensator | 1000μF (Electrolitic) | 1 | Stabilizare alimentare amplificator |
| Switch5) | MTS-102 Toggle (Metal) | 1 | Pornire/Oprire generală |
| PCB6) | Prototipare FR4 4x6cm | 2 | Suport electric componente |
| Modul convertor USB la TTL7) | CH340 | 1 | Adaptor la alimentare circuit |
| Modul USB 2.0 la TTL UART8) | CP2104 | 1 | Convertor serial |
Sunetul este generat digital prin PWM (Pulse Width Modulation) la o frecvență purtătoare înaltă. Pentru a obține un semnal audio analogic curat, semnalul parcurge următorul traseu:
Configurația pinilor ATmega328P:
Pentru filtrul de reconstrucție (Low-Pass), am calculat frecvența de tăiere ($f_c$) folosind formula:
$$f_c = \frac{1}{2 \pi R C}$$
Înlocuind valorile alese ($R = 1000 \Omega$ și $C = 100 \times 10^{-9} F$):
Această valoare a fost aleasă pentru a oferi un sunet “cald”, eliminând eficient zgomotul digital ascuțit generat de tactul microcontrolerului.
Notă privind alimentarea: Simularea comportamentului amplificatorului la volum maxim a indicat necesitatea unui condensator de tip “buffer” de 1000μF. Acesta previne resetarea Arduino-ului în momentele în care boxele solicită un curent de vârf (peste 500mA) din bateria de 5V.
Software-ul este organizat modular, fiecare periferic avand propriul modul (synth, usart, adc, i2c, oled), cu separare clara intre fisiere header si implementare.
Nucleul audio foloseste Direct Digital Synthesis (DDS) cu un tabel sinus de 256 esantioane stocat in PROGMEM (Flash), economisind cei 2 KB de SRAM disponibili. Fiecare din cele 4 voci polifonice utilizeaza un acumulator de faza pe 16 biti, al carui byte superior indexeaza direct tabelul — eliminand orice calcul trigonometric la runtime.
Generarea esantioanelor se face in ISR(TIMER1_OVF_vect) la 31250 Hz (Fast PWM 9-bit), avand un buget strict de ~512 cicluri CPU. Toata aritmetica foloseste fixed-point Q8.8 si operatii pe intregi — fara virgula mobila. Mixarea vocilor, aplicarea envelope-ului ADSR si scalarea volumului se reduc la inmultiri si shift-uri pe 16/32 biti, mentinand ISR-ul sub 200 cicluri (~39% din buget).
Envelope-ul ADSR este avansat separat la 1 kHz prin ISR(TIMER2_COMPA_vect) via adsr_tick_voice(), decupland rata lenta a modulatiei de amplitudine de rata rapida de esantionare.
Alocarea vocilor foloseste o strategie in trei pasi: re-trigger daca nota este deja activa, alocare voce libera (IDLE), sau voice stealing bazat pe varsta relativa (scadere modulara uint8_t).
Semnalul PWM porneste centrat la 50% duty (PWM_CENTER=255), generand 0V DC prin condensatorul de cuplaj si eliminand pocniturile la pornire.
Receptia este polling non-blocant (USART0_available() + USART0_read()), evitand overhead-ul unui ISR suplimentar care ar concura cu ISR-urile audio. Transmisia este blocanta per-caracter.
Citirea celor 5 potentiometre (Attack, Decay, Sustain, Release, Volume) se face prin polling la intervale rare, folosind un contor uint8_t cu overflow natural la 256 iteratii — evitand un timer dedicat. Valorile ADC sunt convertite in rate Q8.8 prin calc_rate() si aplicate atomic (cu cli()/sei()).
Scriptul PianoController ruleaza pe Linux (Wayland/X11) fara dependinte grafice, folosind termios raw mode pentru detectia tastelor cu latenta minima. Un mecanism de auto-release cu timere per-nota (_schedule_release()) simuleaza key-up din terminal, care nu ofera nativ acest eveniment. Comunicatia seriala este protejata de un threading.Lock, iar un thread daemon dedicat (serial_reader_thread()) citeste asincron raspunsurile de la ATmega.
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.