This is an old revision of the document!


Vocal Coach

Ciprian-Marian Munteanu, 332CB

Introducere

Vocal Coach este un dispozitiv embedded care ajuta utilizatorul sa exerseze intonatia vocala. Dispozitivul reda o nota muzicala de referinta folosind un buzzer pasiv, capteaza vocea utilizatorului printr-un microfon analogic cu amplificare, analizeaza semnalul audio folosind algoritmul Goertzel si ofera feedback in timp real: nota cantata este prea joasa (LOW), corecta (OK) sau prea inalta (HIGH).

Ideea a pornit de la nevoia unui instrument simplu si accesibil pentru incepatorii in muzica, care sa permita exersarea intonatiei fara a depinde de un smartphone sau conexiune la internet. Spre deosebire de aplicatiile generale de tuning, acest dispozitiv este construit special pentru antrenament vocal pe un set restrans de note (A2-A3), ceea ce il face fezabil pe hardware cu resurse limitate.

Repository GitHub: https://github.com/ciprianmunteanu1/vocal-coach

Descriere generala

Sistemul este organizat in urmatoarele module:

Module hardware:

  • Intrare audio — microfon MAX4466 capteaza vocea utilizatorului, iesirea analogica conectata la ADC-ul Arduino
  • Iesire audio — buzzer pasiv reda nota de referinta prin PWM
  • Feedback vizual — modul LED semafor (rosu/galben/verde)
  • Afisaj — OLED 128×64 I2C afiseaza starea sistemului, nota tinta si rezultatul
  • Intrare utilizator — 3 butoane (START/NEXT/BACK) si potentiometru pentru selectarea notei tinta

Module software:

  • Masina de stari — IDLE → PLAY_NOTE → LISTEN_ANALYZE → RESULT
  • Esantionare ADC — citire microfon pe ADC0 si potentiometru pe ADC1
  • Motor Goertzel contextual — compara nota tinta cu vecinii sai inferior si superior
  • Validare semnal — detectie amplitudine prea mica si clipping
  • Logica feedback — decide LOW, OK, HIGH, NO SIG sau LOUD

Interactiunea modulelor: Utilizatorul selecteaza nota tinta cu potentiometrul. La apasarea START, Arduino reda nota pe buzzer, apoi intra intr-o fereastra de ascultare in care ADC-ul esantioneaza microfonul. Algoritmul Goertzel contextual proceseaza semnalul in mod streaming si compara energia pentru nota tinta, nota inferioara si nota superioara. Rezultatul este afisat pe OLED si prin modulul LED.

Hardware Design

Lista de componente

Componenta Cantitate Rol
Arduino Nano ATmega328P + CH340 1 Microcontroller principal
Modul microfon MAX4466 ajustabil 1 Intrare audio
Afisaj OLED 128×64 I2C SSD1306 1 Afisare informatii
Buzzer pasiv 5V 1 Redare nota de referinta
Modul LED semafor 3.3-5V 1 Feedback vizual
Buton tactil 6x6x5mm 3 Intrare utilizator
Potentiometru 10K WH148 1 Selectare nota tinta
Tranzistor NPN 2N2222 / BC337 1 Driver pentru buzzer
Rezistor 1K ohm 1 Limitare curent baza tranzistor
Rezistor 220 ohm 5 Limitare curent LED-uri / rezerve
Condensator electrolitic 10uF 2 Filtrare alimentare
Condensator ceramic 100nF 1 Decuplare locala microfon, optional
Breadboard 830 puncte 1 Platforma de prototipare
Fire Dupont tata-tata / mama-tata 40+40 Interconectare
Cablu USB 1 Alimentare si programare

Schema electrica

Schema electrica prezinta conexiunile dintre Arduino Nano si modulele externe. Microfonul MAX4466 este conectat la intrarea analogica A0, potentiometrul la A1, OLED-ul foloseste magistrala I2C prin pinii A4/SDA si A5/SCL, iar buzzerul pasiv este controlat de pe pinul D9.

In varianta finala, buzzerul este comandat printr-un tranzistor NPN pentru a evita solicitarea directa a pinului microcontrollerului. Pentru primele teste, buzzerul poate fi conectat temporar direct intre D9 si GND, dar varianta cu tranzistor este preferata pentru montajul final.

Butoanele sunt conectate intre pini digitali si GND, urmand sa fie citite in software folosind rezistentele interne de pull-up ale microcontrollerului. Modulul LED semafor este controlat prin trei pini digitali separati, cate unul pentru fiecare culoare.

Tabel conexiuni

Semnal / Componenta Pin componenta Pin Arduino Nano Observatii
MAX4466 VCC 5V Alimentare modul microfon
MAX4466 GND GND Masa comuna
MAX4466 OUT A0 Semnal audio analogic catre ADC
Potentiometru 10K pin lateral 1 5V Capat divizor de tensiune
Potentiometru 10K pin mijloc A1 Valoare analogica pentru selectarea notei
Potentiometru 10K pin lateral 2 GND Masa
OLED SSD1306 VCC 5V Alimentare display, daca modulul este compatibil 3V-5V
OLED SSD1306 GND GND Masa comuna
OLED SSD1306 SDA A4 / SDA Magistrala I2C
OLED SSD1306 SCL A5 / SCL Magistrala I2C
Buzzer pasiv + 5V Alimentare buzzer in varianta cu tranzistor
Buzzer pasiv - Colector tranzistor NPN Comandat prin tranzistor
Tranzistor NPN Baza D9 prin rezistor 1K Semnal BUZZER_DRV
Tranzistor NPN Colector Buzzer - Comutare buzzer catre GND
Tranzistor NPN Emitor GND Masa comuna
LED semafor R D4 LED rosu, feedback LOW
LED semafor Y D5 LED galben, redare nota / feedback HIGH
LED semafor G D6 LED verde, feedback OK
LED semafor GND GND Masa comuna
Buton START pin 1 D2 Configurat INPUT_PULLUP
Buton START pin 2 GND Apasat = LOW
Buton NEXT pin 1 D3 Configurat INPUT_PULLUP
Buton NEXT pin 2 GND Apasat = LOW
Buton BACK pin 1 D7 Configurat INPUT_PULLUP
Buton BACK pin 2 GND Apasat = LOW
Condensator 10uF + 5V Filtrare alimentare
Condensator 10uF - GND Atentie la polaritate
Condensator 100nF intre VCC si GND langa MAX4466 Optional, decuplare locala

Alimentare

Dispozitivul este alimentat prin portul USB al placii Arduino Nano, de la laptop sau de la un power bank de 5V. Alimentarea prin USB este suficienta pentru versiunea curenta a proiectului, deoarece modulele folosite au consum redus: microfonul MAX4466, OLED-ul, buzzerul pasiv si modulul LED semafor.

Toate modulele folosesc masa comuna (GND). Alimentarea de 5V este distribuita catre microfon, OLED, potentiometru, modul LED si buzzer.

Pentru reducerea zgomotului pe alimentare, se folosesc condensatori de filtrare intre 5V si GND. Condensatorul electrolitic de 10uF ajuta la stabilizarea alimentarii, iar un condensator ceramic de 100nF poate fi adaugat langa microfon pentru decuplare locala.

Software Design

Implementarea finala este realizata in PlatformIO, in C bare-metal pentru Arduino Nano cu microcontroller ATmega328P la 16 MHz. Proiectul nu foloseste framework-ul Arduino si nu depinde de biblioteci externe precum Wire, Adafruit_GFX sau Adafruit_SSD1306. Functionalitatile necesare sunt implementate direct prin registrele microcontrollerului.

Codul este impartit modular:

