This shows you the differences between two versions of the page.
pm:prj2025:rnedelcu:cosmin.croitoriu [2025/05/27 22:25] cosmin.croitoriu - |
pm:prj2025:rnedelcu:cosmin.croitoriu [2025/05/28 15:56] (current) cosmin.croitoriu |
||
---|---|---|---|
Line 48: | Line 48: | ||
**Overview** | **Overview** | ||
+ | |||
Partea software a proiectului se bazează pe următoarele etape: | Partea software a proiectului se bazează pe următoarele etape: | ||
* Citește semnalul audio de la intrarea analogică A0, folosind în spate ADC-ul integrat. | * Citește semnalul audio de la intrarea analogică A0, folosind în spate ADC-ul integrat. | ||
Line 58: | Line 59: | ||
**Implementarea Efectelor Audio** | **Implementarea Efectelor Audio** | ||
- | - **Clean**: nu se aplică nimic asupra semnalului și este transmis nemodificat. | + | * **Clean**: nu se aplică nimic asupra semnalului și este transmis nemodificat. |
- | - **Distorsion**: Inputul este amplificat și apoi limitat la o anumită valoare maximă/minimă | + | * **Distorsion**: Inputul este amplificat și apoi limitat la o anumită valoare maximă/minimă |
<code> | <code> | ||
int distortionEffect(int input) { | int distortionEffect(int input) { | ||
Line 79: | Line 81: | ||
</code> | </code> | ||
- | - **Tremolo**: Modifică volumul în timp folosind o undă sinusoidală. Pentru a face codul mai eficient, nu am folosit funția sin din math.h, ci am salvat valorile sinusoidei într-un fișier separat. | + | * **Tremolo**: Modifică volumul în timp folosind o undă sinusoidală. Pentru a face codul mai eficient, nu am folosit funția sin din math.h, ci am salvat valorile sinusoidei într-un fișier separat, într-un vector. Fiecare valoare din acest vector reprezintă un coeficient de volum între 0 și 1, care este aplicat semnalului audio pentru a-l face mai tare sau mai slab în mod ciclic. Dacă parcurgem vectorul pas cu pas, adică câte un eșantion la fiecare buclă, vom avea o frecvență joasă de modulare (efectul tremolo va suna lent). |
+ | |||
+ | Dar dacă dorim să creștem frecvența tremolo-ului (adică să facem vibrația volumului mai rapidă), avem două opțiuni: | ||
+ | |||
+ | * Scădem timpul între eșantioane (frecvența cu care se face sample++) (rate) | ||
+ | |||
+ | * Parcurgem mai rapid vectorul – adică sări peste eșantioane: sample += tremoloStepSize | ||
<code> | <code> | ||
int tremoloEffect(int input) { | int tremoloEffect(int input) { | ||
Line 100: | Line 108: | ||
} | } | ||
</code> | </code> | ||
- | ===== Rezultate Obţinute ===== | ||
- | <note tip> | + | * **BitCrusher**: Efectul bitcrusher constă în scăderea rezoluției semnalului audio, adică în reducerea numărului de biți folosiți pentru a reprezenta fiecare eșantion. În loc de un semnal fluid de 10 biți (0–1023, pe Arduino), semnalul este „zdrobit” în trepte mari, ceea ce duce la un sunet digital, agresiv. În proiect am folosit folsit între 4 și 64 de nivele. |
- | Care au fost rezultatele obţinute în urma realizării proiectului vostru. | + | <code> |
- | </note> | + | int bitcrusherEffect(int input) { |
+ | // Nr de nivele | ||
+ | int bitDepth = map(intensity, minIntensity, maxIntensity, 1, 4); | ||
+ | int levels = 1 << bitDepth; | ||
- | ===== Concluzii ===== | + | // Diferenta dintre 2 nivele |
+ | int stepSize = 1024 / levels; | ||
- | ===== Download ===== | + | // Maparea inputului la un nivel din semnal |
+ | int crushed = (input / stepSize) * stepSize; | ||
+ | return constrain(crushed, 0, 1023); | ||
+ | } | ||
+ | </code> | ||
- | <note warning> | + | **Controlul intensității și schimbarea de efecte**: |
- | 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ă ;-). | + | Pentru un răspuns rapid și a elimina overhead-ul, am utilizat întreruperi: |
+ | Trei butoane sunt folosite: | ||
+ | * D4: schimbă efectul (prin întrerupere **PCINT**): Folosim PCINT, deoarce D4 nu are întrerupere INT. Astfel, avem nevoie de o condiție suplimentară pentru a nu se activa întreruperea pe ambele fronturi. | ||
+ | <code> | ||
+ | // Enable la PCINTs | ||
+ | PCICR |= (1 << PCIE2); | ||
- | 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**. | + | // Enable pt D4 |
- | </note> | + | PCMSK2 |= (1 << PCINT20); |
+ | </code> | ||
+ | * D2: scade intensitatea (prin întrerupere **INT0**): Întreruperea este activată pe frontul negativ HIGH to LOW. | ||
+ | * D3 crește intensitatea (prin întrerupere **INT1**) Întreruperea este activată pe frontul negativ HIGH to LOW. | ||
+ | În toate cazurile am folosit o măsură de a evita debounce-ul folosind niște variabile care rețin timestamp-ul ultimei schimbări. | ||
+ | |||
+ | **Conversia Analog-Digital**: Pentru prelucrarea semnalului de la chitară, am folosit convertorul analog-digital intern al Arduino-ului, configurat manual pentru a controla mai precis performanța și viteza de eșantionare. | ||
+ | Inițializarea se face în funcția setupADC() prin care se se setează referința la AVcc, se activează ADC-ul și se se setează prescaler-ul la 64. | ||
+ | <code> | ||
+ | void setupADC() { | ||
+ | // AVcc ca referinta si calanalul 0 by default | ||
+ | ADMUX = (1 << REFS0); | ||
+ | |||
+ | // Enable la ADC su Prescaler 64 | ||
+ | ADCSRA = (1 << ADEN) | ||
+ | | (1 << ADPS2) | (1 << ADPS1); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Pentru citire în bucla de loop, se schimbă canalul între A0 și A1 (folosim A1 pentru fotorezistor), iar apoi se porneste conversia și se asteaptă terminarea. | ||
+ | <code> | ||
+ | uint16_t readADC(uint8_t pin) { | ||
+ | // Setam canalul, 0 sau 1. | ||
+ | ADMUX = (ADMUX & 0xF0) | (pin & 0x0F); | ||
+ | |||
+ | // Start conversie | ||
+ | ADCSRA |= (1 << ADSC); | ||
+ | |||
+ | // Se asteapta pana conversia este terminata | ||
+ | while (ADCSRA & (1 << ADSC)); | ||
+ | |||
+ | return ADC; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | **Conversia Digital-Analog**: Semnalele procesate sunt trimise la DAC-ul **MCP4725**, care are implicit adresa 0x60, și care funcționează pe **protocolul I2C**. Valoarea de 10 biți este transformată într-una de 12 biți prin shiftare la stânga. | ||
+ | |||
+ | <code> | ||
+ | dac.setVoltage(scaled << 2, false); // false = fără scriere în EEPROM | ||
+ | </code> | ||
+ | |||
+ | **Controlul Volumului prin Fotorezistor**: La pinul A1 este conectat potențialul divizorului de tensiune din care face parte fotorezistorului, astfel încât, când fotorezistorul nu este acoperit, potențialul este mic, iar atunci când este acoperit, potențialul este mare. Acest potențial ajustează volumul semnalului. | ||
+ | <code> | ||
+ | float getVolumeFromLDR() { | ||
+ | int ldr = analogRead(A1); | ||
+ | int volumeInt = map(ldr, 300, 700, 1000, 0); | ||
+ | volumeInt = constrain(volumeInt, 0, 1000); | ||
+ | return volumeInt / 1000.0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ===== Concluzii și Rezultat ===== | ||
+ | Implementarea finală oferă un procesor de efecte simplu și modular, care imită decent cele 3 efecte. Rezultatul este unul satisfăcător, sunetul fiind destul de bun pentru procesarea cu un Arduino Uno. Drept îmbunătățire, aș încerca să fac codul low-level, fără bibliotecile Arduino, astfel putând să obțin atât o procesare mai bună a sunetului, dar și posibilitatea de a adăuga noi efecte. | ||
+ | Proiectul a fost unul foarte interesant, care m-a făcut să înțeleg mai bine noțiunile de la laboratorul de PM, și să îmi aprofundez cunoștiințele de electronică. Cel mai mult m-am distrat la partea hardware, la lipit. Nu pot să exprim în cuvinte fericirea pe care am simțit-o atunci când am văzut că trece semnalul de chitară nedistorsionat :-D | ||
===== Jurnal ===== | ===== Jurnal ===== | ||
Line 122: | Line 196: | ||
* 12.4.2025: Am facut partea de output doar cu un singur filtru trece jos, pentru a testa sunetul. Deoarece sunetul nu era grozav, am decvis să folosesc filtrul Sallen Key. | * 12.4.2025: Am facut partea de output doar cu un singur filtru trece jos, pentru a testa sunetul. Deoarece sunetul nu era grozav, am decvis să folosesc filtrul Sallen Key. | ||
* 14.4.2025: Am făcut output stage-ul, folosind filtrul Sallen Key. Drept amplificator am folosit TL972, pe care l-am pus pe PCB cu ajutorul unui adaptor SMD, după **multe ore de chin** pentru a-l lipi. Neașteptat, chiar a funcționat! | * 14.4.2025: Am făcut output stage-ul, folosind filtrul Sallen Key. Drept amplificator am folosit TL972, pe care l-am pus pe PCB cu ajutorul unui adaptor SMD, după **multe ore de chin** pentru a-l lipi. Neașteptat, chiar a funcționat! | ||
+ | {{:pm:prj2025:rnedelcu:adaptor.png?200|}} | ||
* 16.4.2025: Am implementat primele versiuni ale distorsion-ului si al tremolo-ului. Observ ca sunetul este destul de "muffled", probabil din cauza filtrelor de 5kHz. | * 16.4.2025: Am implementat primele versiuni ale distorsion-ului si al tremolo-ului. Observ ca sunetul este destul de "muffled", probabil din cauza filtrelor de 5kHz. | ||
- | * 18.4.2025: Adaugare a butoanelor care modifica intensitatea efectului si a fotorezistorului. | + | * 18.4.2025: Adaugare a butoanelor care modifica intensitatea efectului si a fotorezistorului. |
+ | * 23.4.2025: Am observat că ceva s-a întâmplat cu procesorul plăcii, deoarece nu mai trimite bine semnalul. cu același cod folosit... A trebuit să renunț l ecran pentru a obține un sunet decent. | ||
+ | * 25.4.2025: Finalizare proiect + pagină de OCW. | ||
===== Bibliografie/Resurse ===== | ===== Bibliografie/Resurse ===== | ||
+ | [[https://ww1.microchip.com/downloads/en/devicedoc/22039d.pdf|Datasheet DAC MCP4725]] | ||
[[https://www.electrosmash.com/pedalshield-uno|Pedal Shield Uno]] | [[https://www.electrosmash.com/pedalshield-uno|Pedal Shield Uno]] | ||
Line 134: | Line 212: | ||
[[https://ocw.cs.pub.ro/courses/pm/prj2017/ddragomir/cmihalache|Proiect inspiratie]] | [[https://ocw.cs.pub.ro/courses/pm/prj2017/ddragomir/cmihalache|Proiect inspiratie]] | ||
+ | |||
+ | {{:pm:prj2025:rnedelcu:cosmin_proiect_pm.zip|Arhiva cod}} | ||
<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> | ||