Orodha ya maudhui:

Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284: Hatua 9
Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284: Hatua 9

Video: Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284: Hatua 9

Video: Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284: Hatua 9
Video: How Use Stable Diffusion, SDXL, ControlNet, LoRAs For FREE Without A GPU On Kaggle Like Google Colab 2024, Novemba
Anonim
Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284
Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284
Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284
Sampuli 1024 FFT Spectrum Analyzer Kutumia Atmega1284

Mafunzo haya rahisi (kwa kuzingatia ugumu wa mada hii) itakuonyesha jinsi unavyoweza kutengeneza sampuli ya wigo rahisi wa sampuli 1024 ukitumia bodi ya aina ya Arduino (1284 Nyembamba) na mpangaji wa serial. Aina yoyote ya bodi inayolingana ya Arduino itafanya, lakini ikiwa ina RAM zaidi, azimio bora la masafa utapata. Itahitaji zaidi ya 8 KB ya RAM ili kuhesabu FFT na sampuli 1024.

Uchunguzi wa wigo hutumiwa kuamua sehemu kuu za masafa ya ishara. Sauti nyingi (kama zile zinazozalishwa na ala ya muziki) zinajumuishwa na masafa ya kimsingi na sauti zingine ambazo zina masafa ambayo ni nambari kamili ya masafa ya kimsingi. Mchambuzi wa wigo atakuonyesha vifaa hivi vyote vya wigo.

Unaweza kutaka kutumia usanidi huu kama kaunta ya masafa au kuangalia aina yoyote ya ishara ambazo unashuku kuwa zinaleta kelele kwenye mzunguko wako wa elektroniki.

Tutazingatia hapa sehemu ya programu. Ikiwa ungependa kufanya mzunguko wa kudumu kwa programu maalum utahitaji kukuza na kuchuja ishara. Usahihishaji huu wa hali ya chini unategemea kabisa ishara unayotaka kusoma, kulingana na ukubwa wake, impedance, masafa ya juu nk … Unaweza kuangalia https://www.instructables.com/id/Analog-Sensor-Sig …….

Hatua ya 1: Kusanikisha Maktaba

Tutatumia maktaba ya ArduinoFFT iliyoandikwa na Enrique Condes. Kwa kuwa tunataka kuweka RAM kadiri inavyowezekana tutatumia tawi la kukuza la hazina hii ambayo inaruhusu kutumia aina ya data ya kuelea (badala ya mara mbili) kuhifadhi data ya sampuli na kompyuta. Kwa hivyo lazima tuisakinishe kwa mikono. Usijali, pakua tu kumbukumbu na uifungue kwenye folda yako ya maktaba ya Arduino (kwa mfano kwenye usanidi chaguomsingi wa Windows 10: C: Watumiaji _your_user_name_ / Nyaraka / maktaba ya Arduino)

Unaweza kuangalia kuwa maktaba imewekwa kwa usahihi kwa kuandaa moja ya mifano iliyotolewa, kama "FFT_01.ino."

Hatua ya 2: Dhana za Nne za Kubadilisha na FFT

Onyo: ikiwa huwezi kusimama ukiona nukuu yoyote ya kihesabu unaweza kutaka kuruka hadi hatua ya 3. Kwa hivyo, ikiwa haupati yote, fikiria tu hitimisho mwishoni mwa sehemu hiyo.

Wigo wa masafa hupatikana kupitia algorithm ya Fast Fourier Transform. FFT ni utekelezaji wa dijiti ambao inakaribia dhana ya hesabu ya Mabadiliko ya Fourier. Chini ya dhana hii mara tu utapata mageuzi ya ishara inayofuata mhimili wa wakati, unaweza kujua uwakilishi wake katika uwanja wa masafa, ulio na maadili tata (halisi + ya kufikirika). Wazo ni sawa, kwa hivyo unapojua uwakilishi wa kikoa cha masafa unaweza kuibadilisha kurudi kwa kikoa cha wakati na kurudisha ishara kama vile kabla ya mabadiliko.

Lakini tutafanya nini na seti hii ya maadili tata ya hesabu katika uwanja wa wakati? Kweli, nyingi zitaachwa kwa wahandisi. Kwa sisi tutaita algorithm nyingine ambayo itabadilisha maadili haya magumu kuwa data ya wiani wa wigo: hiyo ni ukubwa (= ukali) wa thamani inayohusishwa na kila bendi ya masafa. Idadi ya bendi ya masafa itakuwa sawa na idadi ya sampuli.

