Satura rādītājs:

1024 paraugi FFT spektra analizators, izmantojot Atmega1284: 9 soļus
1024 paraugi FFT spektra analizators, izmantojot Atmega1284: 9 soļus

Video: 1024 paraugi FFT spektra analizators, izmantojot Atmega1284: 9 soļus

Video: 1024 paraugi FFT spektra analizators, izmantojot Atmega1284: 9 soļus
Video: Insight into the beneficial use of Real-Time Spectrum Analysis for identification of elusive signals 2024, Novembris
Anonim
1024 paraugi FFT spektra analizators, izmantojot Atmega1284
1024 paraugi FFT spektra analizators, izmantojot Atmega1284
1024 paraugi FFT spektra analizators, izmantojot Atmega1284
1024 paraugi FFT spektra analizators, izmantojot Atmega1284

Šī salīdzinoši vienkāršā apmācība (ņemot vērā šīs tēmas sarežģītību) parādīs, kā jūs varat izveidot ļoti vienkāršu 1024 paraugu spektra analizatoru, izmantojot Arduino tipa plāksni (1284 šaurs) un sērijveida ploteri. Derēs jebkura veida ar Arduino saderīga tāfele, taču, jo vairāk tajā ir RAM, jo labākā frekvences izšķirtspēja. Lai aprēķinātu FFT ar 1024 paraugiem, būs nepieciešami vairāk nekā 8 KB RAM.

Spektra analīzi izmanto, lai noteiktu signāla galvenās frekvences sastāvdaļas. Daudzas skaņas (piemēram, tās, kuras rada mūzikas instruments) sastāv no pamata frekvences un dažām harmonikām, kuru frekvence ir pamatfrekvences vesels skaitlis. Spektra analizators parādīs visus šos spektrālos komponentus.

Iespējams, vēlēsities izmantot šo iestatījumu kā frekvences skaitītāju vai pārbaudīt jebkāda veida signālus, kas, jūsuprāt, rada troksni jūsu elektroniskajā shēmā.

Šeit mēs koncentrēsimies uz programmatūras daļu. Ja vēlaties izveidot pastāvīgu ķēdi kādam konkrētam lietojumam, signāls ir jānostiprina un jāfiltrē. Šī iepriekšēja kondicionēšana ir pilnībā atkarīga no signāla, kuru vēlaties izpētīt, atkarībā no tā amplitūdas, pretestības, maksimālās frekvences utt. … Jūs varat pārbaudīt

1. darbība: bibliotēkas instalēšana

Mēs izmantosim ArduinoFFT bibliotēku, kuras autors ir Enrike Kondess. Tā kā mēs vēlamies pēc iespējas vairāk rezerves RAM, mēs izmantosim šīs krātuves izstrādes zaru, kas ļauj izmantot peldošo datu tipu (nevis dubultā), lai saglabātu izlases un aprēķinātos datus. Tāpēc mums tas jāinstalē manuāli. Neuztraucieties, vienkārši lejupielādējiet arhīvu un izsaiņojiet to savā Arduino bibliotēkas mapē (piemēram, Windows 10 noklusējuma konfigurācijā: C: / Users / _your_user_name_ / Documents / Arduino / libraries)

Lai pārbaudītu, vai bibliotēka ir pareizi instalēta, apkopojiet vienu no sniegtajiem piemēriem, piemēram, "FFT_01.ino".

2. solis: Furjē transformācijas un FFT jēdzieni

Brīdinājums: ja nevarat redzēt nevienu matemātisku apzīmējumu, iespējams, vēlēsities pāriet uz 3. darbību. Jebkurā gadījumā, ja nesaņemat visu, vienkārši apsveriet secinājumu sadaļas beigās.

Frekvenču spektru iegūst, izmantojot ātrā Furjē transformācijas algoritmu. FFT ir digitāla ieviešana, kas tuvina Furjē transformācijas matemātisko koncepciju. Saskaņā ar šo jēdzienu, kad esat ieguvis signāla evolūciju pēc laika ass, jūs varat uzzināt tā attēlojumu frekvenču apgabalā, kas sastāv no sarežģītām (reālām + iedomātām) vērtībām. Koncepcija ir abpusēja, tāpēc, zinot frekvenču domēna attēlojumu, varat to pārveidot laika domēnā un saņemt signālu tieši tāpat kā pirms pārveidošanas.

Bet ko mēs darīsim ar šo aprēķināto sarežģīto vērtību kopumu laika jomā? Nu, lielākā daļa tiks atstāta inženieru ziņā. Mums būs jāizsauc cits algoritms, kas pārveidos šīs sarežģītās vērtības spektra blīvuma datos: tā ir lieluma (= intensitātes) vērtība, kas saistīta ar katru frekvenču joslu. Frekvenču joslas skaits būs tāds pats kā paraugu skaits.