Fisier Rol
main.c Punctul de intrare al aplicatiei, initializare module, masina de stari, ecrane OLED si feedback LED
gpio.c/h Configurare pini digitali, butoane cu pull-up intern si control LED-uri
adc.c/h Initializare ADC, citire microfon pe ADC0 si potentiometru pe ADC1
timer.c/h Timer0 in mod CTC pentru tick de 1 ms, folosit la temporizari si debounce
buzzer.c/h Timer1 in mod CTC, iesire OC1A / D9 pentru generarea notelor pe buzzer
goertzel.c/h Algoritmul Goertzel contextual si votarea LOW / OK / HIGH
twi.c/h Driver TWI/I2C bare-metal pentru comunicarea cu OLED-ul
ssd1306.c/h Driver text-only pentru OLED SSD1306, fara framebuffer complet
uart.c/h Debug prin USART0 la 9600 baud

Masina de stari

Aplicatia este organizata in patru stari principale:

Stare Descriere
IDLE Utilizatorul selecteaza nota tinta cu potentiometrul. OLED-ul afiseaza nota curenta.
PLAY_NOTE Buzzerul reda nota de referinta timp de aproximativ 900 ms. LED-ul galben este aprins doar in aceasta stare.
LISTEN_ANALYZE Buzzerul este oprit, LED-urile sunt stinse, iar microfonul este esantionat si analizat.
RESULT OLED-ul si LED-urile afiseaza rezultatul: LOW, OK, HIGH, NO SIG sau LOUD.

Butoanele au urmatorul comportament:

  • START porneste testul pentru nota selectata curent.
  • NEXT alege o nota aleatoare diferita, ca mod de challenge.
  • BACK revine la nota redata anterior.

Butoanele sunt conectate intre pin si GND si sunt citite cu rezistentele interne de pull-up ale microcontrollerului. Astfel, un buton apasat este citit ca LOW. Pentru evitarea declansarilor multiple, se foloseste detectie pe front si debounce de 180 ms.

Utilizarea perifericelor ATmega328P

Implementarea foloseste direct perifericele microcontrollerului:

  • GPIO: registrele DDRD, PORTD si PIND configureaza butoanele si LED-urile.
  • ADC: ADC0 / A0 citeste microfonul MAX4466, iar ADC1 / A1 citeste potentiometrul.
  • Timer0: functioneaza in mod CTC si genereaza un tick de 1 ms.
  • Timer1: genereaza semnalul pentru buzzer pe D9 / PB1 / OC1A.
  • USART0: inlocuieste Serial Monitor din Arduino si afiseaza informatii de debug.
  • TWI/I2C: controleaza OLED-ul SSD1306 pe pinii A4/SDA si A5/SCL.

Pentru buzzer, Timer1 este configurat in mod CTC cu toggle pe OC1A. Frecventa este determinata de valoarea OCR1A, calculata cu formula:

OCR1A = F_CPU / (2 * prescaler * frecventa) - 1

Pentru ADC se foloseste referinta AVcc, deoarece semnalele analogice sunt in intervalul 0-5V. Conversia este pe 10 biti, suficienta pentru selectarea notei cu potentiometrul si pentru estimarea amplitudinii semnalului de la microfon.

Algoritmul Goertzel contextual

Pentru analiza audio se foloseste algoritmul Goertzel. In loc sa se realizeze o detectie generala de pitch sau o transformata FFT, proiectul foloseste o abordare contextuala. Pentru fiecare nota tinta, sunt analizate doar trei frecvente:

  • nota de sub tinta — LOW
  • nota tinta — OK
  • nota de peste tinta — HIGH

Aceasta abordare este potrivita pentru ATmega328P, deoarece reduce memoria necesara si numarul de calcule. Algoritmul proceseaza semnalul in mod streaming, fara a salva un buffer audio mare in SRAM.

Gama folosita pentru antrenament este adaptata pentru bass-bariton:

A2, B2, C3, D3, E3, F3, G3, A3

Intern, lista contine si o nota sub gama si una peste gama:

G2, A2, B2, C3, D3, E3, F3, G3, A3, B3

Astfel, pentru fiecare nota tinta se poate compara energia notei inferioare, a notei corecte si a notei superioare.

Semnalul microfonului MAX4466 este centrat in jurul valorii de mijloc a ADC-ului, aproximativ 519. Componenta continua este eliminata printr-un tracker lent al centrului semnalului. Ferestrele cu amplitudine prea mica sunt tratate ca lipsa de semnal, iar ferestrele care ating valorile extreme ale ADC-ului sunt marcate ca fiind clipping.

Analiza ruleaza pe mai multe ferestre audio. Fiecare fereastra valida voteaza LOW, OK sau HIGH. Rezultatul final este ales prin vot majoritar. Daca votul este prea apropiat, rezultatul este marcat ca neclar in loc sa se forteze o decizie gresita.

Afisare OLED

OLED-ul SSD1306 este controlat printr-un driver propriu minimal, folosind TWI/I2C. Pentru economie de memorie, nu se foloseste un framebuffer complet de 1024 bytes. Textul este scris direct pe paginile display-ului, folosind un font 5×7 stocat in PROGMEM.

OLED-ul afiseaza doar informatiile esentiale: starea sistemului, nota tinta si rezultatul. Informatiile detaliate, precum amplitudinea, voturile si energiile Goertzel, sunt trimise prin USART.

Rezultate Obtinute

Proiectul final este functional pe Arduino Nano cu ATmega328P, fara framework-ul Arduino. Au fost integrate toate modulele: butoane, potentiometru, microfon MAX4466, buzzer, LED-uri si OLED SSD1306.

Dispozitivul permite selectarea unei note tinta din gama A2-A3, reda nota pe buzzer, apoi analizeaza semnalul audio captat de microfon. Feedback-ul este afisat pe OLED si prin LED-uri: rosu pentru LOW, verde pentru OK, galben pentru HIGH, rosu + galben pentru rezultat neclar si toate LED-urile pentru semnal prea puternic.

Validarea a fost facuta treptat: GPIO, ADC, buzzer cu Timer1, Goertzel prin USART, OLED prin TWI/I2C si integrarea finala. Proiectul a fost testat cu voce.

Utilizarea finala de resurse este:

Resursa Utilizat Total Procent
Flash 9964 bytes 30720 bytes 32.4%
SRAM 856 bytes 2048 bytes 41.8%

Concluzii

Proiectul demonstreaza implementarea unui sistem embedded de antrenament vocal folosind direct perifericele ATmega328P: GPIO, ADC, timere, USART si TWI/I2C.

Algoritmul Goertzel contextual s-a dovedit potrivit pentru hardware-ul folosit, deoarece compara doar nota tinta cu vecinii sai si evita costul unei detectii complete de pitch. Driverul OLED text-only, fara framebuffer complet, a redus consumul de SRAM si a permis rularea stabila pe Arduino Nano.

Limitarea principala este ca sistemul nu functioneaza ca tuner vocal general, ci ca antrenor pentru o gama restransa de note. Pentru scopul proiectului, aceasta abordare este suficienta si eficienta.

Download

Repository GitHub: https://github.com/ciprianmunteanu1/vocal-coach

Repository-ul proiectului contine:

  • codul sursa PlatformIO;
  • fisierele C si header pentru modulele software;
  • schema electrica;
  • documentatia proiectului.

Jurnal

Data Activitate
Etapa 1 Documentatie initiala, lista componente, schema bloc
Etapa 2 Realizare schema electrica in KiCad, validare conexiuni hardware pe breadboard
Etapa 3 Testare GPIO: butoane START/NEXT/BACK si LED-uri prin registre
Etapa 4 Testare ADC pentru potentiometru si microfon MAX4466
Etapa 5 Implementare buzzer cu Timer1 pe OC1A / D9
Etapa 6 Implementare si testare algoritm Goertzel contextual prin USART
Etapa 7 Implementare driver TWI/I2C si SSD1306 text-only
Etapa 8 Integrare finala: masina de stari, OLED, LED feedback, buzzer si analiza audio
Etapa 9 Testare finala cu voce si aplicatie de pian pe telefon

Bibliografie/Resurse

Resurse Hardware:

Resurse Software:

pm/prj2026/andrei.batasev/ciprian.munteanu04.1779136145.txt.gz · Last modified: 2026/05/18 23:29 by ciprian.munteanu04
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