Proiectul constă într-un procesor de efecte audio digital pentru chitară electrică, realizat cu ajutorul unui Arduino UNO (ATmega328), care aplică efecte audio (ex: distorsiune, tremolo, delay) semnalului de la chitară.
Scopul proiectului este de a oferi o soluție accesibilă și personalizabilă pentru chitariști, care le permite să adauge diverse efecte audio chitarii lor folosind un procesor digital realizat cu Arduino. Proiectul își propune să înlocuiască echipamentele de efecte tradiționale costisitoare, oferind un control total asupra parametrilor fiecărui efect.
În plus, proiectul permite extinderea prin adăugarea de noi efecte sau îmbunătățiri, ceea ce îl face o platformă ideală pentru învățare și experimentare continuă.
Chitara se va conecta la procesorul de efecte printr-o mufa Jack 6.3 mm. Procesorul are 3 butoane si 3 LEDs care reprezinta cate un efect:
Deoarece semnalul de la chitara este unul slab, acesta va trece printr-un amplificator LM358. Apoi va trece in convertorul ADC din Arduino, procesat, iar apoi trimis la convertorul DAC MCP4725, apoi se poate alege volumul care trece ca output prin a doua mufa jack 6.3 mm unde va fi conectata o boxa.
1. Intrarea semnalului de chitară (jack intrare)
2. Etajul de amplificare cu LM358 (U1:A și U1:B)
LM358 este un amplificator operațional dual (două canale într-un singur cip). Primul canal este folosit pentru amplificarea semnalului de intrare.
U1:A - Amplificator cu feedback
U1:B - Etaj suplimentar de amplificare
3. Potențiometru volum (RV2 - 10 kΩ)
4. MCP4725 - DAC extern
5. Butoanele și LED-urile
Interfete
Link catre poze si video demonstrativ: aici
Din simplul fapt ca acest proiect lucreaza si proceseaza semnal audio, inseamna ca partea de cod trebuie sa functioneze foarte repede si sa faca masuratori (esantioane) foarte rapid (sample rate). Deci sample rate mare → frecventa mare. Acest lucru nu se pot obtine cu biblioteci Arduino, deci singura solutie a fost de a lucra in PlatformIO in maniera de la laborator.
1. GPIO
Am folosit pini digitali PD2, PD3, PD4 ca intrări cu pull-up pentru butoane și PB2, PB3, PB4 ca ieșiri pentru LED-uri.
2. ADC (Converto Analog-Digital)
Convertirea semnalului audio, adica analog, in digital pentru prelucrare si aplicarea efectelor selectate, apoi pasarea datelor la DAC. De asemnea, este configurat în Free-Running Mode pentru eșantionare continuă la ~10 kHz.
3. Timer(CTC)
Am folosit Timer0 CTC, folosit in tratarea intreruperilor pentru button debounce
4. I2C (TWI)
MCP4725 (DAC) functioneaza prin protocolul I2C, de asemenea este si rapid.
5. Intreruperi (ISR)
Toate interactiunile externe functioneaza cu intreruperi pentru optimizarea codului si a timpului de executie, pentru a nu afecta frecventa pentru sample rate. Am folosit intreruperi pentru:
Rol: Interfața I²C (TWI) generică, folosită pentru a comunica cu DAC-ul MCP4725 la ~400 kHz.
Ce face fiecare functie:
1) twi_init()
TWSR = 0x00;
→ prescaler = 1TWBR = 12;
→ bit-rate generator pentru SCL ≈ 400 kHz la 16 MHzTWCR = (1«TWEN);
→ activează modul TWI (SDA/SCL)
2) twi_start(address)
TWCR = (1«TWSTA)|(1«TWEN)|(1«TWINT);
→ emite condiția START
3) twi_write(data)
TWDR = data;
TWCR = (1«TWEN)|(1«TWINT);
→ începe transmiterea
4) twi_stop()
TWCR = (1«TWSTO)|(1«TWEN);
→ emite STOPRol: : Strat de abstracție peste TWI pentru a scrie rapid valori 12-biți în MCP4725.
Ce fac functiile:
1) dac_init()
twi_init()
2) mcp4725_write(val)
twi_start(addr|0)
→ trimite pe magistrală condiția START, apoi adresa de 7 biți a DAC-ului (0x62) urmată de bitul R/W=0 (scriere).twi_write(0x40)
→ fast-mode commandtwi_write(val»4)
→ cei 8 biți ai codului DAC de 12 biți, adică biții de ordin înalt D11…D4twi_write1)
→ Trimite următorii 4 biți (D3…D0), puși în nibble-ul superior al octetului:
Octet 1 = [ D11 D10 D9 D8 D7 D6 D5 D4 ]
Octet 2 = [ D3 D2 D1 D0 0 0 0 0 ]
twi_stop()
- trimite conditia de STOP si elibereaza magistrala I2CMCP4725 în fast-mode aşteaptă un octet de comandă, apoi doi octeți de date ce conțin cei 12 biți de nivel pe DAC. Primul transportă biții cei mai semnificativi (MSB), al doilea transportă cei mai puțin semnificativi (LSB) “aliniati” în nibble-ul de sus, pentru ca DAC-ul să știe exact cum să le reasambleze.
Rol: Procesarea semnalului convertit in digital, aplicand efectele stabilite: distorsiune, tremolo, delay
Creaza o forma de unda distorsionata si ascutita, cu tranzitiii rapide pentru un sunet “heavy”.
Amplifică ușor frecvențele medii și înalte pentru mai mult „bite”
y=x⋅(0.7+0.3⋅∣x∣)
Tranziție netedă la limită.
y=tanh(gain⋅y)
Taie vârfurile peste ±0.8 pentru senzație agresivă.
y=max(min(y,+0.8),−0.8)
Pentru că DAC-ul MCP4725 lucrează cu rezoluţie de 12 biţi (domeniu numeric 0…4095), trebuie să mapăm semnalul nostru normalizat (−1…+1) pe acest interval.
Astfel, pentru un semnal normalizat x∈[−1,1]x∈[−1,1], codul final este
DAC_code=⌊x⋅2047⌋+2048
asigurând conversia corectă pe 12 biţi.
Acest efect oscileaza volumul semnalului la o frecvență joasă (LFO) pentru „vibrato de volum”.
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.
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ă).
Apoi multiplicăm semnalul de intrare cu un amestec între volumul original și valoarea LFO:
Dacă LFO este aproape de 1, semnalul are volum aproape normal.
Dacă LFO este aproape de 0, semnalul este atenuat (mai silențios).
Prin schimbarea „adâncimii” (depth) poți controla cât de puternică este această variație de volum.
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.
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.
Rol: Preluare continuă de semnal analogic și declanșare ISR pentru procesare.
Avem urmatoarele setari pentru registre:
ADMUX = (1«REFS0);
- REFS0=1 → referință AVcc, canal ADC0ADCSRA = 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-RunDIDR0 = (1«ADC0D)
; → dezactivează intrare digitală pe ADC0ADCSRA |= (1«ADSC);
→ pornește prima conversieIntreruperile folosite:
ISR(ADC_vect)
De ce Free-Running? Vrem eșantionare continuă la frecvență fixă, fără să declanșăm singur fiecare conversie. Asa obtinem eficienta mai buna.
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)
ISR(TIMER0_COMPA_vect)
De ce PCINT + timer? Detectăm rapid schimbarea de buton și facem debounce fără blocări în bucla principală.
Inițializează toate modulele și intră în buclă infinită.
Flux general:
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.
1) Free-Running ADC
2) Intreruperi
3) Math Library
4) Buffer Circular Fix-Size pentru Delay
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.
Total: I_total≈15mA (MCU)+1mA (DAC)+2mA (LM358)+6mA (LED)≈24mA
Putere: P=V×I≈5V×24mA=120mW
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.
7 Mai: Descriere poriect si adaugarea listei de piese
18 Mai: Descriere detaliata pentru hardware si modificare liste de componente.
25 Mai: Decriere detaliata Software + estimarea puterii consumate si optimizarile facute