Jūs noteikti esat iepazinies ar ekvalaizera koncepciju, piemēram, šo Atpakaļ uz astoņdesmitajiem gadiem ar grafisko EQ. Mēs iegūsim tāda paša veida rezultātus, bet ar 1024 joslām, nevis 16 un daudz lielāku intensitātes izšķirtspēju. Kad ekvalaizers sniedz vispārēju priekšstatu par mūziku, smalkā spektrālā analīze ļauj precīzi aprēķināt katras no 1024 joslu intensitāti.

Ideāls jēdziens, bet:

  1. Tā kā FFT ir Furjē transformācijas digitalizēta versija, tā tuvina digitālo signālu un zaudē daļu informācijas. Tātad, stingri sakot, FFT rezultāts, ja tas tiktu pārveidots ar apgrieztu FFT algoritmu, nedotu tieši sākotnējo signālu.
  2. Arī teorija uzskata signālu, kas nav galīgs, bet tas ir nemainīgs nemainīgs signāls. Tā kā mēs to digitalizēsim tikai noteiktu laiku (ti, paraugi), tiks ieviestas vēl dažas kļūdas.
  3. Visbeidzot, analogu un ciparu pārveidošanas izšķirtspēja ietekmēs aprēķināto vērtību kvalitāti.

Praksē

1) paraugu ņemšanas biežums (atzīmēts fs)

Mēs ņemsim signāla paraugu, t.i., izmērīsim tā amplitūdu ik pēc 1 sekundēm. fs ir paraugu ņemšanas biežums. Piemēram, ja mēs ņemam paraugu pie 8 KHz, mikroshēmā esošais ADC (analogo ciparu pārveidotājs) nodrošinās mērījumus ik pēc 1/8000 sekundēm.

2) Paraugu skaits (kodā atzīmēts N vai paraugi)

Tā kā pirms FFT palaišanas mums ir jāiegūst visas vērtības, mums tās būs jāsaglabā, un tāpēc mēs ierobežosim paraugu skaitu. FFT algoritmam nepieciešami vairāki paraugi, kuru jauda ir 2. Jo vairāk paraugu mums ir, jo labāk, bet tas aizņem daudz atmiņas, vēl jo vairāk, ka mums būs arī jāsaglabā pārveidotie dati, kas ir sarežģītas vērtības. Arduino FFT bibliotēka ietaupa vietu, izmantojot

  • Viens masīvs ar nosaukumu "vReal", lai saglabātu izlases datus un pēc tam pārveidoto datu reālo daļu
  • Viens masīvs ar nosaukumu "vImag", lai saglabātu pārveidoto datu iedomāto daļu

Nepieciešamais RAM apjoms ir vienāds ar 2 (masīvi) * 32 (biti) * N (paraugi).

Tātad mūsu Atmega1284 ar jauku 16 KB RAM mēs saglabāsim ne vairāk kā N = 16000*8/64 = 2000 vērtības. Tā kā vērtību skaitam ir jābūt 2, mēs saglabāsim ne vairāk kā 1024 vērtības.

3) Frekvences izšķirtspēja

FFT aprēķinās vērtības tik daudzām frekvenču joslām kā paraugu skaits. Šīs joslas būs no 0 HZ līdz paraugu ņemšanas frekvencei (fs). Tādējādi frekvences izšķirtspēja ir šāda:

Izšķirtspēja = fs / N

Izšķirtspēja ir labāka, ja tā ir zemāka. Tāpēc labākai izšķirtspējai (zemākai) mēs vēlamies:

  • vairāk paraugu un/vai
  • zemāks fs

Bet…

4) Minimālais fs

Tā kā mēs vēlamies redzēt daudz frekvenču, dažas no tām ir daudz augstākas par "pamata frekvenci", mēs nevaram iestatīt fs pārāk zemu. Faktiski pastāv Nikvista - Šenona izlases teorēma, kas liek mums iegūt paraugu ņemšanas biežumu, kas krietni pārsniedz divreiz lielāku maksimālo frekvenci, kādu mēs vēlētos pārbaudīt.

Piemēram, ja mēs vēlamies analizēt visu spektru no 0 Hz līdz 15 KHz, kas ir aptuveni maksimālā frekvence, ko lielākā daļa cilvēku var skaidri dzirdēt, mums ir jāiestata paraugu ņemšanas frekvence 30 KHz. Faktiski elektroniķi to bieži nosaka 2,5 (vai pat 2,52) * maksimālajā frekvencē. Šajā piemērā tas būtu 2,5 * 15 KHz = 37,5 KHz. Parastās profesionālās audio paraugu ņemšanas frekvences ir 44,1 KHz (audio CD ierakstīšana), 48 KHz un vairāk.

Secinājums:

1. līdz 4. punkts noved pie: mēs vēlamies izmantot pēc iespējas vairāk paraugu. Mūsu gadījumā ar 16 KB RAM ierīci mēs ņemsim vērā 1024 paraugus. Mēs vēlamies ņemt paraugus pēc iespējas zemākā paraugu ņemšanas biežumā, ja vien tas ir pietiekami augsts, lai analizētu augstāko frekvenci, kādu mēs sagaidām savā signālā (vismaz 2,5 * šī frekvence).

3. darbība: signāla simulācija

Signāla simulācija
Signāla simulācija

Pirmajam mēģinājumam mēs nedaudz pārveidosim bibliotēkā sniegto TFT_01.ino piemēru, lai analizētu signālu, kas sastāv no

  • Pamatfrekvence ir iestatīta uz 440 Hz (mūzikas A)
  • 3. harmonika ar pusi no pamata jaudas ("-3 dB")
  • 5. harmonika pie 1/4 no pamata jaudas ("-6 dB)

Jūs varat redzēt attēlā virs iegūtā signāla. Tas tiešām izskatās ļoti kā īsts signāls, ko dažreiz var redzēt osciloskopā (es to sauktu par "Betmenu") situācijā, kad notiek sinusoidāla signāla izgriešana.

4. solis: Simulēta signāla - kodēšanas analīze

0) Iekļaujiet bibliotēku

#include "arduinoFFT.h"

1) Definīcijas

Deklarāciju sadaļā mums ir

const baits adcPin = 0; // A0

const uint16_t paraugi = 1024; // Šai vērtībai VIENMĒR JĀBŪT 2 jauda konst uint16_t samplingFrequency = 8000; // Ietekmēs taimera maksimālo vērtību timer_setup () SYSCLOCK/8/samplingFrekvencei jābūt veselam skaitlim

Tā kā signālam ir piektā harmonika (šīs harmonikas frekvence = 5 * 440 = 2200 Hz), mums ir jāiestata paraugu ņemšanas frekvence virs 2,5 * 2200 = 5500 Hz. Šeit es izvēlējos 8000 Hz.

Mēs arī deklarējam masīvus, kuros glabāsim neapstrādātus un aprēķinātus datus

float vReal [paraugi];

pludiņš vImag [paraugi];

2) Instantiation

Mēs izveidojam ArduinoFFT objektu. ArduinoFFT izstrādātāja versijā tiek izmantota veidne, lai mēs varētu izmantot peldošo vai dubulto datu tipu. Ar pludiņu (32 bitiem) pietiek, ņemot vērā mūsu programmas vispārējo precizitāti.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, paraugi, paraugu ņemšanas biežums);

3) Simulējot signālu, aizpildot vReal masīvu, nevis aizpildot to ar ADC vērtībām.

Cikla sākumā mēs aizpildām vReal masīvu ar:

pludiņa cikli = ((((paraugi) * signalFrequency) / samplingFrequency); // Signāla ciklu skaits, ko izlasīs paraugu ņemšana

par (uint16_t i = 0; i <paraugi; i ++) {vReal = pludiņš ((amplitūda * (sin ((i * (TWO_PI * cikli))) / paraugi)))))); / * Veidojiet datus ar pozitīvu un negatīvas vērtības */ vReal += pludiņš ((amplitūda * (sin ((3 * i * (TWO_PI * cikli)))))/ paraugi)))/ 2.0);/ * Veidojiet datus ar pozitīvām un negatīvām vērtībām */ vReal += pludiņš ((amplitūda * (sin ((5 * i * (TWO_PI * cikli)))) / paraugi)))) / 4.0); / * Veidojiet datus ar pozitīvām un negatīvām vērtībām * / vImag = 0.0; // Iedomu daļa ir jāatkārto nulles gadījumā, ja tiek veikta cilpa, lai izvairītos no nepareiziem aprēķiniem un pārplūdēm}

Mēs pievienojam fundamentālā viļņa un divu harmoniku ar mazāku amplitūdu digitalizāciju. Mēs inicializējam iedomāto masīvu ar nullēm. Tā kā šis masīvs ir aizpildīts ar FFT algoritmu, mums tas ir jātīra vēlreiz pirms katra jauna aprēķina.

4) FFT skaitļošana

Tad mēs aprēķinām FFT un spektrālo blīvumu

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward);

FFT.compute (FFTDirection:: Uz priekšu); / * Aprēķināt FFT */ FFT.complexToMagnitude (); / * Aprēķināt lielumus */

FFT.windowing (…) darbība maina neapstrādātus datus, jo mēs izpildām FFT ierobežotam paraugu skaitam. Pirmajam un pēdējam paraugam ir pārtraukums (vienā pusē nav “nekā”). Tas ir kļūdu avots. Operācija "logošana" mēdz mazināt šo kļūdu.

FFT.compute (…) ar virzienu "Uz priekšu" aprēķina transformāciju no laika domēna uz frekvences domēnu.

Tad mēs aprēķinām lieluma (ti, intensitātes) vērtības katrai frekvenču joslai. Masīvs vReal tagad ir piepildīts ar lieluma vērtībām.

5) Sērijveida plotera zīmējums

Izdrukāsim vērtības sērijveida ploterī, izsaucot funkciju printVector (…)

PrintVector (vReal, (paraugi >> 1), SCL_FREQUENCY);

Šī ir vispārīga funkcija, kas ļauj drukāt datus ar laika vai frekvences asi.

Mēs arī drukājam tās joslas frekvenci, kurai ir vislielākā vērtība

pludiņš x = FFT.majorPeak ();

Sērijas nospiedums ("f0 ="); Sērijas nospiedums (x, 6); Serial.println ("Hz");

5. solis: Simulēta signāla analīze - rezultāti

Simulēta signāla analīze - rezultāti
Simulēta signāla analīze - rezultāti

Mēs redzam 3 tapas, kas atbilst pamatfrekvencei (f0), 3. un 5. harmoniku ar pusi un 1/4 no f0 lieluma, kā gaidīts. Mēs varam nolasīt loga augšdaļā f0 = 440,430114 Hz. Visu iepriekš minēto iemeslu dēļ šī vērtība nav precīzi 440 Hz, taču tā ir ļoti tuvu reālajai vērtībai. Nebija īsti nepieciešams parādīt tik daudz nenozīmīgu decimāldaļu.

6. darbība: reāla signāla analīze - ADC vadu savienošana

Īsta signāla analīze - ADC vadu savienošana
Īsta signāla analīze - ADC vadu savienošana

Tā kā mēs teorētiski zinām, kā rīkoties, mēs vēlētos analizēt reālu signālu.

Elektroinstalācija ir ļoti vienkārša. Savienojiet pamatni kopā un signāla līniju ar plāksnes A0 tapu, izmantojot sērijveida rezistoru ar vērtību no 1 KOhm līdz 10 KOhm.

Šis sērijas rezistors aizsargās analogo ieeju un izvairīsies no zvana. Tam jābūt pēc iespējas augstākam, lai izvairītos no zvana, un pēc iespējas zemākam, lai nodrošinātu pietiekamu strāvu, lai ātri uzlādētu ADC. Skatiet MCU datu lapu, lai uzzinātu paredzamo ADC ieejai pievienotā signāla pretestību.

Šai demonstrācijai es izmantoju funkciju ģeneratoru, lai, izmantojot 1,2 KOhm rezistoru, ievadītu sinusoidālu signālu ar frekvenci 440 Hz un amplitūdu ap 5 voltiem (vislabāk, ja amplitūda ir no 3 līdz 5 voltiem, tāpēc ADC tiek izmantots gandrīz pilnā mērogā)..

7. solis: reāla signāla analīze - kodēšana

0) Iekļaujiet bibliotēku

#include "arduinoFFT.h"

1) Deklarācijas un instances

Deklarācijas sadaļā mēs definējam ADC ievadi (A0), paraugu skaitu un paraugu ņemšanas biežumu, tāpat kā iepriekšējā piemērā.

const baits adcPin = 0; // A0

const uint16_t paraugi = 1024; // Šai vērtībai VIENMĒR JĀBŪT 2 jauda konst uint16_t samplingFrequency = 8000; // Ietekmēs taimera maksimālo vērtību timer_setup () SYSCLOCK/8/samplingFrekvencei jābūt veselam skaitlim

Mēs izveidojam ArduinoFFT objektu

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, paraugi, paraugu ņemšanas biežums);

2) Taimeris un ADC iestatīšana

Mēs iestatījām taimeri 1, lai tas darbotos paraugu ņemšanas frekvencē (8 KHz) un palielinātu izejas salīdzināšanas pārtraukumu.

void timer_setup () {

// atiestatīt 1. taimeri TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bits (CS11) | bits (WGM12); // CTC, prescaler of 8 TIMSK1 = bit (OCIE1B); OCR1A = (((16000000/8) / paraugu ņemšanas biežums) -1; }

Un iestatiet ADC tā

  • Kā ievadi izmanto A0
  • Aktivizē automātiski katrā 1. taimera izejā salīdzina atbilstību B
  • Izveido pārtraukumu, kad konversija ir pabeigta

ADC pulkstenis ir iestatīts uz 1 MHz, iepriekš palielinot sistēmas pulksteni (16 MHz) par 16. Tā kā katra konversija aizņem aptuveni 13 pulksteņus pilnā mērogā, konvertēšanu var panākt ar frekvenci 1/13 = 0,076 MHz = 76 KHz. Paraugu ņemšanas biežumam jābūt ievērojami zemākam par 76 KHz, lai ADC būtu laiks datu paraugu ņemšanai. (mēs izvēlējāmies fs = 8 KHz).

void adc_setup () {

ADCSRA = bits (ADEN) | bits (ADIE) | bits (ADIF); // ieslēgt ADC, vēlēties pārtraukt pēc pabeigšanas ADCSRA | = bit (ADPS2); // Prescaler no 16 ADMUX = bits (REFS0) | (adcPin & 7); // ADC ievades iestatīšana ADCSRB = bits (ADTS0) | bits (ADTS2); // Taimeris/Skaitītājs1 Salīdzināt B spēles sprūda avotu ADCSRA | = bit (ADATE); // ieslēgt automātisko aktivizēšanu}

Mēs paziņojam par pārtraukuma apstrādātāju, kas tiks izsaukts pēc katras ADC reklāmguvuma, lai saglabātu konvertētos datus vReal masīvā un pārtraukuma dzēšanu

// ADC pilnīgs ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; ja (rezultātsNumurs == paraugi) {ADCSRA = 0; // izslēgt ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Jums var būt izsmeļošs skaidrojums par ADC konvertēšanu Arduino (analogRead).

3) Iestatīšana

Iestatīšanas funkcijā mēs notīrām iedomāto datu tabulu un izsaucam taimera un ADC iestatīšanas funkcijas

nulleI (); // funkcija, kas visus iedomātos datus iestatījusi uz 0 - paskaidrots iepriekšējā sadaļā

taimeris_iestatījums (); adc_setup ();

3) Cilpa

FFT.dcRemoval (); // Noņemiet šī signāla līdzstrāvas komponentu, jo ADC ir atsauce uz zemi

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward); // Nosver datus FFT.compute (FFTDirection:: Forward); // Aprēķināt FFT FFT.complexToMagnitude (); // Aprēķināt lielumus // drukāt spektru un pamatfrekvenci f0 PrintVector (vReal, (paraugi >> 1), SCL_FREQUENCY); pludiņš x = FFT.majorPeak (); Sērijas nospiedums ("f0 ="); Sērijas nospiedums (x, 6); Serial.println ("Hz");

Mēs noņemam līdzstrāvas komponentu, jo ADC ir atsauce uz zemi un signāla centrs ir aptuveni 2,5 volti.

Tad mēs aprēķinām datus, kā paskaidrots iepriekšējā piemērā.

8. solis: reāla signāla analīze - rezultāti

Reāla signāla analīze - rezultāti
Reāla signāla analīze - rezultāti

Patiešām, šajā vienkāršajā signālā mēs redzam tikai vienu frekvenci. Aprēķinātā pamata frekvence ir 440,118194 Hz. Šeit atkal vērtība ir ļoti tuvu reālajai frekvencei.

9. darbība: kā ir ar izgrieztu sinusoidālu signālu?

Kas par izgrieztu sinusoidālu signālu?
Kas par izgrieztu sinusoidālu signālu?

Tagad ļaujiet nedaudz pārspēt ADC, palielinot signāla amplitūdu virs 5 voltiem, tāpēc tas tiek apgriezts. Nespiediet pārāk putru, lai neiznīcinātu ADC ievadi!

Mēs varam redzēt dažas harmonikas. Signāla griešana rada augstas frekvences komponentus.

Jūs esat redzējis FFT analīzes pamatus uz Arduino tāfeles. Tagad varat mēģināt mainīt paraugu ņemšanas biežumu, paraugu skaitu un loga parametru. Bibliotēka arī pievieno dažus parametrus, lai ātrāk un mazāk precīzi aprēķinātu FFT. Jūs ievērosiet, ka, iestatot pārāk zemu paraugu ņemšanas biežumu, aprēķinātie lielumi spektrālas locīšanas dēļ šķitīs pilnīgi kļūdaini.

Ieteicams: