Sisällysluettelo:

1024 Näytteet FFT -spektrianalysaattori Atmega1284: 9 askeleen avulla
1024 Näytteet FFT -spektrianalysaattori Atmega1284: 9 askeleen avulla

Video: 1024 Näytteet FFT -spektrianalysaattori Atmega1284: 9 askeleen avulla

Video: 1024 Näytteet FFT -spektrianalysaattori Atmega1284: 9 askeleen avulla
Video: NVIDIA's NEW Insane TEXT TO VIDEO SHOCKS The Entire Industry! 2024, Marraskuu
Anonim
1024 Näytteet FFT -spektrianalysaattori, joka käyttää Atmega1284 -laitetta
1024 Näytteet FFT -spektrianalysaattori, joka käyttää Atmega1284 -laitetta
1024 Näytteet FFT -spektrianalysaattori Atmega1284: n avulla
1024 Näytteet FFT -spektrianalysaattori Atmega1284: n avulla

Tämä suhteellisen helppo opetusohjelma (ottaen huomioon tämän aiheen monimutkaisuuden) näyttää, kuinka voit tehdä hyvin yksinkertaisen 1024 näytteen spektrianalysaattorin käyttämällä Arduino -tyyppistä levyä (1284 Narrow) ja sarjaplotteria. Kaikenlainen Arduino -yhteensopiva levy toimii, mutta mitä enemmän RAM -muistia sillä on, sitä parempi taajuustarkkuus. FFT: n laskemiseksi 1024 näytteellä tarvitaan yli 8 kt RAM -muistia.

Spektrianalyysiä käytetään määrittämään signaalin päätaajuuskomponentit. Monet äänet (kuten musiikki -instrumentin tuottamat) koostuvat perustaajuudesta ja joistakin harmonisista, joiden taajuus on perustaajuuden kokonaislukumonikerta. Spektrianalysaattori näyttää kaikki nämä spektrikomponentit.

Voit halutessasi käyttää tätä asetusta taajuuslaskurina tai tarkistaa kaikenlaisia signaaleja, joiden epäilet aiheuttavan melua elektronisessa piirissäsi.

Keskitymme tässä ohjelmisto -osaan. Jos haluat tehdä pysyvän piirin tietylle sovellukselle, sinun on vahvistettava ja suodatettava signaali. Tämä esivahvistus on täysin riippuvainen tutkittavasta signaalista sen amplitudin, impedanssin, maksimitaajuuden jne. Mukaan … Voit tarkistaa

Vaihe 1: Kirjaston asennus

Käytämme Enrique Condesin kirjoittamaa ArduinoFFT -kirjastoa. Koska haluamme säästää RAM -muistia mahdollisimman paljon, käytämme tämän arkiston kehityshaaraa, joka sallii float -tietotyypin (kaksinkertaisen sijaan) näytteenotetun ja lasketun datan tallentamiseen. Joten meidän on asennettava se manuaalisesti. Älä huoli, lataa arkisto ja pura se Arduino -kirjastokansioon (esimerkiksi Windows 10: n oletusasetuksissa: C: / Käyttäjät / _käyttäjä_nimesi_ / Dokumentit / Arduino / kirjasto)

Voit tarkistaa, että kirjasto on asennettu oikein, kokoamalla yksi annetuista esimerkeistä, kuten "FFT_01.ino".

Vaihe 2: Fourier -muunnos ja FFT -käsitteet

Varoitus: jos et voi nähdä mitään matemaattista merkintätapaa, voit halutessasi siirtyä vaiheeseen 3. Joka tapauksessa, jos et ymmärrä kaikkea, harkitse vain osan lopussa olevaa johtopäätöstä.

Taajuusspektri saadaan nopean Fourier -muunnosalgoritmin avulla. FFT on digitaalinen toteutus, joka vastaa Fourier -muunnoksen matemaattista käsitettä. Tämän käsitteen mukaan, kun saat signaalin kehityksen aika -akselin jälkeen, voit tietää sen esityksen taajuusalueella, joka koostuu monimutkaisista (todellisista + kuvitteellisista) arvoista. Konsepti on vastavuoroinen, joten kun tiedät taajuusalueen esityksen, voit muuntaa sen takaisin aikatunnukseksi ja saada signaalin takaisin aivan kuten ennen muunnosta.

