Mundarija:

Atmega1284: 9 bosqichlaridan foydalangan holda 1024 namunali FFT spektr analizatori
Atmega1284: 9 bosqichlaridan foydalangan holda 1024 namunali FFT spektr analizatori

Video: Atmega1284: 9 bosqichlaridan foydalangan holda 1024 namunali FFT spektr analizatori

Video: Atmega1284: 9 bosqichlaridan foydalangan holda 1024 namunali FFT spektr analizatori
Video: The END of Photography - Use AI to Make Your Own Studio Photos, FREE Via DreamBooth Training 2024, Noyabr
Anonim
Atmega1284 yordamida 1024 namuna FFT spektr analizatori
Atmega1284 yordamida 1024 namuna FFT spektr analizatori
Atmega1284 yordamida 1024 namuna FFT spektr analizatori
Atmega1284 yordamida 1024 namuna FFT spektr analizatori

Bu nisbatan oson qo'llanma (bu mavzuning murakkabligini hisobga olgan holda) sizga Arduino tipidagi (1284 tor) va ketma -ket chizgich yordamida 1024 namunali spektr analizatorini qanday yasashni ko'rsatib beradi. Arduino -ga mos keladigan har qanday taxta ishlaydi, lekin operativ xotira qanchalik ko'p bo'lsa, siz chastotaning eng yaxshi aniqligini olasiz. 1024 ta namunali FFTni hisoblash uchun 8 KB dan ortiq RAM kerak bo'ladi.

Spektrni tahlil qilish signalning asosiy chastotali komponentlarini aniqlash uchun ishlatiladi. Ko'p tovushlar (cholg'u asboblari tomonidan ishlab chiqarilgan kabi) asosiy chastotadan va ba'zi harmoniklardan tashkil topgan bo'lib, ular chastotaning asosiy sonining butun soniga ko'payadi. Spektr analizatori sizga barcha spektral komponentlarni ko'rsatadi.

Siz ushbu sozlamani chastota hisoblagichi sifatida ishlatishni yoki elektron pallangizda shovqin keltirib chiqarayotganiga shubha qiladigan signallarni tekshirishni xohlashingiz mumkin.

Biz bu erda dasturiy ta'minot qismiga e'tibor qaratamiz. Agar siz ma'lum bir dastur uchun doimiy sxemani yaratmoqchi bo'lsangiz, signalni kuchaytirishingiz va filtrlashingiz kerak bo'ladi. Bu oldindan konditsionerlik siz o'rganmoqchi bo'lgan signalga bog'liq, uning amplitudasi, impedansi, maksimal chastotasi va boshqalarga bog'liq. Siz https://www.instructables.com/id/Analog-Sensor-Sig… tekshirishingiz mumkin.

1 -qadam: Kutubxonani o'rnatish

