Differences

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

Link to this comparison view

pm:prj2024:alucaci:teofil.padurariu [2024/05/23 00:13]
teofil.padurariu
pm:prj2024:alucaci:teofil.padurariu [2024/05/23 00:54] (current)
teofil.padurariu [Bibliografie]
Line 44: Line 44:
 {{:​pm:​prj2024:​alucaci:​guitar_tuner_hardware.jpg?​700|}} {{:​pm:​prj2024:​alucaci:​guitar_tuner_hardware.jpg?​700|}}
 ===== Implementare Software ===== ===== Implementare Software =====
-==== Descriere ==== 
 Este un proiect software-heavy. Este un proiect software-heavy.
  
-=== INPUTUL ȘI PROCESAREA SA ===+==== INPUTUL ȘI PROCESAREA SA ====
 Core-ul tunerului este Arduino Nano. Pe pinul A0 vor veni datele de la microfonul cu ajutorul căruia se captează semnalul analogic generat de vibrația corzii de chitară. Pentru a putea prelucra semnalul de intrare, este necesară eșantionarea acestuia de către ADC. Core-ul tunerului este Arduino Nano. Pe pinul A0 vor veni datele de la microfonul cu ajutorul căruia se captează semnalul analogic generat de vibrația corzii de chitară. Pentru a putea prelucra semnalul de intrare, este necesară eșantionarea acestuia de către ADC.
  
 Procesarea semnalului presupune descompunerea sa din amplitudine(timp) în amplitudine(frecvență),​ găsirea frecvenței de magnitudine maximală și compararea acesteia cu frecvența de referință specifică celei mai apropiate note de aceasta. Este necesar acest proces datorită faptului că semnalul generat de chitara este aperiodic. Conține o multitudine de armonice, care se însumează și formează întregul semnal (matematic, semnalul poate fi gandit ca o însumare de funcții sinus/​cosinus). La nivel software, această descompunere poate fi realizată prin aplicarea transformării Fourier pe semnalul de intrare, implementată prin algoritmul **Fast Fourier Transform** (FFT). Procesarea semnalului presupune descompunerea sa din amplitudine(timp) în amplitudine(frecvență),​ găsirea frecvenței de magnitudine maximală și compararea acesteia cu frecvența de referință specifică celei mai apropiate note de aceasta. Este necesar acest proces datorită faptului că semnalul generat de chitara este aperiodic. Conține o multitudine de armonice, care se însumează și formează întregul semnal (matematic, semnalul poate fi gandit ca o însumare de funcții sinus/​cosinus). La nivel software, această descompunere poate fi realizată prin aplicarea transformării Fourier pe semnalul de intrare, implementată prin algoritmul **Fast Fourier Transform** (FFT).
 index_nota index_nota
-=== BIBLIOTECI EXTERNE ===+ 
 +==== BIBLIOTECI EXTERNE ​====
 Pentru implementarea tuner-ului, am folosit 2 biblioteci externe: Pentru implementarea tuner-ului, am folosit 2 biblioteci externe:
   * arduinoFFT: [[https://​github.com/​kosme/​arduinoFFT|GitHub]]   * arduinoFFT: [[https://​github.com/​kosme/​arduinoFFT|GitHub]]
Line 93: Line 93:
 </​code>​ </​code>​
  
-Pentru generarea tuturor frecvențelor de referință am pornit de la nota A4, ce are frecvența f0 = 440.0Hz. Toate celelalte frecvențe se vor afla pornind de la aceasta: f = f0 * 2 ^ (( NOTE_INDEX - A4_INDEX) / 12)Am generat 64 de note, începând la A0 și mergând până la ultima notă sub 1000Hz. Pentru aflarea indexului cele mai apropiate note de frecvența maximală detectată, am scos din ecuația precedentă pe index_notă. Astfel am obținut formula:+Pentru generarea tuturor frecvențelor de referință am pornit de la nota A4, ce are frecvența f0 = 440.0Hz. Toate celelalte frecvențe se vor afla pornind de la aceasta: 
 + 
 +<​code>​ 
 +f = f0 * 2 ^ ((NOTE_INDEX - A4_INDEX) / 12) 
 +</​code>​ 
 + 
 +Am generat 64 de note, începând la A0 și mergând până la ultima notă sub 1000Hz. Pentru aflarea indexului cele mai apropiate note de frecvența maximală detectată, am scos din ecuația precedentă pe index_notă. Astfel am obținut formula:
  
 <​code>​ <​code>​
 int closest = round(12 * log(peak / A4_FREQ) / log(2.0)) + A4_INDEX; int closest = round(12 * log(peak / A4_FREQ) / log(2.0)) + A4_INDEX;
-<​code/>​+// pentru aflarea frecvenței de la indexul closest 
 +freq[closest] 
 +</code
 + 
 +**Detecția deviației**:​ 
 + 
 +Avem 4 cazuri: 
 +  * Dacă frecvența se află în intervalul (ref - REF_RNG, ref + REF_RNG), unde REF_RNG este o eroare (1 setata in software), atunci coarda este acordata 
 +  * Dacă frecvența detectată este mai mică decât frecvența de referință,​ numărul de segmente care ilustrează cu cât este mai jos aceasta față de cealaltă va fi: 
 + 
 +<​code>​ 
 +float step = (ref - lower) ​14.0; 
 +int16_t seg_num = (uint16_t)((ref - peak) / step); 
 +if (seg_num < 7) seg_num++;​ 
 +</code> 
 + 
 +  * Dacă frecvența detectată este mai mare decât frecvența de referință,​ numărul de segmente care ilustrează cu cât este mai jos aceasta față de cealaltă va fi: 
 + 
 +<​code>​ 
 +float step = (higher - ref) / 14.0; 
 +uint16_t seg_num = (uint16_t)((peak - ref) / step); 
 +if (seg_num < 7) seg_num++;​ 
 +</​code>​ 
 + 
 +  * Dacă amplitudinea nu este îndeajuns de mare încât tunerul să o considere input, atunci LCD-ul va afișa ”Play some notes”. 
 + 
 +**LCD-ul** este folosit pentru afișarea rezultatului procesării,​ alături de LED-ul RGB ce indică starea curentă a tuner-ului. Arduino Nano comunică prin protocolul I2C cu LCD-ul (vezi **labul de I2C**). Am creat 7 caractere custom pentru segmente, care au fost încărcare la inițializarea tuner-ului în memoria controllerului LCD-ului, la adresele 0x0-0x6. Biblioteca permite, prin apelarea unor funcții simple, afișarea caracterelor pe display. 
 + 
 +Let's see some code: 
 + 
 +<​code>​ 
 +LCD.init(); // Initializare I2C 
 +LCD.backlight();​ // Pornire backlight 
 +LCD.setCursor(0,​ 0); // Setare cursor in poziția de scriere (linia 0, caracter 0) 
 +LCD.print("​Guitar Tuner v1"); // Afișare string pe ecran 
 +LCD.clear();​ // Ștergere caractere de pe ecran 
 +LCD.setCursor(0,​ 0); 
 +LCD.write(0x1);​ // Afișarea caracterului de la poziția 0x1 în memoria controllerului LCD-ului. 
 +</​code>​ 
 + 
 +Pentru schimbarea culorii LED-ului am folosit **labul de GPIO**. 
 + 
 +==== CALIBRARE + OPTIMIZARE COD ==== 
 +Pentru că nu am avut hardware-ul necesar să măresc buffer sizeul pentru rezultate mai accurate, am făcut o funcție care întoarce erorile specifice pentru anumite range-uri de frecvențe (le-am determinat experimental):​ 
 + 
 +<​code>​ 
 +float get_fft_error(float f) { 
 + if (f >= freq[0] && f < 200.0) { 
 + return 2.0; 
 + } else if (f >= 200.0 && f < 300.0) { 
 + return 4.0; 
 + } else if (f >= 300.0 && f < 400.0) { 
 + return 6.0; 
 + } else if (f >= 300.0 && f < 400.0) { 
 + return 8.0; 
 + } else { 
 + return 10.0; 
 +
 +
 +</​code>​ 
 + 
 +===== Download ===== 
 +{{:​pm:​prj2024:​alucaci:​guitar_tuner.zip|}} 
 + 
 +===== Bibliografie ===== 
 +  * FFT: [[https://​en.wikipedia.org/​wiki/​Fast_Fourier_transform#:​~:​text=A%20Fast%20Fourier%20Transform%20(FFT,​frequency%20domain%20and%20vice%20versa. | see]] 
 +  * FFT Windowing: [[https://​download.ni.com/​evaluation/​pxi/​Understanding%20FFTs%20and%20Windowing.pdf|see]] 
 +  * ATMega328P: [[https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf | see]] 
 +  * LCD: [[https://​www.openhacks.com/​uploadsproductos/​eone-1602a1.pdf | see]] 
 +  * LED RGB: [[https://​datasheetspdf.com/​datasheet/​KY-016.html|see]]
pm/prj2024/alucaci/teofil.padurariu.1716412422.txt.gz · Last modified: 2024/05/23 00:13 by teofil.padurariu
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