Table of Contents

Procesor digital de efecte pentru chitară

Introducere

Proiectul este un procesor de efecte pentru chitară, care va prelua semnalul de la chitara ca input, îl va procesa digital aplicând diferite efecte sub forma unor funcții matematice, iar apoi îl va transmite către output. Schimbarea efectelor, și modificarea intensității lor, va fi modificată prin butoane, volumul va fi modificat atat printr-un potentiometru, cât și printr-un fotorezistor prin trecerea mâinii deasupra acestuia. Ecranul este folosit pentru afișarea efectului utiilizat, cât și afișarea intensității acestuia. Efectele implementate sunt:

Descriere generală

Schema bloc arată modul general de funcționare al proiectului. Semnalul analogic filtrat de la chitară este convertit în analog folosind modulul ADC de 10 biți al Arduino-ului, iar apoi se face procesarea acestui semnal prin codul scris. Utilizatorul intervine în procesarea semnalului prin butoane și prin fotorezistor, iar tot el primește informații prin display-ul OLED. În final, semnalul este convertit înapoi în analogic folosind DAC-ul extern MCP4725 cu o rezolutie de 12 biți, iar apoi filtrat pentru a fi difuzat cu ajutoul amplificatorului de chitară.

Hardware Design

Nr. Componentă Cantitate Specificații / Comentarii Link către componentă
1 Arduino Uno 1 Microcontroler pentru procesarea semnalului audio https://sigmanortec.ro/Placa-dezvoltare-UNO-R3-Arduino-Compatibil-ATmega328p-CH340G-cu-bara-pini-p170362384
2 Preamplificator op-amp (ex: TL072) 1 Buffer pentru semnalul de intrare de la chitară https://www.emag.ro/circuit-integrat-dip8-texas-instruments-tl072cp-t106485/pd/D40M9YMBM/
3 Rezistențe (4.7kΩ, 10kΩ, 100kΩ, etc.) 5-10 Pentru biasare, divizoare, filtre https://sigmanortec.ro/Kit-Rezistori-si-Potentiometre-A1-p141487466
4 Condensatori (100nF, 10uF, 220nF etc.) 5-10 Pentru filtre de semnal și decuplare https://sigmanortec.ro/Set-120-condensatori-electrolitici-p125779654
5 Convertor D/A extern (ex: MCP4725) 1 DAC pe 12 biți controlat prin SPI https://www.emag.ro/modul-convertor-digital-analog-mcp4725-12bit-i2c-pentru-analiza-eeprom-2-7-5-5v-mcp601/pd/D0Z8WSYBM/
6 Potențiometru (100kΩ) 1 Modificarea amplitudinii semnalului de input https://sigmanortec.ro/Kit-Rezistori-si-Potentiometre-A1-p141487466
7 Amplificator op-amp de ieșire (ex: TL972IPWR) 1 Filtru Sallen-Key 3rd order https://www.tme.com/ca/en/details/tl072cpwr/smd-operational-amplifiers/texas-instruments/
8 Breadboard și fire de conexiune 1 User Interface https://sigmanortec.ro/Breadboard-760-puncte-p190992404
9 Jack 6.3mm stereo (intrare/ieșire) 2 Pentru conectarea chitarei și ieșirii audio https://www.tme.com/ca/en/details/nys215/jack-connectors/rean/
10 Adaptor SSOP8 1 Pentru folosirea op-ampului TL92IPWR https://www.optimusdigital.ro/ro/accesorii-adaptoare-pcb/198-adaptor-pcb-sop8ssop8tssop8-la-dip.html
11 Display 0.96 inch I2C 1 Afișare informații pentru utilizator https://sigmanortec.ro/display-oled-096-i2c-iic-alb

Scheme electrice

Partea de hardware este inspirată din proiectul celor de la ElectroSmash, PedalShield UNO și este împărțită în 3 secțiuni, după cum se poate observa și din poză:

Software Design

Overview

Partea software a proiectului se bazează pe următoarele etape:

Pentru comunicarea cu DAC-ul am folosit biblioteca Adafruit_MCP4725.

Implementarea Efectelor Audio

int distortionEffect(int input) {
  // Centrare în jurul lui 0
  int centered = input - 512;

  // Partea de amplificare a semnalului (între 1.5 și 5)
  float gain = map(intensity, minIntensity, maxIntensity, 150, 500) / 100.0;
  int boosted = centered * gain;

  // Partea de tăiere a semnalului după un anumit threshold
  int threshold = map(intensity, minIntensity, maxIntensity, 512, 128);
  if (boosted > threshold) boosted = threshold;
  if (boosted < -threshold) boosted = -threshold;

  // Recentrare in 512
  return constrain(boosted + 512, 0, 1023);
}

Dar dacă dorim să creștem frecvența tremolo-ului (adică să facem vibrația volumului mai rapidă), avem două opțiuni:

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;
}
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);
}

Controlul intensității și schimbarea de efecte: Pentru un răspuns rapid și a elimina overhead-ul, am utilizat întreruperi: Trei butoane sunt folosite:

// Enable la PCINTs
  PCICR |= (1 << PCIE2);

  // Enable pt D4
  PCMSK2 |= (1 << PCINT20); 
 

Î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.

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);
}

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.

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;
}

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.

dac.setVoltage(scaled << 2, false);  // false = fără scriere în EEPROM

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.

float getVolumeFromLDR() {
  int ldr = analogRead(A1);
  int volumeInt = map(ldr, 300, 700, 1000, 0);
  volumeInt = constrain(volumeInt, 0, 1000);
  return volumeInt / 1000.0;
}

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

Bibliografie/Resurse

Datasheet DAC MCP4725 Pedal Shield Uno

Codul efectelor pentru Pedal Shield

Father of Electronics

Proiect inspiratie

Arhiva cod

Export to PDF