Biz Enrike Condes yozgan ArduinoFFT kutubxonasidan foydalanamiz. Biz RAMni iloji boricha zaxiralashni xohlaganimiz uchun, biz tanlangan va hisoblangan ma'lumotlarni saqlash uchun float ma'lumotlar turini (ikkilik o'rniga) ishlatishga imkon beradigan ushbu omborxonaning ishlab chiquvchi bo'limidan foydalanamiz. Shuning uchun biz uni qo'lda o'rnatishimiz kerak. Xavotir olmang, faqat arxivni yuklab oling va Arduino kutubxonangiz papkasida oching (masalan, Windows 10 standart konfiguratsiyasida: C: / Users / _your_user_name_ / Documents / Arduino / library)

Siz kutubxonaning to'g'ri o'rnatilganligini "FFT_01.ino" kabi berilgan misollardan birini tuzib tekshirishingiz mumkin.

2 -qadam: Fourier Transform va FFT kontseptsiyalari

Ogohlantirish: agar siz hech qanday matematik yozuvni ko'rmasangiz, 3 -bosqichga o'tishni xohlashingiz mumkin. Baribir, agar hammasini tushunmasangiz, bo'lim oxiridagi xulosani ko'rib chiqing.

Chastotali spektr Fast Fourier Transform algoritmi orqali olinadi. FFT - bu Furye transformatsiyasining matematik kontseptsiyasiga yaqinlashgan raqamli dastur. Vaqt o'qidan keyin signalning evolyutsiyasini olganingizda, bu kontseptsiya ostida siz uning murakkab (haqiqiy + xayoliy) qiymatlardan tashkil topgan chastota sohasidagi tasvirini bilib olishingiz mumkin. Kontseptsiya o'zaro ta'sir qiladi, shuning uchun siz chastota domenining tasvirini bilsangiz, uni vaqt maydoniga qaytarishingiz va signalni aylantirishdan oldingi kabi qaytarishingiz mumkin.

Ammo vaqt sohasidagi hisoblangan murakkab qiymatlar to'plami bilan nima qilmoqchimiz? Xo'sh, ko'p qismi muhandislarga qoldiriladi. Biz bu murakkab qiymatlarni spektral zichlik ma'lumotlariga aylantiradigan boshqa algoritmni chaqiramiz: bu har bir chastota diapazoni bilan bog'liq bo'lgan kattalik (= intensivlik) qiymati. Chastotalar diapazoni namunalar soni bilan bir xil bo'ladi.

Siz, shubhasiz, ekvalayzer kontseptsiyasi bilan tanishsiz, xuddi 1980 -yillarga borib, Grafik EQ bilan. Xo'sh, biz xuddi shunday natijalarga erishamiz, lekin 16 o'rniga 1024 tasma va undan yuqori zichlikdagi aniqlik. Ekvalayzer musiqaga global nuqtai nazar bersa, nozik spektral tahlil 1024 diapazonning har birining intensivligini aniq hisoblash imkonini beradi.

Zo'r tushuncha, lekin:

  1. FFT Fourier konvertatsiyasining raqamli versiyasi bo'lgani uchun raqamli signalga yaqinlashadi va ba'zi ma'lumotlarni yo'qotadi. Qat'iy aytganda, FFT natijasi teskari FFT algoritmi bilan o'zgartirilsa, asl signal berilmaydi.
  2. Bundan tashqari, nazariya cheklanmagan, lekin doimiy signaldir. Biz uni faqat ma'lum vaqtgacha (masalan, namunalar) raqamlashtiradigan bo'lsak, yana bir qancha xatolar kiritiladi.
  3. Nihoyat, analogni raqamli konvertatsiyaga o'tkazish hisoblangan qiymatlarning sifatiga ta'sir qiladi.

Amalda

1) namuna olish chastotasi (fs qayd etilgan)

Biz signalni tanlaymiz, ya'ni uning amplitudasini har 1/soniyada o'lchaymiz. fs - namuna olish chastotasi. Masalan, agar biz 8 KGts chastotada namuna olsak, chipda joylashgan ADC (analogdan raqamli konvertor) har 1/8000 soniyada o'lchovni ta'minlaydi.

2) Namunalar soni (kodda ko'rsatilgan N yoki namunalar)

FFTni ishga tushirishdan oldin biz barcha qiymatlarni olishimiz kerak bo'lganligi sababli, biz ularni saqlashimiz kerak va shuning uchun biz namunalar sonini cheklaymiz. FFT algoritmiga 2 ta kuchga ega bo'lgan bir qancha namunalar kerak bo'ladi. Biz qanchalik ko'p namunaga ega bo'lsak, shuncha yaxshi bo'ladi, lekin bu uchun juda ko'p xotira kerak bo'ladi. Arduino FFT kutubxonasi bo'sh joyni tejaydi

  • Tanlangan ma'lumotlarni, so'ngra o'zgartirilgan ma'lumotlarning haqiqiy qismini saqlash uchun "vReal" nomli bir qator
  • O'tkazilgan ma'lumotlarning tasavvur qismini saqlash uchun "vImag" nomli bitta qator

Kerakli RAM miqdori 2 (massiv) * 32 (bit) * N (namunalar) ga teng.

Shunday qilib, 16 Kb tezkor xotiraga ega bo'lgan Atmega1284 -da biz maksimal N = 16000*8/64 = 2000 qiymatlarini saqlaymiz. Qiymatlar soni 2 ga teng bo'lishi kerak, biz maksimal 1024 qiymatni saqlaymiz.

3) Chastotani aniqligi

FFT namunalar soniga teng bo'lgan chastota diapazonlari uchun qiymatlarni hisoblab chiqadi. Bu diapazonlar 0 Gts dan namuna olish chastotasiga (fs) qadar cho'ziladi. Shunday qilib, chastota aniqligi:

Fresolution = fs / N

Ruxsat pastroq bo'lganda yaxshiroq bo'ladi. Shunday qilib, yaxshiroq hal qilish uchun (pastroq) biz xohlaymiz:

  • ko'proq namunalar va/yoki
  • pastroq fs

Lekin…

4) minimal fs

Biz juda ko'p chastotalarni ko'rishni xohlaganimiz uchun, ularning ba'zilari "asosiy chastotadan" ancha yuqori, biz fsni juda past darajada o'rnatolmaymiz. Aslida, bizni sinovdan o'tkazmoqchi bo'lgan maksimal chastotadan ikki baravar yuqori namuna olish chastotasiga ega bo'lishga majbur qiladigan Nyquist -Shannon tanlov teoremasi mavjud.

Masalan, agar biz 0 Gts dan 15 KGts gacha bo'lgan barcha spektrni tahlil qilmoqchi bo'lsak, bu taxminan ko'pchilik odamlar aniq eshitadigan maksimal chastota, biz namuna olish chastotasini 30 KHz ga o'rnatishimiz kerak. Darhaqiqat, elektronlar ko'pincha uni 2,5 (yoki hatto 2,52) * maksimal chastotaga o'rnatadilar. Bu misolda bu 2,5 * 15 KHz = 37,5 KHz bo'ladi. Professional audioda odatdagi namuna olish chastotalari 44,1 KGts (audio CD yozuvi), 48 KGts va boshqalar.

Xulosa:

1 dan 4 gacha ballar quyidagilarga olib keladi: biz iloji boricha ko'proq namunalardan foydalanmoqchimiz. Bizning holatimizda 16 KB operativ xotira qurilmasi bilan biz 1024 ta namunani ko'rib chiqamiz. Biz signalimizda kutgan eng yuqori chastotani tahlil qilish uchun yetarli darajada yuqori bo'lsa, iloji boricha namuna olishning eng past chastotasida namuna olishni xohlaymiz (kamida 2,5 * bu chastota).

3 -qadam: signalni simulyatsiya qilish

Signalni simulyatsiya qilish
Signalni simulyatsiya qilish

Birinchi urinishimiz uchun biz kutubxonada berilgan TFT_01.ino misolini biroz o'zgartirib, signalni tahlil qilamiz.

  • Asosiy chastota, 440 Gts ga sozlangan (musiqiy A)
  • 3-garmonik, asosiy kuchning yarmida ("-3 dB")
  • 5-garmonik fundamental kuchining 1/4 qismida ("-6 dB)

Olingan signalni yuqoridagi rasmda ko'rishingiz mumkin. Haqiqatan ham, sinusoidal signal kesilganida, ba'zida osiloskopda ko'rish mumkin bo'lgan haqiqiy signalga o'xshaydi (men buni "Batman" deb atagan bo'lardim).

4 -qadam: Simulyatsiya qilingan signalni tahlil qilish - kodlash

0) kutubxonani qo'shing

#"arduinoFFT.h" ni qo'shing

1) ta'riflar

Deklaratsiyalar bo'limlarida bizda bor

const bayt adcPin = 0; // A0

const uint16_t namunalari = 1024; // Bu qiymat har doim 2 const kuchga ega bo'lishi kerak uint16_t samplelingFrequency = 8000; // timer_setup () da taymerning maksimal qiymatiga ta'sir qiladi SYSCLOCK/8/samplelingFrekans butun son bo'lishi kerak

Signal 5 -chi harmonikaga ega bo'lgani uchun (bu harmonik chastotasi = 5 * 440 = 2200 Gts), biz namuna olish chastotasini 2,5 * 2200 = 5500 Gts dan yuqori o'rnatishimiz kerak. Bu erda men 8000 Gts ni tanladim.

Shuningdek, biz xom va hisoblangan ma'lumotlarni saqlaydigan qatorlarni e'lon qilamiz

float vReal [namunalar];

float vImag [namunalar];

2) chaqiruv

Biz ArduinoFFT ob'ektini yaratamiz. ArduinoFFT -ning dev versiyasi shablonni ishlatadi, shuning uchun biz float yoki ikkilamchi ma'lumotlar turidan foydalanishimiz mumkin. Float (32 bit) bizning dasturimizning umumiy aniqligi uchun etarli.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, namunalar, namuna olish chastotasi);

3) signalni ADC qiymatlari bilan to'ldirish o'rniga vReal qatorini to'ldirish orqali simulyatsiya qilish.

Loop boshida biz vReal qatorini to'ldiramiz:

float davrlari = (((namunalar) * signalFrequency) / namuna olishFrekans); // Namuna olish o'qiladigan signal davrlarining soni

for (uint16_t i = 0; i <namunalar; i ++) {vReal = float ((amplitudasi * (sin ((i * (TWO_PI * tsikllari)) / namunalar))))); / * Ma'lumotlarni ijobiy va manfiy qiymatlar */ vReal += float ((amplitudasi * (gunoh ((3 * i * (TWO_PI * tsikllari))/ namunalar)))/ 2.0);/ * Ijobiy va salbiy qiymatli ma'lumotlarni tuzish */ vReal += float ((amplitudasi * (sin ((5 * i * (TWO_PI * tsikllari)) / namunalar))) / 4.0); / * Ijobiy va salbiy qiymatli ma'lumotlarni tuzish * / vImag = 0.0; // Noto'g'ri hisob -kitoblar va toshib ketishlarning oldini olish uchun aylanada xayoliy qismni nolga qo'yish kerak}

Biz asosiy to'lqin va amplitudasi past bo'lgan ikkita harmonikani raqamlashtirishni qo'shamiz. Xayoliy qatorni nol bilan boshlaymiz. Ushbu massiv FFT algoritmi bilan to'ldirilganligi sababli, biz har bir yangi hisob -kitobdan oldin uni qayta tozalashimiz kerak.

4) FFT hisoblash

Keyin biz FFT va spektral zichlikni hisoblaymiz

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

FFT.compute (FFTDirection:: Forward); / * Hisoblash FFT */ FFT.complexToMagnitude (); / * Hisoblash kattaliklari */

FFT.windowing (…) operatsiyasi xom ma'lumotlarni o'zgartiradi, chunki biz FFTni cheklangan miqdordagi namunalarda ishlatamiz. Birinchi va oxirgi namunalar uzluksizlikni ko'rsatadi (ularning bir tomonida "hech narsa" yo'q). Bu xato manbai. "Deraza oynasi" operatsiyasi bu xatoni kamaytiradi.

"Oldinga" yo'nalishi bilan FFT.compute (…) vaqt domenidan chastota sohasiga o'tishni hisoblaydi.

Keyin biz har bir chastota diapazoni uchun kattalik (ya'ni intensivlik) qiymatlarini hisoblaymiz. VReal qatori endi kattalik qiymatlari bilan to'ldiriladi.

5) Serial plotter chizilgan

PrintVector funktsiyasini chaqirib, ketma -ket plotterdagi qiymatlarni chop qilaylik (…)

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

Bu vaqt o'qi yoki chastota o'qi bilan ma'lumotlarni chop etishga imkon beradigan umumiy funktsiya.

Biz, shuningdek, eng katta qiymatga ega bo'lgan tarmoqli chastotasini chop etamiz

float x = FFT.majorPeak ();

Serial.print ("f0 ="); Ketma -ket chop etish (x, 6); Serial.println ("Hz");

5 -qadam: Simulyatsiya qilingan signalni tahlil qilish - natijalar

Simulyatsiya signalining tahlili - natijalar
Simulyatsiya signalining tahlili - natijalar

Biz kutilganidek, f0 kattaligining yarmi va 1/4 qismi bilan 3 -chi va 5 -garmonik asosiy chastotaga (f0) mos keladigan 3 ta shpikni ko'ramiz. Biz oynaning yuqori qismida o'qishimiz mumkin f0 = 440.430114 Hz. Bu qiymat aniq 440 Hz emas, chunki yuqorida tushuntirilgan barcha sabablarga ko'ra, lekin u haqiqiy qiymatga juda yaqin. Shuncha ahamiyatsiz o'nli kasrlarni ko'rsatish kerak emas edi.

6 -qadam: Haqiqiy signalni tahlil qilish - ADCni ulash

Haqiqiy signalni tahlil qilish - ADCni ulash
Haqiqiy signalni tahlil qilish - ADCni ulash

Biz nazariyada qanday harakat qilishni bilganimiz uchun haqiqiy signalni tahlil qilmoqchimiz.

Ulanish juda oddiy. 1 KOhm dan 10 KOm gacha bo'lgan ketma -ket qarshilik orqali erni va signal chizig'ini taxtangizning A0 piniga ulang.

Ushbu ketma -ket qarshilik analog kirishni himoya qiladi va qo'ng'iroqni oldini oladi. Qo'ng'iroqni oldini olish uchun iloji boricha yuqori bo'lishi va ADCni tezda zaryad qilish uchun etarlicha past oqim bo'lishi kerak. ADC kirishiga ulangan signalning kutilayotgan impedansini bilish uchun MCU ma'lumotlar jadvaliga qarang.

Bu demo uchun men 440 Gts chastotali sinusoidal signalni 5 volt atrofida sinusoidal signal bilan ta'minlash uchun funktsiya generatoridan foydalandim (agar amplitudasi 3 dan 5 voltgacha bo'lsa, ADC to'liq shkalada ishlatilsa yaxshi bo'ladi), 1,2 KOm qarshilik orqali.

7 -qadam: Haqiqiy signalni tahlil qilish - kodlash

0) kutubxonani qo'shing

#"arduinoFFT.h" ni qo'shing

1) Deklaratsiyalar va misollar

Deklaratsiya bo'limida biz ADC kirishini (A0), namunalar sonini va namuna olish chastotasini, oldingi misoldagi kabi aniqlaymiz.

const bayt adcPin = 0; // A0

const uint16_t namunalari = 1024; // Bu qiymat har doim 2 const kuchga ega bo'lishi kerak uint16_t samplelingFrequency = 8000; // timer_setup () da taymerning maksimal qiymatiga ta'sir qiladi SYSCLOCK/8/samplelingFrekans butun son bo'lishi kerak

Biz ArduinoFFT ob'ektini yaratamiz

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, namunalar, namuna olish chastotasi);

2) Taymer va ADCni sozlash

Biz taymer 1 ni o'rnatdik, shunda u namuna olish chastotasida (8 KGts) aylanadi va chiqishni taqqoslashda uzilishni oshiradi.

void timer_setup () {

// taymerni qayta o'rnatish 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bit (CS11) | bit (WGM12); // CTC, 8 TIMSK1 = oldindan hisoblagich = bit (OCIE1B); OCR1A = ((16000000/8) / namuna olish chastotasi) -1; }

Va ADCni shunday sozlang

  • Kirish sifatida A0 dan foydalaniladi
  • Har bir taymerda avtomatik ravishda 1 ta chiqish taqqoslash mos keladi
  • Konvertatsiya tugagandan so'ng uzilish hosil qiladi

ADC soati 1 MGts ga o'rnatiladi, 16 soatlik tizimli soatni oldindan belgilash orqali. Har bir konvertatsiya taxminan 13 soatni to'liq hajmda bajarganligi sababli, konvertatsiyaga 1/13 = 0,076 MGts = 76 KGts chastotada erishish mumkin. Namuna olish chastotasi 76 kHz dan ancha past bo'lishi kerak, bu esa ADC ma'lumotlarini tanlab olish uchun vaqt ajratishi mumkin. (biz fs = 8 KHz ni tanladik).

void adc_setup () {

ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // ADC -ni yoqing, ADCSRA | = bit (ADPS2) tugagandan so'ng uzilishni xohlang; // 16 ADMUX = bit (REFS0) oldindan hisoblagichi | (adcPin & 7); // ADC kirishini sozlash ADCSRB = bit (ADTS0) | bit (ADTS2); // Taymer/hisoblagich1 solishtiring Match B tetik manbai ADCSRA | = bit (ADATE); // avtomatik ishga tushirishni yoqish}

Biz har bir ADC konvertatsiyasidan keyin chaqiriladigan, vReal massivida ayirilgan ma'lumotlarni saqlash va uzilishlarni tozalash uchun chaqiriladigan uzilish ishlovchilarini e'lon qilamiz.

// ADC to'liq ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; if (resultNumber == namuna) {ADCSRA = 0; // ADCni o'chirish}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Siz Arduino (analogRead) da ADC konvertatsiyasi haqida to'liq tushuntirishga ega bo'lishingiz mumkin.

3) sozlash

O'rnatish funktsiyasida biz xayoliy ma'lumotlar jadvalini tozalaymiz va taymer va ADCni sozlash funktsiyalarini chaqiramiz

nol I (); // barcha xayoliy ma'lumotlarni 0 ga o'rnatgan funksiya - oldingi bo'limda tushuntirilgan

timer_setup (); adc_setup ();

3) halqa

FFT.dcRemoval (); // ADC erga havola qilinganligi sababli, ushbu signalning doimiy komponentini olib tashlang

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward); // FFT.compute ma'lumotlarini tortish (FFTDirection:: Forward); // Hisoblash FFT FFT.complexToMagnitude (); // Hisob kattaliklari // spektr va asosiy chastotani chop etish f0 PrintVector (vReal, (namunalar >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Serial.print ("f0 ="); Ketma -ket chop etish (x, 6); Serial.println ("Hz");

Biz DC komponentini olib tashlaymiz, chunki ADC erga tegishli va signal taxminan 2,5 volt atrofida markazlashtirilgan.

Keyin biz oldingi misolda aytilganidek ma'lumotlarni hisoblaymiz.

8 -qadam: Haqiqiy signalni tahlil qilish - natijalar

Haqiqiy signalni tahlil qilish - natijalar
Haqiqiy signalni tahlil qilish - natijalar

Darhaqiqat, biz bu oddiy signalda faqat bitta chastotani ko'ramiz. Hisoblangan asosiy chastota 440.118194 Hz. Bu erda yana qiymat haqiqiy chastotaning juda yaqin taxminidir.

9 -qadam: kesilgan sinusoidal signal haqida nima deyish mumkin?

Qisqartirilgan sinusoidal signal haqida nima deyish mumkin?
Qisqartirilgan sinusoidal signal haqida nima deyish mumkin?

Keling, signalning amplitudasini 5 voltdan oshirib, ADC ni biroz oshirib yuboramiz, shuning uchun u kesiladi. ADC kirishini yo'q qilmaslik uchun juda shoshmang!

Biz ba'zi harmonikalar paydo bo'lishini ko'rishimiz mumkin. Signalni kesish yuqori chastotali komponentlarni hosil qiladi.

Siz Arduino doskasida FFT tahlilining asoslarini ko'rdingiz. Endi siz namuna olish chastotasini, namunalar sonini va oyna parametrini o'zgartirishga urinib ko'rishingiz mumkin. Kutubxona FFTni kamroq aniqlik bilan tezroq hisoblash uchun ba'zi parametrlarni qo'shadi. Agar siz namuna olish chastotasini juda past qilib qo'ygan bo'lsangiz, spektral katlama tufayli hisoblangan kattaliklar umuman noto'g'ri ko'rinadi.

Tavsiya: