Voor een gegeven frequentie, is de maximale frequentie/2 die uit het signaal correct kan worden gereconstrueerd de Nyquist-frequentie.

Als je dat digitaal toepast haal je dat.

In de praktijk wordt inderdaad vaak 2.2 toegepast om wat eventueel door filters wordt weggehaald te compenseren.

Hey,

Groetzel werkt zeer goed voor gekende frequenties!

Nu zou ik ook niet gekende sinus frequenties willen meten en ik wil ook 4 frequenties tegelijk willen meten.

Kent iemand hier een algoritme voor?

Ligt er aan wat je precies bedoelt.

A: Wil je ALLE frequencies meten en de 4 hoogste daaruit pakken?

B: Of wil je 4 willekeurige frequencies meten, die je dus instelt.

Voor A meet je dus alle frequenties, ook al gebriuk je er maar 4 -> Fourier

Voor B meet je maar 4 frequenties tegelijk -> Blijf Groetzel gebruiken

neen Neen, 4 'niet' vooraf gekende frequenties.

4 sinus frequenties tussen 10 en 10000 Hz, die allen tegelijk op mijn antenne instralen.

Maar 'niet' gekend zijn.

Dan zijn we weer terug bij mijn eerste antwoord. Toen dacht ik nog dat je dat wilde doen.
Voor dit geval dus: FFT nemen, en de vier grootste getallen Y zoeken. De bijbehorende X'en zijn de gezochte frequenties.

De nauwkeurigheid waarmee dat kan, hangt af van het aantal samples dat je hebt. Aangezien je tot 10kHz wilt kunnen kijken, kun je met 22kHz sampelen. Doe je dat gedurende 1 seconde, dan is iedere "bin" ongeveer 1 Hz breed en is dat je oplossend vermogen.
Kun je tien seconden lang meten, dan kun je tot op 1/10 Hz kijken. Etc.

Op 9 september 2009 11:13:01 schreef Frederick E. Terman:
De FFT zal normaal gesproken een array van getallen leveren.
Als je nu daaruit de grootste amplitude zoekt, dan moet dat haast degene zijn waarvan zijn rang overeenkomt met de frequentie die je zoekt.
Dus zoek naar de Y met de grootste ABS(Y), en dan is zijn X je frequentie.

Frederick, kan je dit verduidelijken?

Mijn samples gaan in een array.
Ik neem de 4 hoogste samples hieruit.
Dan bereken ik de tijd van de hoogste samples hieruit?

Ah, FFT geeft mij een complexe waarde. Met een reeele array en imaginaire array.

Dus dan neem ik de 4 hoogste amplitudes(y) en kijk welk imaginair(x) deel daarbij hoort.

Nee, je neemt de hoogste amplitude √ (re-deel2 + im-deel2) en kijkt waar (welke frequentie) die bij hoort!
Al die stelletjes (van steeds een reële en een imaginaire waarde) horen toch ieder bij een frequentie?

Nog eens.
Je neemt je samples en steekt die in een array. Rang = tijd, waarde = momentane spanning.

Je laat de FFT los op het array, en krijgt een nieuw array. Rang = frequentie, complexe waarde = amplitude

Zoek de grootste amplitude, en kijk welke frequentie (positie in de array) die heeft.
Zoek de één na grootste... etc.

[Bericht gewijzigd door Frederick E. Terman op (41%)]

Dank u Frederick, nu wordt het inderdaad duidelijk!

Kan je me enkel nog een goed FFT algoritme voorstellen.

Kan ik dit algoritme bv gebruiken?


short FFT(short int dir,long m,double *x,double *y)
{
   long n,i,i1,j,k,i2,l,l1,l2;
   double c1,c2,tx,ty,t1,t2,u1,u2,z;

   _/* Calculate the number of points */
   n = 1;
   for (i=0;i<m;i++) 
      n *= 2;

   _/* Do the bit reversal */
   i2 = n >> 1;
   j = 0;
   for (i=0;i<n-1;i++) {
      if (i < j) {
         tx = x[i];
         ty = y[i];
         x[i] = x[j];
         y[i] = y[j];
        
 x[j] = tx;
         y[j] = ty;
      }
      k = i2;
      while (k <= j) {
         j -= k;
         k >>= 1;
      }
      j += k;
   }

   _/* Compute the FFT */
   c1 = -1.0; 
   c2 = 0.0;
   l2 = 1;
   for (l=0;l<m;l++) {
      l1 = l2;
      l2 <<= 1;
      u1 = 1.0; 
      u2 = 0.0;
      for (j=0;j<l1;j++) {
         for (i=j;i<n;i+=l2) {
            i1 = i + l1;
            t1 = u1 * x[i1] - u2 * y[i1];
            t2 = u1 * y[i1] + u2 * x[i1];
            x[i1] = x[i] - t1; 
            y[i1] = y[i] - t2;
            x[i] += t1;
            y[i] += t2;
         }
         z =  u1 * c1 - u2 * c2;
         u2 = u1 * c2 + u2 * c1;
         u1 = z;
      }
      c2 = sqrt((1.0 - c1) / 2.0);
      if (dir == 1) 
         c2 = -c2;
      c1 = sqrt((1.0 + c1) / 2.0);
   }

   _/* Scaling for forward transform */
   if (dir ==
 1) {
      for (i=0;i<n;i++) {
         x[i] /= n;
         y[i] /= n;
      }
   }
   
   return(TRUE);
}

Dit algoritme vraagt blijkbaar 2 arrays. Terwijl ik toch voldoende heb aan 1 array. Rang en waarde?

Hier is nog een voorbeeld van wat ik bedoel. Links zie je vier sinusachtige dingen, en hun totaalsignaal in blauw. De samples staan onder "Totaal:"; het samplenummer staat uiterst links.
Dan doe ik de Fourier op de samples. Het resultaat is complex (omdat de fasen willekeurig waren), dus bereken ik de amplitude. Dan deel ik de amplituden nog eens door de helft van het aantal samples (hier dus door 16, want ik had 32 samples) en krijg zo de originele waarden terug. In jouw geval zal dit een schaalfactor-kwestie zijn.

Je C-code deelt door het aantal samples, maar geeft ook de "spiegelfrequenties" bovenin het array door. In mijn voorbeeld zijn die weggelaten. Verder lees ik heel slecht C; maar de code gebruikt ongetwijfeld arrays om in te vlinderen. Anders zou het geen FFT zijn.

http://www.uploadarchief.net/files/download/resized/fourier_20090929.png ← Klik op het plaatje voor een grotere versie!

Frederick, vraagje? De sinussen(1-2-3-4) komen allen samen in een array(het blauwe signaal of het totaal).

Dan laat ik de FFT los op die ééne array die mij dan een complexe teruggeeft van elke frequentie appart?

Want het doel is om uit het blauwe signaal terug de afzonderlijke frequenties te kunnen meten.

De tekening is me vrij duidelijk.

Groetzel kan je ook gebruiken als je de frequenties van de 4 sinussen niet kent.

Het voordeel van Groetzel is dat het snel is bij kleine hoeveelheid sinussen, of je ze kent of niet. Als je over het hele spectrum maar op 8 punten wilt meten kan je nog steeds Groetzel gebruiken, ook al weet je niet op welke van de 8 punten je 4 sinussen zitten.

Bij veel meer dan 8 punten kan je beter FFT gebruiken inderdaad. :)

Op 29 september 2009 22:39:57 schreef OBBO:
Dan laat ik de FFT los op die ééne array die mij dan een complexe teruggeeft van elke frequentie appart?

Ja, natuurlijk. Dat is wat de FFT doet.
De andere kolommen waren alleen een hulpje om even vier sinussen te maken. De FFT kijkt alleen naar de kolom "Totaal:".

De rangnummers van het frequentiearray (dus de gevonden frequenties) komen altijd overeen met gehele veelvouden van 1/sampleperiode.

Zit er in het ingangssignaal een frequentie die tussen twee van zulke frequenties in ligt (in mijn voorbeeld dus bijv. 5,5) dan zal de amplitude dus niet in één 'bin' terechtkomen, maar verdeeld worden over de naburige bins.

Om de frequentiebepaling toch zo scherp mogelijk te houden, en de "spread" dus te beperken tot alleen de dichtsbijgelegen bins, moet je je samples eerst "windowen". Wat dat is moet je maar eens Googelen. Zoek op Hann, Blackman, etc.

Ik ben deze morgen gaan meten aan men frequentiegenerator en het is me inderdaad opgevallen dat de amplitude daalt als de frequentie stijgt.

Dus zou ik perfect uit de getransformeerde array de hoogste amplitude , één na hoogste amplitude, enz. rangnummer van kunnen aflezen en daar de frequentie uit kunnen halen?

Dat van je frequentiegenerator de amplitude daalt als je een hogere frequentie instelt heeft toch niets met de FFT te maken? Dat ligt aan het apparaat, lijkt me - ik begrijp het gebruik van "inderdaad" niet.

De FFT levert je een array met daarin voor iedere frequentie de bijbehorende amplitude. De meeste amplitudes zullen heel laag zijn; die zou je "ruis" kunnen noemen. De amplitudes die hoog zijn, horen bij de gezochte frequenties.

Een frequentie die tussen twee "array" frequenties in valt, wordt verdeeld tussen deze twee (en nog wat rommel verderop).
Als je een meetperiode van een seconde aan samples hebt, kun je frequenties van bijvoorbeeld 18 of 122 of 3988 Hz precies meten.
Maar een frequentie van 18,4 Hz vind je terug in de arrayplaatsen behorende bij 18 en 19, plus nog wat kleinere waarden daar weer omheen.

Langere sampletijden leveren een fijner onderscheid op.
Lees ook over de Windowfunctie, die je nodig gaat hebben.

Nog een voorbeeld: van links naar rechts 7 Hz, 7.2 Hz, 7.5 Hz. Boven zonder windowfunctie; onder mèt.
De windowfunctie zorgt voor een kleinere scherpte voor de 7 Hz, maar het voordeel is dat "gebroken" frequenties 7.2 en 7.5 Hz nu juist scherper afgebeeld worden.
NB: dit zijn FFT's van maar 32 samples. In een veel grotere FFT zouden de frequenties óók maar enkele bins in beslag nemen, en in het grotere plaatje dus relatief zeer scherp bepaald zijn.

http://www.uploadarchief.net/files/download/fourier_window_20090930.png

[Bericht gewijzigd door Frederick E. Terman op (22%)]

Frederick, met 256 samples zou ik al heel scherp kunnen meten?

Maar hoe meer samples hoe meer rekenwerk.

Van 0 tot 10000 Hz in 256 stapjes is 39 Hz, ongeveer. Dat is dan dus het oplossend vermogen (zie ook alle eerdere posts).
Een FFT is rekenwerk, ja. Je oor doet dat allemaal real time voor niks, knap he? :)

Wat een mens allemaal niet kan.:)

De FFT functie in Excel is btw een goede tip Frederick.

Je had het in de vorige posts over de scaling. Moet ik dan rekening houden met de scaling?

In je excel sheet Frederick, kan je me het verschil vertellen tussen Ampl. en nor. Ampl. ?

[Bericht gewijzigd door OBBO op (20%)]

Op 29 september 2009 22:21:59 schreef Frederick E. Terman:
Dan doe ik de Fourier op de samples. Het resultaat is complex (omdat de fasen willekeurig waren), dus bereken ik de amplitude. Dan deel ik de amplituden nog eens door de helft van het aantal samples (hier dus door 16, want ik had 32 samples) en krijg zo de originele waarden terug. In jouw geval zal dit een schaalfactor-kwestie zijn.

Dus: Fourier (complex) -> Amplitude -> GeNORmaliseerde amplitude.
Als je goed kijkt zie je dat de genormaliseerde amplitudes ontstaan doordat ik door 16 heb gedeeld (zie boven).
Dat is dus in mijn geval de schaalfactor. Zo krijg ik de originele amplitudes weer terug - de schaal klopt dan weer.

In JOUW geval zal de schaalfactor anders zijn, want je signaal komt niet uit een spreadsheet, maar uit (bijvoorbeeld) een ADC converter of een geluidskaart of zo. Je wilt dan een uitkomst in Volts of dBm of iets dergelijks.

Heb eens gegoogled en er bestaan verschillende FFT vormen.

Er zijn er die enkel een reëele array transformeren, maar er zijn er ook die een complexe array transformeren(zoals in men code example).

Als ik de complexe gebruik neem ik dan Umom = imaginair? En wat is dan men reëel deel?

In hoeveer kun je FFT realtime gebruiken?

Als ik optel: Eerst de array vullen met samples. Dan complexe van maken. Dan FFT berekenen die dezelfde array gebruikt voor de transformatie. Dan uit die array terug men complexe halen voor de frequenties. En in al die tijd kunnen geen nieuwe samples genomen worden?

[Bericht gewijzigd door OBBO op (29%)]

Er bestaat natuurlijk maar één FFT. De uitvoering kan verschillen, maar da's wat anders.
Als je reële samples hebt (en die heb je), dan gaan die in de vakjes voor het reële gedeelte. In de "imaginaire vakjes" zet je telkens een nul.

Je kunt een FFT ook omgekeerd gebruiken, dus om van een frequentiespectrum weer een tijd-signaal te maken: reverse FFT. Zo kun je dan dus een signaal binnenhalen, naar een spectrum transformeren, er dan van alles mee doen (zoals alles boven en/of onder een bepaalde frequentie weglaten!) en dan weer terugtransformeren naar een signaal.

Als je in real time werkt, moet de ADC natuurlijk continu gevuld worden met samples. Dat kan met een interrupt routine. De berekeningen wachten dan gewoon een paar µs.
Er zijn voor de PC tientallen programmaatjes die dit doen, zodat je van het binnenkomende geluid continu een steeds mee veranderd spectrum kunt bekijken. Of waarmee je allerlei radio-signalen kunt ontcijferen, zoals morse, telex, facsimile plaatjes en nog veel mooiere signalen die je soms op het oor niet eens kunt horen, zo zwak zijn ze, maar die toch leesbare tekst opleveren.

Bedankt Frederick, nu heb ik genoeg informatie om met de code aan de slag te gaan.

Inderdaad, een timer interrupt, samples in een array laden en dan hopen dat de FFT berekening snel genoeg is om het realtime te tonen op het LCD.

Als men frequentiemeter af is, maak ik in deze post een update van het resultaat.

Frederick, ik heb een klein test programmatje gemaakt. Sinus functie in een tabel laten zetten en deze dan door de FFT gedraait.

Ik krijg een tabel terug met 1 amplitude(die correct is) met als index [0]. Kan dit kloppen voor 1 enkele sinus?

Hoe interpreteer ik hieruit de frequentie?

De imaginaire tabel is leeg. Is dat omdat er nu geen faseverschuiving is?

Elke zuivere sinus geeft mij na FFT index[0]

Normaal gesproken komt een cosinus in de reële vakjes terecht, en een sinus in de imaginaire. Een fase die daar tussenin ligt, levert een mengvorm op: dan heb je een aandeel reëel èn een aandeel imaginair.
Maar dat hangt ook van het programma af natuurlijk; daarvoor zou je de code moeten inspecteren om te zien hoe de schrijver daarmee omspringt. Het bovenstaande is in ieder geval de definitie.

Je probleem met die index begrijp ik niet.
Wat een (gewone) DFT doet is het ongeveer als volgt te begrijpen: alle samples worden vermenigvuldigd met een test-cosinus met frequentie n, en al die producten worden bij elkaar opgeteld. Daarna gebeurt dit nog eens met een test-sinus met frequentie n.
Nu heb je het reële en het imaginaire gedeelte te pakken voor het aandeel van frequentie n in je samples.
Die n laat je oplopen van 0 af tot zo hoog als je wilt gaan - normaal zo hoog als iets minder dan de helft van het aantal samples.

Met n=0 is cos(0) altijd 1. Je meet daarmee dus de gelijkspanningscomponent in het signaal. Dat klopt, want dat is frequentie nul. De gelijkspanningscomponent heeft geen imaginair aandeel uiteraard, en dat komt uit, want sin(0) is altijd nul!

Een frequentie die vier keer 'past' in je samples (waarvan je dus vier perioden gesampled hebt), levert in de tests altijd een totaal van nul op, behalve als n=4. Zijn resultaat is dus te vinden in het vakje met indexnummer vier. Etcetera.

Dat een bepaalde frequentie alleen een aandeel levert als de test-n ermee overeenkomt, is gemakkelijk in te zien: het product van twee sinussen met ongelijke frequenties is zelf weer de som van twee andere sinussen (met de som-en verschilfrequenties). Die som zal dus gemiddeld altijd nul opleveren.

Hoe dan ook, index nul is het gelijkspanningsaandeel, als het goed is.

Op 3 oktober 2009 16:33:40 schreef Frederick E. Terman:
Met n=0 is cos(0) altijd 1. Je meet daarmee dus de gelijkspanningscomponent in het signaal. Dat klopt, want dat is frequentie nul. De gelijkspanningscomponent heeft geen imaginair aandeel uiteraard, en dat komt uit, want sin(0) is altijd nul!

Hoe dan ook, index nul is het gelijkspanningsaandeel, als het goed is.

Frederick, je bedoelt dus dat de FFT men sinus functie ontleedt in één enkele gelijkspanning?

Ik heb een sinus tabel gemaakt met periode 2PI, PI, PI/2....

Geven allemaal een gelijkspanning na de FFT.

Ik bedoel dus, dat het gelijkspanningsaandeel in het signaal, na de FFT een waarde oplevert die daarmee overeenkomt, en wel als "frequentie nul".
Het gelijkspanningsaandeel is alleen reëel, en heeft geen imaginaire tegenhanger. Uit de berekening klopt dat ook, want de functie cos(0) is altijd één, maar sin(0) is altijd nul.

Bij de berekening van het aandeel van frequentie nul komen de imaginaire producten dus steeds op nul uit; alleen de reële producten leveren iets op (àls er tenminste gelijkspanning in het signaal zit - vaak is dat natuurlijk niet zo en is de gemiddelde spanning van het signaal zelf nul).

Ik begrijp niet wat voor tabel je nu hebt of hoe je rekent. Het principe wat ik je gaf is de DFT (discrete fourier transformatie). De FFT is daar een rechtstreekse afgeleide van, waarbij heel slim met tabellen wordt omgesprongen. Maar dat is verder niet essentieel - daar had je immers al een programma voor.

Het zou misschien goed zijn als je eens "met de hand" (met Excel, bijvoorbeeld, maar niet met de ingebouwde Fourierfunctie) een paar berekeningen zou maken:

  • Het product van twee sinussen met gelijke frequentie en de invloed van hun onderlinge fase.
  • Het product van twee sinussen van ONgelijke frequentie en de invloed van hun onderlinge fase.
  • Zelf eens een signaal opbouwen uit een beetje gelijkspanning plus wat sinussen.
  • Dat signaal dan vermenigvuldigen met sinussen en cosinussen van oplopende frequentie (ook frequentie nul!), en kijken wat er iedere keer uitkomt.

Want het is net of je helemáál niet begrijpt wat er achter zit.