Mutta mitä aiomme tehdä tämän joukon laskettuja monimutkaisia arvoja aika -alueella? Suurin osa jää insinööreille. Me kutsumme toista algoritmia, joka muuntaa nämä monimutkaiset arvot spektritiheysdataksi: joka on taajuusalueeseen liittyvä suuruus (= intensiteetti). Taajuuskaistan määrä on sama kuin näytteiden määrä.

Olet varmasti tuttu taajuuskorjainkonseptista, kuten tämä Takaisin 1980 -luvulle graafisen taajuuskorjaimen kanssa. No, saamme samanlaisia tuloksia, mutta 1024 kaistalla 16 sijasta ja paljon enemmän intensiteettitarkkuutta. Kun taajuuskorjain antaa yleiskuvan musiikista, hienon spektrianalyysin avulla voidaan laskea tarkasti kunkin 1024 kaistan intensiteetti.

Täydellinen konsepti, mutta:

  1. Koska FFT on Fourier -muunnoksen digitalisoitu versio, se lähentää digitaalista signaalia ja menettää joitakin tietoja. Joten tarkasti ottaen FFT: n tulos, jos se muutetaan takaisin käänteisellä FFT -algoritmilla, ei antaisi täsmälleen alkuperäistä signaalia.
  2. Myös teoria pitää signaalia, joka ei ole äärellinen, mutta joka on ikuinen vakio-signaali. Koska digitalisoimme sen vain tietyn ajan (esim. Näytteet), lisäämme joitakin virheitä.
  3. Lopuksi analogisen digitaalimuunnoksen resoluutio vaikuttaa laskettujen arvojen laatuun.

Käytännössä

1) Näytteenottotaajuus (merkitty fs)

Otamme näytteen signaalista eli mittaamme sen amplitudin 1/fs sekunnin välein. fs on näytteenottotaajuus. Jos esimerkiksi otamme näytteen taajuudella 8 KHz, sirulla oleva ADC (analoginen digitaalimuunnin) antaa mittauksen 1/8000 sekunnin välein.

2) Näytteiden lukumäärä (merkitty koodiin N tai näytteet)

Koska meidän on saatava kaikki arvot ennen FFT: n suorittamista, meidän on tallennettava ne ja rajoitamme näytteiden määrää. FFT -algoritmi tarvitsee useita näytteitä, joiden teho on 2. Mitä enemmän näytteitä meillä on, sitä parempi, mutta se vie paljon muistia, sitä enemmän meidän on myös tallennettava muunnetut tiedot, jotka ovat monimutkaisia arvoja. Arduino FFT -kirjasto säästää tilaa käyttämällä

  • Yksi matriisi nimeltä "vReal" näytetietojen ja sitten muunnetun datan todellisen osan tallentamiseksi
  • Yksi taulukko nimeltä "vImag" muunnetun datan kuvitteellisen osan tallentamiseksi

Tarvittava RAM -muistin määrä on 2 (taulukot) * 32 (bittiä) * N (näytteet).

Joten Atmega1284 -laitteeseen, jossa on mukava 16 kt RAM -muistia, tallennamme enintään N = 16000*8/64 = 2000 -arvoa. Koska arvojen määrän on oltava 2, tallennamme enintään 1024 arvoa.

3) Taajuustarkkuus

FFT laskee arvot niin monelle taajuuskaistalle kuin näytteiden määrä. Nämä kaistat ulottuvat 0 Hz: stä näytteenottotaajuuteen (fs). Siksi taajuuden resoluutio on:

Fresolution = fs / N

Resoluutio on parempi, kun se on pienempi. Joten paremman resoluution (alhaisempi) toivomme:

  • lisää näytteitä ja/tai
  • alempi fs

Mutta…

4) Vähäinen fs

Koska haluamme nähdä paljon taajuuksia, jotkut niistä ovat paljon korkeampia kuin "perustaajuus", emme voi asettaa fs: ää liian alhaiseksi. Itse asiassa on olemassa Nyquist – Shannonin näytteenottoteoreemi, joka pakottaa meidät näytteenottotaajuuteen, joka on selvästi yli kaksi kertaa sen enimmäistaajuuden, jonka haluaisimme testata.

Jos esimerkiksi haluamme analysoida kaikkia taajuuksia 0 Hz: stä 15 KHz: iin, mikä on suurin sallittu taajuus, jonka useimmat ihmiset voivat selvästi kuulla, meidän on asetettava näytteenottotaajuus 30 KHz. Itse asiassa elektronikot asettavat sen usein 2,5 (tai jopa 2,52) * enimmäistaajuudeksi. Tässä esimerkissä se olisi 2,5 * 15 KHz = 37,5 KHz. Tavalliset näytteenottotaajuudet ammattikäytössä ovat 44,1 KHz (audio -CD -tallennus), 48 KHz ja enemmän.

Johtopäätös:

Pisteet 1–4 johtavat: haluamme käyttää mahdollisimman monta näytettä. Meidän tapauksessa, jossa on 16 kt RAM -laitetta, harkitsemme 1024 näytettä. Haluamme ottaa näytteitä mahdollisimman pienellä näytteenottotaajuudella, kunhan se on riittävän korkea analysoimaan korkeinta taajuutta, jota odotamme signaalissamme (vähintään 2,5 * tämä taajuus).

Vaihe 3: Signaalin simulointi

Signaalin simulointi
Signaalin simulointi

Ensimmäiseksi kokeiluksi muutamme hieman kirjastossa annettua TFT_01.ino -esimerkkiä analysoidaksesi signaalin, joka koostuu

  • Perustaajuus, 440 Hz (musiikki A)
  • Kolmas harmoninen puolet perusvoimasta ("-3 dB")
  • Viides harmoninen 1/4 perustaajuudesta ("-6 dB)

Voit nähdä tuloksena olevan signaalin yläpuolella olevassa kuvassa. Se näyttää todellakin aidolta signaalilta, jonka joskus voi nähdä oskilloskoopilla (kutsuisin sitä "Batmaniksi") tilanteessa, jossa sinimuotoinen signaali leikataan.

Vaihe 4: Simuloidun signaalin analysointi - koodaus

0) Sisällytä kirjasto

#include "arduinoFFT.h"

1) Määritelmät

Ilmoitukset -osioissa meillä on

const tavu adcPin = 0; // A0

const uint16_t näytteet = 1024; // Tämän arvon PITÄÄ AINA olla 2 const uint16_t samplingFrequency = 8000; // Vaikuttaa ajastimen maksimiarvoon kohdassa timer_setup () SYSCLOCK/8/samplingFrequency should be a whole number

Koska signaalilla on viides harmoninen (tämän harmonisen taajuus = 5 * 440 = 2200 Hz), meidän on asetettava näytteenottotaajuus yli 2,5 * 2200 = 5500 Hz. Tässä valitsin 8000 Hz.

Ilmoitamme myös taulukot, joihin raaka- ja lasketut tiedot tallennetaan

kelluva vReal [näytteet];

kelluva vImag [näytteet];

2) Instantiaatio

Luomme ArduinoFFT -objektin. ArduinoFFT: n kehittäjäversio käyttää mallia, joten voimme käyttää joko float- tai double -tyyppiä. Float (32 bittiä) riittää ohjelman yleiseen tarkkuuteen.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, näytteet, näytteenottotaajuus);

3) Simuloidaan signaali täyttämällä vReal -taulukko sen sijaan, että se täytettäisiin ADC -arvoilla.

Silmukan alussa täytetään vReal -matriisi seuraavasti:

float cycles = ((((näytteet) * signalFrequency) / samplingFrequency); // Näytteenottosignaalin lukemien lukumäärä

for (uint16_t i = 0; i <näytteet; i ++) {vReal = float ((amplitudi * (sin ((i * (TWO_PI * syklit)) / näytteet)))))); / * Rakenna data positiivisella ja negatiiviset arvot */ vReal += float ((amplitudi * (sin ((3 * i * (TWO_PI * syklit)))))/ näytteet)))/ 2.0);/ * Rakenna data positiivisilla ja negatiivisilla arvoilla */ vReal += kelluva ((amplitudi * (sin ((5 * i * (TWO_PI * sykliä)))) / näytteet))) / 4.0); / * Rakenna positiivisia ja negatiivisia arvoja sisältävä data * / vImag = 0,0; // Kuvitteellinen osa on nollattava, jos silmukointi tapahtuu väärien laskelmien ja ylivuotojen välttämiseksi}

Lisäämme perusaallon digitalisoinnin ja kaksi harmonista, joilla on pienempi amplitudi. Alustamme kuvitteellisen taulukon nollalla. Koska tämä taulukko on FFT -algoritmin täyttämä, meidän on tyhjennettävä se uudelleen ennen jokaista uutta laskentaa.

4) FFT -laskenta

Sitten laskemme FFT ja spektrin tiheys

FFT. -ikkuna (FFTWindow:: Hamming, FFTDirection:: eteenpäin);

FFT.compute (FFTDirection:: Eteenpäin); / * Laske FFT */ FFT.complexToMagnitude (); / * Laske suuruusluokkia */

FFT.windowing (…) -toiminto muuttaa raakatietoja, koska suoritamme FFT: n rajoitetulla määrällä näytteitä. Ensimmäisessä ja viimeisessä näytteessä esiintyy epäjatkuvuus (toisella puolella ei ole "mitään"). Tämä on virheen lähde. "Ikkunatoiminto" pyrkii vähentämään tätä virhettä.

FFT.compute (…) suunnalla "eteenpäin" laskee muunnoksen aikatunnuksesta taajuusalueeksi.

Sitten laskemme suuruus (eli intensiteetti) arvot kullekin taajuuskaistalle. VReal -taulukko on nyt täynnä suuruusarvoja.

5) Sarjakuvaajapiirustus

Tulostetaan arvot sarjakuvaajalle kutsumalla funktiota printVector (…)

PrintVector (vReal, (näytteet >> 1), SCL_FREQUENCY);

Tämä on yleinen toiminto, jonka avulla voidaan tulostaa tietoja aika- tai taajuusakselilla.

Tulostamme myös sen taajuuden, jolla on suurin suuruusarvo

float x = FFT.majorPeak ();

Sarjajälki ("f0 ="); Sarjanjälki (x, 6); Sarja.println ("Hz");

Vaihe 5: Simuloidun signaalin analyysi - tulokset

Simuloidun signaalin analyysi - Tulokset
Simuloidun signaalin analyysi - Tulokset

Näemme kolme piikkiä, jotka vastaavat perustaajuutta (f0), kolmas ja viides harmoninen, puolet ja 1/4 f0 -suuruudesta, kuten odotettiin. Voimme lukea ikkunan yläosasta f0 = 440,430114 Hz. Tämä arvo ei ole tarkasti 440 Hz kaikista edellä selitetyistä syistä, mutta se on hyvin lähellä todellista arvoa. Ei todellakaan ollut tarpeen näyttää niin monia merkityksettömiä desimaaleja.

Vaihe 6: Todellisen signaalin analysointi - ADC: n johdotus

Todellisen signaalin analyysi - ADC: n johdotus
Todellisen signaalin analyysi - ADC: n johdotus

Koska tiedämme teoriassa miten edetä, haluaisimme analysoida todellisen signaalin.

Johdotus on hyvin yksinkertainen. Liitä maadoitukset ja signaalijohto kortin A0 -nastaan sarjavastuksen avulla, jonka arvo on 1 KOhm - 10 KOhm.

Tämä sarjavastus suojaa analogista tuloa ja välttää soittoa. Sen on oltava mahdollisimman korkea, jotta vältetään soittoääni, ja mahdollisimman alhainen, jotta se saa tarpeeksi virtaa ADC: n nopeaan lataamiseen. Katso MCU -tietolomakkeesta tietääksesi ADC -tuloon kytketyn signaalin odotetun impedanssin.

Tätä esittelyä varten käytin funktiogeneraattoria syöttämään sinimuotoisen signaalin, jonka taajuus on 440 Hz ja jonka amplitudi on noin 5 volttia (on parasta, jos amplitudi on 3–5 volttia, joten ADC: tä käytetään lähes täydellä asteikolla) 1,2 KOhm: n vastuksen kautta.

Vaihe 7: Todellisen signaalin analysointi - koodaus

0) Sisällytä kirjasto

#include "arduinoFFT.h"

1) Ilmoitukset ja esimerkit

Ilmoitusosassa määritellään ADC -tulo (A0), näytteiden lukumäärä ja näytteenottotaajuus, kuten edellisessä esimerkissä.

const tavu adcPin = 0; // A0

const uint16_t näytteet = 1024; // Tämän arvon PITÄÄ AINA olla 2 const uint16_t samplingFrequency = 8000; // Vaikuttaa ajastimen maksimiarvoon kohdassa timer_setup () SYSCLOCK/8/samplingFrequency should be a whole number

Luomme ArduinoFFT -objektin

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, näytteet, näytteenottotaajuus);

2) Ajastin ja ADC -asetukset

Asetamme ajastimen 1 niin, että se pyörii näytteenottotaajuudella (8 KHz) ja nostaa keskeytyksen lähdön vertailussa.

void timer_setup () {

// nollaa ajastin 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bitti (CS11) | bitti (WGM12); // CTC, esisäädin 8 TIMSK1 = bit (OCIE1B); OCR1A = (((16000000/8) / näytteenottotaajuus) -1; }

Ja aseta ADC niin

  • Käyttää tuloa A0
  • Käynnistää automaattisesti jokaisessa ajastimen 1 lähdössä vertaa ottelua B
  • Luo keskeytyksen, kun muunnos on valmis

ADC -kello asetetaan taajuudelle 1 MHz esiastelemalla järjestelmän kelloa (16 MHz) 16: lla. Näytteenottotaajuuden tulisi olla huomattavasti pienempi kuin 76 KHz, jotta ADC: llä on aikaa ottaa näytteitä. (valitsimme fs = 8 KHz).

void adc_setup () {

ADCSRA = bitti (ADEN) | bitti (ADIE) | bitti (ADIF); // kytke ADC päälle, halua keskeyttää valmistumisen jälkeen ADCSRA | = bit (ADPS2); // Esisäädin 16 ADMUX = bitti (REFS0) | (adcPin & 7); // ADC -tulon asettaminen ADCSRB = bit (ADTS0) | bitti (ADTS2); // Ajastin/laskuri1 Vertaa ottelun B laukaisulähdettä ADCSRA | = bit (ADATE); // ota automaattinen laukaisu käyttöön}

Ilmoitamme, että keskeytyksenkäsittelijä, joka kutsutaan jokaisen ADC -muunnoksen jälkeen, tallentaa muunnetut tiedot vReal -taulukkoon ja poistaa keskeytyksen

// ADC täydellinen ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; if (resultNumber == näytteet) {ADCSRA = 0; // sammuta ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Sinulla voi olla kattava selitys ADC -muunnoksesta Arduinolla (analogRead).

3) Asennus

Asetustoiminnossa tyhjennämme kuvitteellisen tietotaulukon ja kutsumme ajastin- ja ADC -asetustoiminnot

nollaI (); // funktio, joka asettaa kaikki kuvitteelliset tiedot arvoon 0 - selitetty edellisessä osassa

timer_setup (); adc_setup ();

3) Silmukka

FFT.dcRemoval (); // Irrota tämän signaalin DC -komponentti, koska ADC viittaa maahan

FFT. -ikkuna (FFTWindow:: Hamming, FFTDirection:: eteenpäin); // Punnitse tiedot FFT.compute (FFTDirection:: Eteenpäin); // Laske FFT FFT.complexToMagnitude (); // Laske suuruusluokat // spektrin ja perustaajuuden tulostus f0 PrintVector (vReal, (näytteet >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Sarjajälki ("f0 ="); Sarjanjälki (x, 6); Sarja.println ("Hz");

Poistamme tasavirtakomponentin, koska ADC on maadoitettu ja signaali on keskimäärin noin 2,5 volttia.

Sitten laskemme tiedot edellisen esimerkin mukaisesti.

Vaihe 8: Todellisen signaalin analyysi - tulokset

Todellisen signaalin analyysi - Tulokset
Todellisen signaalin analyysi - Tulokset

Itse asiassa näemme vain yhden taajuuden tässä yksinkertaisessa signaalissa. Laskettu perustaajuus on 440,118194 Hz. Tässäkin arvo on hyvin lähellä likimääräistä todellista taajuutta.

Vaihe 9: Entä leikattu sinimuotoinen signaali?

Entä leikattu sinimuotoinen signaali?
Entä leikattu sinimuotoinen signaali?

Nyt annetaan ADD: n ylikierrosta lisäämällä signaalin amplitudia yli 5 voltin, joten se leikataan. Älä työnnä liikaa, jotta ADC -tulo ei tuhoutuisi!

Voimme nähdä joitain harmonisia. Signaalin leikkaaminen luo korkeataajuisia komponentteja.

Olet nähnyt FFT -analyysin perusteet Arduino -taululla. Nyt voit yrittää muuttaa näytteenottotaajuutta, näytteiden määrää ja ikkunaparametria. Kirjasto lisää myös joitakin parametreja FFT: n laskemiseksi nopeammin ja vähemmän tarkasti. Huomaat, että jos asetat näytteenottotaajuuden liian alhaiseksi, lasketut suuruudet näyttävät täysin virheellisiltä spektrin taittumisen vuoksi.

Suositeltava: