Jag skulle vilja mäta frekvensen på en ton med en PIC.
Vill mäta frekvenser mellan 300Hz och 4kHz. Varje mätning får göras så snabbt det går, men max med 500ms mellanrum mellan mätningarna.
Tja! Du skulle ju även kunna använda de digitala ingångarna om man förutsätter att en period varierar mellan c.a. 0V och 5V.
När sinusvågen (eller vad du nu har för insignal) stiger över gränsvärdet för en 1:a på t.ex. RA1 på PORTA så sätter du det som en period i en variabel och plussar sedan på med 1 varje gång RA1 skiftar från 0 till 1.
Sedan är det bara räkna pulserna över en viss tidsperiod, säg 10ms, och sedan multiplicera resultatet med 100 (eftersom 10ms går 100 ggr i en sekund), så får du frekvensen i Hz.
Om tonen är enkel som sinus eller fyrkantvåg så går det bra att göra som grabbarna ovan beskriver.
Men toner från div musikinstrumet svänger mer komplicerat och passerar ofta 0 fler än 2 gånger/period.
Värsta tänkbara är att mäta frekvensen på en röst (kan passera 0 typ 16gr/period).
Tanken är just att bygga en stämmapparat.
Sedan kan man använda samma frekvensmätning till att bygga en MIDI-gitarr.
Tänker högt:
Men om man komprimerar ljudet och låter det passera en schmitt-trigger så det blir mer fyrkantvåg? Den kurvan borde bli lik en pwm-signal...
Bara en tanke som sagt.
Frekvensmätning utförs enkelt (vid låga frekvenser) med den inbyggda komparatorn. Annars får man använda en pic timer som klockas externt. Till denna krävs dock (om du inte har logiska nivåer) en liten förstärkare som driver insignalen till saturation.
Skall Du stämma ett instrument är det enklaste att alstra rätt ton och sedan nollsväva strängen mot denna. Mycket enklare än att läsa av fladdrande siffror.
vanlig FFT ger väldigt dålig upplösning i dessa sammanhang.
Det du ska använda dig av är autokorrelation eller AMDF (average magnitude difference function).
Autokorrelationen beräknar du genom:
Ryy(l)=sum( r(k) *r(k+l) ) där k är vektorindex och l är en förskjutning
Ryy kommer ge en vekor med korreketionen mellen signalen och signalen själv med en förkjutning. Detta innebär att du kommer få ett maximum vid den förskjutning som motsvarar din pitch.
En troligtviss bättre metod är AMDF som jobbar med differenser i stället.
AMDF(l)=sum( r(k) - r(k+l) ) där k är vektorindex och l är en förskjutning
AMDF fungerar på nästan samma sätt men nu får du ett minimum istället för et max. AMDF är lite lättare att tänka hur den fungerar.
om du har en period på 20 sample så kommer du få AMDF(20) = r(k) -r(k+20). Efter som du är inne på en ny period nu så kommer du att få noll (idealt). Jag har själv testat AMDF i både matlab och i en DSP, och det fungerar bra. Säg bara till om du vill ha mer förklarat eller vill ha matlab-filer på AMDF/autokorr.