Hakika unajua wazo la kusawazisha, kama hii Rudi miaka ya 1980 na EQ ya Picha. Kweli, tutapata matokeo ya aina hiyo lakini kwa bendi 1024 badala ya 16 na azimio kubwa zaidi. Wakati kusawazisha kunatoa mtazamo wa ulimwengu wa muziki, uchambuzi mzuri wa macho unaruhusu kuhesabu kabisa kiwango cha kila bendi ya 1024.

Dhana kamili, lakini:

  1. Kwa kuwa FFT ni toleo la dijiti la ubadilishaji wa Fourier, inakadiriwa ishara ya dijiti, na hupoteza habari. Kwa hivyo, kwa kweli, matokeo ya FFT ikiwa yangebadilishwa nyuma na algorithm iliyogeuzwa ya FFT haitatoa ishara halisi.
  2. Pia nadharia inazingatia ishara ambayo haina mwisho, lakini hiyo ni ishara ya kudumu ya kudumu. Kwa kuwa tutaifanya kuwa ya dijiti kwa kipindi fulani tu (yaani sampuli), makosa mengine zaidi yataletwa.
  3. Mwishowe azimio la analojia kwa ubadilishaji wa dijiti litaathiri ubora wa nambari zilizohesabiwa.

Katika mazoezi

1) Mzunguko wa sampuli (fs iliyojulikana)

Tutapiga ishara, i.e.kupima urefu wake, kila sekunde 1 / fs. fs ni masafa ya sampuli. Kwa mfano tukipiga sampuli kwa 8 KHz, ADC (analojia na kibadilishaji cha dijiti) ambayo iko kwenye chip itatoa kipimo kila 1/8000 ya sekunde.

2) Idadi ya sampuli (N iliyoonyeshwa au sampuli kwenye nambari)

Kwa kuwa tunahitaji kupata maadili yote kabla ya kuendesha FFT tutalazimika kuzihifadhi na kwa hivyo tutapunguza idadi ya sampuli. Algorithm ya FFT inahitaji sampuli kadhaa ambazo ni nguvu ya 2. Sampuli zaidi tunayo bora lakini inachukua kumbukumbu nyingi, zaidi ambayo tutahitaji pia kuhifadhi data iliyobadilishwa, ambayo ni maadili tata. Maktaba ya Arduino FFT inaokoa nafasi kwa kutumia

  • Safu moja inayoitwa "vReal" kuhifadhi data zilizochukuliwa na kisha sehemu halisi ya data iliyobadilishwa
  • Safu moja inayoitwa "vImag" kuhifadhi sehemu ya kufikiria ya data iliyobadilishwa

Kiasi kinachohitajika cha RAM ni sawa na 2 (safu) 32 (bits) * N (sampuli).

Kwa hivyo katika Atmega1284 yetu ambayo ina 16 KB nzuri ya RAM tutahifadhi kiwango cha juu cha N = 16000 * 8/64 = 2000 maadili. Kwa kuwa idadi ya maadili lazima iwe nguvu ya 2, tutahifadhi kiwango cha juu cha 1024.

3) azimio la masafa

FFT itahesabu maadili kwa bendi nyingi za masafa kama idadi ya sampuli. Bendi hizi zitatoka kwa 0 HZ hadi mzunguko wa sampuli (fs). Kwa hivyo, azimio la masafa ni:

Utatuzi = fs / N.

Azimio ni bora wakati wa chini. Kwa hivyo kwa azimio bora (chini) tunataka:

  • sampuli zaidi, na / au
  • fs ya chini

Lakini…

4) Fs ndogo

Kwa kuwa tunataka kuona masafa mengi, zingine zikiwa za juu sana kuliko "frequency msingi" hatuwezi kuweka fs chini sana. Kwa kweli kuna nadharia ya sampuli ya Nyquist – Shannon ambayo inatulazimisha kuwa na mzunguko wa sampuli vizuri zaidi ya mara mbili ya kiwango cha juu ambacho tungependa kujaribu.

Kwa mfano, ikiwa tungependa kuchambua wigo wote kutoka 0 Hz ili tuseme 15 KHz, ambayo ni takriban kiwango cha juu zaidi ambacho wanadamu wanaweza kusikia waziwazi, lazima tuweke frequency ya sampuli kwa 30 KHz. Kwa kweli wataalamu wa elektroniki mara nyingi huiweka kwa 2.5 (au hata 2.52) * masafa ya juu. Katika mfano huu ambayo itakuwa 2.5 * 15 KHz = 37.5 KHz. Masafa ya kawaida ya sampuli katika sauti ya kitaalam ni 44.1 KHz (rekodi ya CD ya sauti), 48 KHz na zaidi.

Hitimisho:

Pointi 1 hadi 4 zinaongoza kwa: tunataka kutumia sampuli nyingi iwezekanavyo. Kwa upande wetu na 16 KB ya kifaa cha RAM tutazingatia sampuli 1024. Tunataka sampuli kwa kiwango cha chini kabisa cha sampuli iwezekanavyo, ilimradi ni ya kutosha kuchambua masafa ya juu zaidi tunayotarajia katika ishara yetu (2.5 * masafa haya, angalau).

Hatua ya 3: Kuiga Ishara

Kuiga Ishara
Kuiga Ishara

Kwa jaribio letu la kwanza, tutabadilisha kidogo mfano wa TFT_01.ino uliotolewa kwenye maktaba, kuchambua ishara iliyojumuisha

  • Mzunguko wa kimsingi, umewekwa hadi 440 Hz (muziki A)
  • 3 harmonic kwa nguvu ya msingi ("-3 dB")
  • 5 harmonic saa 1/4 ya nguvu ya msingi ("-6 dB)

Unaweza kuona kwenye picha hapo juu ishara inayosababisha. Inaonekana kweli sana kama ishara halisi ambayo wakati mwingine inaweza kuona kwenye oscilloscope (nitaiita "Batman") katika hali wakati kuna kubanwa kwa ishara ya sinusoidal.

Hatua ya 4: Uchambuzi wa Ishara Iliyoigwa - Uwekaji Coding

0) Jumuisha maktaba

# pamoja na "arduinoFFT.h"

1) Ufafanuzi

Katika sehemu za matamko, tuna

const byte adcPin = 0; // A0

sampuli uint16_t = 1024; // Thamani hii LAZIMA iwe nguvu ya 2 const uint16_t samplingFrequency = 8000; // Itaathiri kiwango cha juu cha kipima wakati katika kuweka kipima muda () SYSCLOCK / 8 / sampuli Mara kwa mara inapaswa kuwa nambari

Kwa kuwa ishara ina harmonics ya 5 (masafa ya harmonic hii = 5 * 440 = 2200 Hz) tunahitaji kuweka mzunguko wa sampuli juu ya 2.5 * 2200 = 5500 Hz. Hapa nilichagua 8000 Hz.

Tunatangaza pia safu ambapo tutahifadhi data ghafi na iliyokadiriwa

kuelea vReal [sampuli];

kuelea vImag [sampuli];

2) Taasisi

Tunaunda kitu cha ArduinoFFT. Toleo la dev la ArduinoFFT hutumia templeti ili tuweze kutumia kuelea au aina ya data mara mbili. Kuelea (bits 32) ni vya kutosha kwa kuzingatia usahihi wa jumla wa programu yetu.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, sampuli, sampuliFrequency);

3) Kuiga ishara kwa kujaza safu ya vReal, badala ya kuwa na idadi ya maadili ya ADC.

Mwanzoni mwa Kitanzi tunajaza safu ya vReal na:

mizunguko ya kuelea = ((((sampuli) * isharaFrequency) / samplingFrequency); // Idadi ya mizunguko ya ishara ambayo sampuli itasoma

kwa (uint16_t i = 0; i <sampuli; i ++) {vReal = kuelea ((amplitude * (sin ((i * (TWO_PI * mizunguko)) / sampuli)))); / * Jenga data na chanya na maadili hasi * / vReal + = kuelea ((amplitude * (dhambi ((3 * i * (mizunguko ya TWO_PI *)) / sampuli))) / 2.0); / * Jenga data na maadili mazuri na hasi * / vReal + = kuelea ((amplitude * (dhambi ((5 * i * (mizunguko ya TWO_PI *)) / sampuli))) / 4.0); / * Jenga data na maadili mazuri na hasi * / vImag = 0.0; // Sehemu ya kufikiria lazima ipigwe sifuri ikiwa itafunguliwa ili kuepuka mahesabu mabaya na kufurika}

Tunaongeza upeanaji wa dijiti ya wimbi la kimsingi na harmoniki mbili zilizo na kiwango kidogo. Kuliko sisi kuanzisha safu ya kufikiria na sifuri. Kwa kuwa safu hii imejaa hesabu ya FFT tunahitaji kuifuta tena kabla ya kila hesabu mpya.

4) FFT kompyuta

Kisha sisi huhesabu FFT na wiani wa spectral

Upepo wa FFT (FFTWindow:: Hamming, FFTDirection:: Forward);

FFT.compute (FFTDirection:: Mbele); / * Fanya FFT * / FFT.complexToMagnitude (); / * Kokotoa ukubwa * /

Uendeshaji wa upepo wa FFT (…) unabadilisha data mbichi kwa sababu tunaendesha FFT kwa idadi ndogo ya sampuli. Sampuli za kwanza na za mwisho zinaonyesha kukomesha (hakuna "chochote" upande mmoja wao). Hiki ni chanzo cha makosa. Operesheni ya "kumaliza" inaelekea kupunguza kosa hili.

FFT.compute (…) na mwelekeo "Mbele" unashughulikia mabadiliko kutoka kwa kikoa cha wakati hadi kikoa cha masafa.

Kisha tunakadiria viwango vya ukubwa (i.e. nguvu) kwa kila bendi ya masafa. Safu ya vReal sasa imejazwa na maadili ya ukubwa.

5) Mchoro wa mpangaji wa serial

Wacha tuchapishe maadili kwenye mpangilio wa serial kwa kupiga kazi printVector (…)

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

Hii ni kazi ya generic ambayo inaruhusu kuchapisha data na mhimili wa wakati au mhimili wa masafa.

Pia tunachapisha masafa ya bendi ambayo ina thamani kubwa zaidi

kuelea x = FFT.majorPeak ();

Serial.print ("f0 ="); Printa ya serial (x, 6); Serial.println ("Hz");

Hatua ya 5: Uchambuzi wa Ishara Iliyoigwa - Matokeo

Uchambuzi wa Ishara Iliyoigwa - Matokeo
Uchambuzi wa Ishara Iliyoigwa - Matokeo

Tunaona spiki 3 zinazolingana na mzunguko wa kimsingi (f0), 3 na 5 ya usawa, na nusu na 1/4 ya ukubwa wa f0, kama inavyotarajiwa. Tunaweza kusoma juu ya dirisha f0 = 440.430114 Hz. Thamani hii sio 440 Hz haswa, kwa sababu ya sababu zote zilizoelezwa hapo juu, lakini iko karibu sana na thamani halisi. Haikuwa lazima sana kuonyesha desimali nyingi zisizo na maana.

Hatua ya 6: Uchambuzi wa Ishara halisi - Wiring ADC

Uchambuzi wa Ishara halisi - Wiring ADC
Uchambuzi wa Ishara halisi - Wiring ADC

Kwa kuwa tunajua jinsi ya kuendelea kwa nadharia, tungependa kuchambua ishara halisi.

Wiring ni rahisi sana. Unganisha viwanja pamoja na laini ya ishara kwenye pini ya A0 ya bodi yako kupitia kontena la safu na thamani ya 1 KOhm hadi 10 KOhm.

Upinzani wa safu hii utalinda uingizaji wa analog na uepuke kupigia. Lazima iwe juu iwezekanavyo kuzuia mlio, na chini iwezekanavyo kutoa sasa ya kutosha kuchaji ADC haraka. Rejelea data ya MCU kujua impedance inayotarajiwa ya ishara iliyounganishwa kwenye uingizaji wa ADC.

Kwa onyesho hili nilitumia jenereta ya kazi kulisha ishara ya sinusoidal ya frequency 440 Hz na amplitude karibu volts 5 (ni bora ikiwa amplitude iko kati ya volts 3 na 5 kwa hivyo ADC inatumiwa karibu na kiwango kamili), kupitia kontena la 1.2 KOhm.

Hatua ya 7: Uchambuzi wa Ishara halisi - Uwekaji Coding

0) Jumuisha maktaba

# pamoja na "arduinoFFT.h"

1) Azimio na upendeleo

Katika sehemu ya tamko tunafafanua uingizaji wa ADC (A0), idadi ya sampuli na masafa ya sampuli, kama vile mfano uliopita.

const byte adcPin = 0; // A0

sampuli uint16_t = 1024; // Thamani hii LAZIMA iwe nguvu ya 2 const uint16_t samplingFrequency = 8000; // Itaathiri kiwango cha juu cha kipima wakati katika kuweka kipima muda () SYSCLOCK / 8 / sampuli Mara kwa mara inapaswa kuwa nambari

Tunaunda kitu cha ArduinoFFT

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, sampuli, sampuliFrequency);

2) Kuweka kipima muda na ADC

Tunaweka kipima saa 1 kwa hivyo inazunguka kwa masafa ya sampuli (8 KHz) na inaleta usumbufu kwa kulinganisha pato.

kuweka timer_setup () {

// kuweka upya kipima muda 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = kidogo (CS11) | kidogo (WGM12); // CTC, daktari mkuu wa 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000/8) / sampuliFrequency) -1; }

Na weka ADC iwe hivyo

  • Inatumia A0 kama pembejeo
  • Vichocheo kiatomati kwenye kila kipato cha timer 1 linganisha mechi B
  • Hutengeneza usumbufu wakati ubadilishaji umekamilika

Saa ya ADC imewekwa saa 1 MHz, kwa kuashiria saa ya mfumo (16 MHz) na 16. Kwa kuwa kila ubadilishaji huchukua takriban saa13 kwa kiwango kamili, mabadiliko yanaweza kupatikana kwa masafa ya 1/13 = 0.076 MHz = 76 KHz. Mzunguko wa sampuli unapaswa kuwa chini sana kuliko 76 KHz ili ADC iwe na wakati wa kupima data. (tulichagua fs = 8 KHz).

batili adc_setup () {

ADCSRA = kidogo (ADEN) | kidogo (ADIE) | kidogo (ADIF); // washa ADC, unataka kukatiza ukamilishaji ADCSRA | = kidogo (ADPS2); // Mtangazaji wa 16 ADMUX = kidogo (REFS0) | (adcPin & 7); // kuweka pembejeo ya ADC ADCSRB = kidogo (ADTS0) | kidogo (ADTS2); // Timer / Counter1 Linganisha Mechi ya chanzo B inayosababisha ADCSRA | = kidogo (ADATE); // washa kuwasha kiotomatiki}

Tunatangaza mshughulikiaji atakayeitwa baada ya kila ubadilishaji wa ADC kuhifadhi data iliyobadilishwa katika safu ya vReal, na kusafisha kwa usumbufu

// ADC kamili ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; ikiwa (matokeoNambari == sampuli) {ADCSRA = 0; // zima ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Unaweza kuwa na maelezo kamili juu ya ubadilishaji wa ADC kwenye Arduino (AnalogSoma).

3) Usanidi

Katika kazi ya usanidi tunafuta meza ya data ya kufikirika na kupiga simu kazi za usanidi wa saa na ADC

sifuri (); // kazi ambayo imeweka 0 data yote ya kufikiria - imeelezewa katika sehemu iliyopita

kuweka muda (); adc_setup ();

3) Kitanzi

FFT.dc Kuondolewa (); // Ondoa sehemu ya DC ya ishara hii kwani ADC inarejelewa ardhini

Upepo wa FFT (FFTWindow:: Hamming, FFTDirection:: Forward); // Pima data FFT.compute (FFTDirection:: Mbele); // Fanya FFT FFT.complexToMagnitude (); // hesabu za ukubwa // uchapishaji wigo na mzunguko wa msingi f0 PrintVector (vReal, (sampuli >> 1), SCL_FREQUENCY); kuelea x = FFT.majorPeak (); Serial.print ("f0 ="); Printa ya serial (x, 6); Serial.println ("Hz");

Tunaondoa sehemu ya DC kwa sababu ADC inarejelewa ardhini na ishara imejikita karibu na volts 2.5 takriban.

Kisha tunahesabu data kama ilivyoelezwa katika mfano uliopita.

Hatua ya 8: Uchambuzi wa Ishara halisi - Matokeo

Uchambuzi wa Ishara halisi - Matokeo
Uchambuzi wa Ishara halisi - Matokeo

Hakika tunaona masafa moja tu katika ishara hii rahisi. Mzunguko wa kimsingi uliohesabiwa ni 440.118194 Hz. Hapa tena thamani ni ukaribu wa karibu sana wa masafa halisi.

Hatua ya 9: Je! Kuhusu Ishara Iliyopunguka ya Sinusoidal?

Je! Je! Kuhusu Ishara Iliyopunguzwa ya Sinusoidal?
Je! Je! Kuhusu Ishara Iliyopunguzwa ya Sinusoidal?

Sasa inaruhusu kuzidisha ADC kidogo kwa kuongeza ukubwa wa ishara juu ya volts 5, kwa hivyo imefungwa. Je, si kushinikiza pia mush si kuharibu pembejeo ADC!

Tunaweza kuona sauti zingine zikionekana. Ukataji wa ishara huunda vifaa vya masafa ya juu.

Umeona misingi ya uchambuzi wa FFT kwenye bodi ya Arduino. Sasa unaweza kujaribu kubadilisha mzunguko wa sampuli, idadi ya sampuli na parameter ya Window. Maktaba pia inaongeza parameter kadhaa kuhesabu FFT haraka na usahihi kidogo. Utagundua kuwa ikiwa utaweka kiwango cha sampuli chini sana, ukubwa wa kompyuta utaonekana kuwa na makosa kabisa kwa sababu ya kukunjwa kwa wigo.

Ilipendekeza: