Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2025:rnedelcu:cosmin.croitoriu [2025/05/27 09:00]
cosmin.croitoriu
pm:prj2025:rnedelcu:cosmin.croitoriu [2025/05/28 15:56] (current)
cosmin.croitoriu
Line 47: Line 47:
 ===== Software Design ===== ===== Software Design =====
  
 +**Overview**
  
-<note tip> +Partea software a proiectului se bazează pe următoarele etape
-Descrierea codului aplicaţiei (firmware)+    Citește semnalul audio de la intrarea analogică A0folosind în spate ADC-ul integrat. 
-  mediu de dezvoltare (if any) (e.g. AVR StudioCodeVisionAVR) +    Aplică unul din cele 4 efecte
-  librării şi surse 3rd-party (e.gProcyon AVRlib) +    Scalează semnalul rezultat în funcție de valoarea ​ luminozității ambientale, detectată cu un LDR pe A1. 
-  algoritmi şi structuri ​pe care plănuiţi să le implementaţ+    * Trimite semnalul procesat către DAC-ul extern, scalând mai întâi output-ul pentru a fi pe 12 biți. Comunicarea cu DAC-ul se face protocolul I2C. 
-  (etapa 3) surse şfuncţii implementate +    Efectele, cât șintensitatea lor sunt schimbate cu ajutorul butoanelor prin întreruperi 
-</​note>​+Pentru comunicarea cu DAC-ul am folosit biblioteca Adafruit_MCP4725.
  
-===== Rezultate Obţinute ===== 
  
-<note tip> +**Implementarea Efectelor Audio** 
-Care au fost rezultatele obţinute în urma realizării proiectului vostru+  * **Clean**: nu se aplică nimic asupra semnalului și este transmis nemodificat
-</note>+  * **Distorsion**:​ Inputul este amplificat și apoi limitat la o anumită valoare maximă/minimă
  
-===== Concluzii =====+<​code>​ 
 +int distortionEffect(int input) { 
 +  // Centrare în jurul lui 0 
 +  int centered ​input - 512;
  
-===== Download =====+  // Partea de amplificare a semnalului (între 1.5 și 5) 
 +  float gain map(intensity,​ minIntensity,​ maxIntensity,​ 150, 500) / 100.0; 
 +  int boosted ​centered * gain;
  
-<note warning>​ +  // Partea de tăiere a semnalului după un anumit threshold 
-O arhivă (sau mai multe dacă este cazul) cu fişierele obţinute în urma realizării proiectului:​ surseschemeetc. Un fişier READMEun ChangeLogun script de compilare şi copiere automată pe uC crează întotdeauna o impresie bună ;-).+  int threshold = map(intensityminIntensitymaxIntensity512128); 
 +  if (boosted > threshold) boosted = threshold;​ 
 +  if (boosted < -thresholdboosted = -threshold;
  
-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 Alin331CC -> **:​pm:​prj2009:​cc:​dumitru_alin**. +  // Recentrare in 512 
-</note>+  return constrain(boosted + 512, 0, 1023); 
 +
 +</​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, î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>​ 
 +int tremoloEffect(int input) { 
 +  // Nr de frame-uri ca valoarea sinusoidei sa ramana constanta. 
 +  int rate = map(intensity,​ minIntensity,​ maxIntensity,​ 16, 1); 
 + 
 +  // Nr de step-uri sa fie sarite intre sample-uri 
 +  int tremoloStepSize = map(intensity,​ minIntensity,​ maxIntensity,​ 2, 8); 
 + 
 +  step++; 
 +  if (step >= rate) { 
 +    step = 0; 
 +    sample += tremoloStepSize;​ 
 +    if (sample >= 1024) sample -= 1024; 
 +  } 
 + 
 +  // Calculul factorului de scalare pe baza valoriii sinusoidei din fisier 
 +  float tremolo = map(waveform[sample],​ 0, 255, 0, 1000) / 1000.0; 
 +  return input * tremolo; 
 +
 +</​code>​ 
 + 
 +  * **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. 
 +<​code>​ 
 +int bitcrusherEffect(int input) { 
 +  // Nr de nivele 
 +  int bitDepth = map(intensity,​ minIntensity,​ maxIntensity,​ 1, 4); 
 +  int levels = 1 << bitDepth; ​  
 + 
 +  // Diferenta dintre 2 nivele 
 +  int stepSize = 1024 / levels; 
 + 
 +  // Maparea inputului la un nivel din semnal  
 +  int crushed = (input / stepSize) * stepSize;  
 +  return constrain(crushed,​ 0, 1023); 
 +
 +</​code>​ 
 + 
 +**Controlul intensității și schimbarea de efecte**: 
 +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); 
 + 
 +  // Enable pt D4 
 +  PCMSK2 |= (1 << PCINT20);  
 + </​code>​ 
 +  * D2scade 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 78: 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 90: 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>​
  
pm/prj2025/rnedelcu/cosmin.croitoriu.1748325633.txt.gz · Last modified: 2025/05/27 09:00 by cosmin.croitoriu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0