Мазмуну:

1024 Samples FFT спектр анализатору Atmega1284: 9 кадамдарын колдонуу
1024 Samples FFT спектр анализатору Atmega1284: 9 кадамдарын колдонуу

Video: 1024 Samples FFT спектр анализатору Atmega1284: 9 кадамдарын колдонуу

Video: 1024 Samples FFT спектр анализатору Atmega1284: 9 кадамдарын колдонуу
Video: Анализатор аудио спектра на Arduino своими руками 2024, Июль
Anonim
1024 үлгүлөрү FFT спектр анализатору Atmega1284 менен
1024 үлгүлөрү FFT спектр анализатору Atmega1284 менен
1024 үлгүлөрү FFT спектр анализатору Atmega1284 менен
1024 үлгүлөрү FFT спектр анализатору Atmega1284 менен

Бул салыштырмалуу оңой үйрөткүч (бул теманын татаалдыгын эске алуу менен) сизге Arduino тибиндеги тактаны (1284 тар) жана сериялык плоттерди колдонуу менен 1024 үлгүдөгү спектр анализаторун кантип жасоону көрсөтөт. Arduino менен шайкеш келген ар кандай такта жасайт, бирок RAM канчалык көп болсо, сиз эң жакшы жыштык чечимин аласыз. ФФТны 1024 үлгү менен эсептөө үчүн 8 КБдан ашык RAM керек болот.

Спектр анализи сигналдын негизги жыштык компоненттерин аныктоо үчүн колдонулат. Көптөгөн үндөр (музыкалык аспапта чыгарылгандай) фундаменталдык жыштыктан жана кээ бир гармоникалардан турат, ал жыштыгы бүтүн сандын негизги жыштыгына барабар. Спектр анализатору сизге бул спектралдык компоненттердин бардыгын көрсөтөт.

Сиз бул орнотууну жыштык эсептегич катары колдонууну же электрондук схемаңызга кандайдыр бир ызы -чуу алып келет деп шектелген сигналдардын бардыгын текшерүүнү каалашыңыз мүмкүн.

Биз бул жерде программалык камсыздоо бөлүгүнө токтолобуз. Эгерде сиз конкреттүү тиркеме үчүн туруктуу схема жасоону кааласаңыз, анда сигналды күчөтүп, чыпкалоо керек болот. Бул алдын ала кондиционер сиз окуган сигналга толугу менен көз каранды, анын амплитудасына, импедансына, максималдуу жыштыгына жана башкаларга жараша болот. Https://www.instructables.com/id/Analog-Sensor-Sig… текшере аласыз

1 -кадам: Китепкананы орнотуу

Биз Enrique Condes жазган ArduinoFFT китепканасын колдонобуз. Биз RAMди мүмкүн болушунча көбүрөөк сактоону каалаганыбыз үчүн, бул репозиторийдин иштелип чыккан бөлүмүн колдонобуз, ал үлгүлүү жана эсептелген маалыматтарды сактоо үчүн калкып жүрүүчү маалымат түрүн (эки эселенгендин ордуна) колдонууга мүмкүнчүлүк берет. Андыктан кол менен орнотушубуз керек. Кабатыр болбоңуз, архивди жүктөп алып, Arduino китепкана папкаңыздан чыгарыңыз (мисалы, Windows 10дун демейки конфигурациясында: C: / Users / _your_user_name_ / Documents / Arduino / library)

"FFT_01.ino" сыяктуу берилген мисалдардын бирин түзүп, китепкананын туура орнотулганын текшере аласыз.

2 -кадам: Фурье трансформациясы жана FFT түшүнүктөрү

Эскертүү: эгер сиз математикалык белгилерди көрө албасаңыз, анда 3 -кадамга өтүүнү каалашыңыз мүмкүн. Баары бир, эгерде баарын түшүнбөсөңүз, бөлүмдүн аягындагы тыянакты карап көрүңүз.

Жыштык спектри Fast Fourier Transform алгоритми аркылуу алынат. FFT - бул Фурье трансформациясынын математикалык концепциясын болжолдогон санариптик ишке ашыруу. Убакыт огунун артынан сигналдын эволюциясын алгандан кийин, бул түшүнүк боюнча анын татаал (реалдуу + элестүү) баалуулуктардан турган жыштык домениндеги өкүлчүлүгүн биле аласыз. Концепция эки тараптуу, андыктан жыштыктын домендик өкүлчүлүгүн билгенде, аны кайра убакыт доменине которуп, трансформацияга чейинкидей сигналды кайра кайтарып алсаңыз болот.

Бирок биз убакыт домениндеги бул эсептелген татаал баалуулуктар топтому менен эмне кылабыз? Ооба, анын көбү инженерлерге калат. Биз үчүн бул татаал баалуулуктарды спектралдык тыгыздыкка айландыра турган дагы бир алгоритмди чакырабыз: бул ар бир жыштык диапазону менен байланышкан чоңдуктун (= интенсивдүүлүгүнүн) мааниси. Жыштык тилкесинин саны үлгүлөрдүн санына барабар болот.

Сиз, албетте, эквалайзер түшүнүгү менен таанышсыз, бул сыяктуу 1980 -жылдарга чейин кайра Graphic EQ менен. Ооба, биз ушундай эле натыйжаларга ээ болобуз, бирок 16 эмес, 1024 диапазону жана андан да көп интенсивдүүлүк. Эквалайзер музыканын глобалдык көрүнүшүн бергенде, майда спектрдик анализ 1024 диапазондорунун ар биринин интенсивдүүлүгүн так эсептөөгө мүмкүндүк берет.

Идеалдуу түшүнүк, бирок:

  1. FFT Фурьенин санариптештирилген версиясы болгондуктан, ал санариптик сигналга жакындайт жана кээ бир маалыматты жоготот. Ошентип, так айтканда, FFTдин натыйжасы тескери FFT алгоритми менен кайра өзгөртүлсө, оригиналдуу сигналды бербейт.
  2. Ошондой эле теория чексиз эмес, бирок түбөлүктүү туруктуу сигнал деп эсептейт. Биз аны белгилүү бир убакытка (башкача айтканда үлгүлөргө) гана санариптештире тургандыктан, дагы кээ бир каталар киргизилет.
  3. Акырында аналогду санарипке которуу эсептелген баалуулуктардын сапатына таасирин тийгизет.

Иш жүзүндө

1) тандоо ылдамдыгы (fs белгиледи)

Биз сигналдын үлгүсүн алабыз, б.а. анын амплитудасын өлчөйбүз, ар бир 1/сек секундда. fs - бул тандоо ылдамдыгы. Мисалы, эгер биз 8 КГцте үлгү алсак, анда чиптин бортунда турган ADC (санариптик конвертерге аналог) ар бир 1/8000 секундда өлчөөнү камсыз кылат.

2) үлгүлөрдүн саны (коддо N же үлгүлөр белгиленген)

Биз FFTди иштетүүдөн мурун бардык баалуулуктарды алышыбыз керек болгондуктан, биз аларды сакташыбыз керек, ошондуктан биз үлгүлөрдүн санын чектейбиз. FFT алгоритмине 2 кубаттуулугу бар бир катар үлгүлөр керек. Бизде канчалык көп үлгүлөр болсо, ошончолук жакшы болот, бирок ал көп эс тутумду талап кылат, ошончолук биз татаал баалуулуктар болгон трансформацияланган маалыматтарды сакташыбыз керек болот. Arduino FFT китепканасы колдонуу менен мейкиндикти үнөмдөйт

  • Тандалган маалыматтарды, андан кийин трансформацияланган маалыматтын чыныгы бөлүгүн сактоо үчүн "vReal" аттуу бир массив
  • Которулган маалыматтын элестүү бөлүгүн сактоо үчүн "vImag" аттуу бир массив

RAMдын керектүү суммасы 2ге барабар (массивдер) * 32 (биттер) * N (үлгүлөр).

Ошентип, 16 КБ оперативдүү RAM бар Atmega1284, биз максималдуу N = 16000*8/64 = 2000 маанилерди сактайбыз. Баалардын саны 2 кубаттуулукта болушу керек болгондуктан, максимум 1024 маанини сактайбыз.

3) Жыштыктын чечилиши

FFT үлгүлөрдүн санына жараша канча жыштык диапазонунда баалуулуктарды эсептейт. Бул диапазондор 0 Гцтен тандоо ылдамдыгына чейин жетет (fs). Демек, жыштыктын чечилиши:

Fresolution = fs / N

Чечим төмөн болгондо жакшы болот. Ошентип, жакшыраак чечим үчүн (төмөн) биз каалайбыз:

  • дагы үлгүлөр жана/же
  • төмөнкү fs

Бирок…

4) Минималдуу фс

Биз көп жыштыктарды көргүбүз келгендиктен, алардын айрымдары "фундаменталдык жыштыктан" алда канча жогору, биз fs өтө төмөн кое албайбыз. Чындыгында, бизди сынап көрүүнү каалаган максималдуу жыштыктан эки эсе жогору ылдамдыкка ээ болууга мажбурлаган Nyquist -Shannon тандалма теоремасы бар.

Мисалы, эгер биз 0 Гцтен баштап бардык спектрди 15 КГцке чейин анализдөөнү кааласак, бул болжол менен көпчүлүк адамдар так уга ала турган максималдуу жыштык, биз тандап алуу жыштыгын 30 КГцке коюшубуз керек. Негизи электрониктер аны көбүнчө 2,5 (же 2,52) * эң жогорку жыштыкка коюшат. Бул мисалда бул 2,5 * 15 КГц = 37,5 КГц болмок. Профессионалдык аудиодогу адаттагыдай жыштыктар 44.1 КГц (аудио CD жазуу), 48 КГц жана башкалар.

Жыйынтык:

1ден 4кө чейинки упайлар: биз мүмкүн болушунча көп үлгүлөрдү колдонууну каалайбыз. Биздин учурда 16 КБ оперативдүү түзмөк менен биз 1024 үлгүнү карайбыз. Биз сигналда күткөн эң жогорку жыштыкты анализдөө үчүн жетишерлик жогору болгончо, мүмкүн болушунча эң төмөнкү тандоо ылдамдыгында үлгү алгыбыз келет (жок дегенде 2,5 * бул жыштык).

3 -кадам: Сигналды тууроо

Сигналды симуляциялоо
Сигналды симуляциялоо

Биринчи аракетибиз үчүн, китепканада берилген TFT_01.ino мисалын бир аз өзгөртүп, сигналды анализдөө үчүн

  • Негизги жыштык, 440 Гцке коюлган (музыкалык А)
  • Үчүнчү гармоник фундаменталдык кубаттуулуктун жарымында ("-3 дБ")
  • Фундаменталдык кубаттуулуктун 1/4 бөлүгүндөгү 5-гармония ("-6 дБ)

Сиз пайда болгон сигналдын үстүндөгү сүрөттө көрө аласыз. Чынында, бул синусоидалык сигналдын кыркылышы болгондо, кээде осциллографта (мен аны "Батман" деп атайм) көрө турган чыныгы сигналга абдан окшош.

4 -кадам: окшоштурулган сигналдын анализи - коддоо

0) китепкананы камтыйт

#"arduinoFFT.h" кошуу

1) Аныктамалар

Декларация бөлүмдөрүндө бизде бар

const байт adcPin = 0; // A0

const uint16_t үлгүлөрү = 1024; // Бул маани ар дайым 2 const uint16_t samplingFrequency = 8000 кубаттуулугу болушу керек; // Таймердин максималдуу маанисине таасирин тийгизет timer_setup () SYSCLOCK/8/sampleling

Сигнал 5 -ші гармоникага ээ болгондуктан (бул гармониктин жыштыгы = 5 * 440 = 2200 Гц) биз тандап алуу жыштыгын 2,5 * 2200 = 5500 Гцтен жогору коюшубуз керек. Бул жерде мен 8000 Гцти тандадым.

Биз ошондой эле чийки жана эсептелген маалыматтарды сактай турган массивдерди жарыялайбыз

float vReal [үлгүлөр];

float vImag [үлгүлөр];

2) Ыкчамдоо

Биз ArduinoFFT объектисин түзөбүз. ArduinoFFTтин dev версиясы шаблонду колдонот, андыктан биз калкып чыгууну же кош маалымат түрүн колдоно алабыз. Float (32 бит) биздин программанын тактыгына байланыштуу жетиштүү.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, үлгүлөр, samplingFrequency);

3) vReal массивин толтуруу менен сигналды симуляциялоо, аны ADC баалуулуктары менен толтуруунун ордуна.

Циклдин башында vReal массивин толтурабыз:

сүзүү циклдери = (((үлгүлөр) * signalFrequency) / samplingFrequency); // Тандоо окуй турган сигнал циклдеринин саны

for (uint16_t i = 0; i <үлгүлөр; i ++) {vReal = калкып чыгуу ((амплитудасы * (күнөө ((i * (TWO_PI * циклдери)) / үлгүлөрү)))))); / * Оң жана терс баалуулуктар */ vReal += калкып чыгуу ((амплитудасы * (күнөө ((3 * i * (TWO_PI * циклдер))/ үлгүлөр)))/ 2.0);/ * Оң жана терс мааниси бар маалыматтарды түзүү */ vReal += калкып чыгуу ((амплитудасы * (күнөө ((5 * i * (TWO_PI * циклдер)) / үлгүлөр))) / 4.0); / * Оң жана терс мааниси бар маалыматтарды түзүү * / vImag = 0.0; // Туура эмес эсептөөлөрдү жана толуп кетүүлөрдү болтурбоо үчүн, элестүү бөлүк нөлгө салынышы керек}

Биз негизги толкундун санариптештирүүсүн жана эки амплитудасы аз гармониканы кошобуз. Биз элестеткен массивди нөлдөр менен баштайбыз. Бул массив FFT алгоритми менен толтурулгандыктан, биз аны ар бир жаңы эсептөөнүн алдында кайра тазалашыбыз керек.

4) FFT эсептөө

Андан кийин биз ФФТны жана спектралдык тыгыздыкты эсептейбиз

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

FFT.compute (FFTDirection:: Forward); / * Compute FFT */ FFT.complexToMagnitude (); / * Чоңдуктарды эсептөө */

FFT.windowing (…) операциясы чийки маалыматты өзгөртөт, анткени биз FFTди чектелген сандагы үлгүлөрдө иштетебиз. Биринчи жана акыркы үлгүлөр үзгүлтүккө учурайт (алардын бир тарабында "эч нерсе" жок). Бул катанын булагы. "Терезе" операциясы бул катаны азайтат.

FFT.compute (…) "Алга" багыты менен убакыт доменинен жыштык доменине которууну эсептейт.

Андан кийин биз ар бир жыштык диапазонунун чоңдугун (б.а. интенсивдүүлүгүн) эсептейбиз. VReal массиви азыр чоңдуктун маанилери менен толтурулат.

5) Сериялык плоттер чиймеси

PrintVector функциясын чакырып, баалуулуктарды сериялык плоттерге басып чыгаралы (…)

PrintVector (vReal, (үлгүлөр >> 1), SCL_FREQUENCY);

Бул убакыт огу же жыштык огу менен маалыматтарды басып чыгарууга мүмкүнчүлүк берген жалпы функция.

Биз ошондой эле эң чоң баллга ээ болгон жыштыкты басып чыгарабыз

float x = FFT.majorPeak ();

Serial.print ("f0 ="); Serial.print (x, 6); Serial.println ("Гц");

5 -кадам: окшоштурулган сигналдын анализи - жыйынтыктар

Симуляцияланган сигналдын анализи - Жыйынтыктар
Симуляцияланган сигналдын анализи - Жыйынтыктар

Биз күткөндөй, f0 чоңдугунун жарымы жана 1/4 бөлүгү менен, негизги жыштыкка (f0), 3 -жана 5 -гармоникаларга туура келген 3 чукулду көрөбүз. Биз терезенин жогору жагында окуй алабыз f0 = 440.430114 Гц. Бул маани 440 Гц эмес, жогоруда түшүндүрүлгөн бардык себептерден улам, бирок чыныгы баага абдан жакын. Анча маанилүү эмес ондуктарды көрсөтүү чынында эле зарыл болгон эмес.

6 -кадам: Чыныгы сигналдын анализи - ADCге зым тартуу

Чыныгы сигналдын анализи - ADCге зым тартуу
Чыныгы сигналдын анализи - ADCге зым тартуу

Теорияда кантип улантуу керектигин билгендиктен, чыныгы сигналды анализдөөнү каалайбыз.

Кабелдер абдан жөнөкөй. Негиздерди жана сигнал линиясын тактаңыздын A0 пинине 1 КОмдон 10 КОмго чейинки сериядагы резистор аркылуу туташтырыңыз.

Бул сериядагы резистор аналогдук кирүүнү коргойт жана шыңгыроодон сактайт. Бул шыңгыроону болтурбоо үчүн мүмкүн болушунча жогору жана ADCти тез заряддоо үчүн жетиштүү токту камсыз кылуу үчүн мүмкүн болушунча төмөн болушу керек. ADC киришине туташкан сигналдын күтүлгөн импедансын билүү үчүн MCU маалымат барагына кайрылыңыз.

Бул демо үчүн мен 440 Гц жана амплитудасы 5 вольттун тегерегиндеги синусоидалдык сигналды берүү үчүн функция генераторун колдондум (амплитудасы 3 менен 5 вольттун ортосунда болсо жакшы, ошондуктан ADC толук масштабда колдонулат), 1.2 КОм резистор аркылуу.

7 -кадам: Чыныгы сигналдын анализи - коддоо

0) китепкананы камтыйт

#"arduinoFFT.h" кошуу

1) Декларациялар жана инстанциялар

Декларация бөлүмүндө биз ADC киргизүүнү (A0), үлгүлөрдүн санын жана тандоо мисалын мурунку мисалда көрсөтүлгөндөй аныктайбыз.

const байт adcPin = 0; // A0

const uint16_t үлгүлөрү = 1024; // Бул маани ар дайым 2 const uint16_t samplingFrequency = 8000 кубаттуулугу болушу керек; // Таймердин максималдуу маанисине таасирин тийгизет timer_setup () SYSCLOCK/8/sampleling Frequency бүтүн сан болушу керек

Биз ArduinoFFT объектисин түзөбүз

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, үлгүлөр, samplingFrequency);

2) Таймер жана ADC орнотуу

Биз таймерди 1 койдук, андыктан ал тандоо ылдамдыгында (8 КГц) айланат жана өндүрүштү салыштырууда үзгүлтүккө учуратат.

жараксыз timer_setup () {

// баштапкы абалга келтирүү Таймер 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = бит (CS11) | бит (WGM12); // CTC, prescaler 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000 /8) / samplingFrequency) -1; }

Жана ADCди ушундай орнотуңуз

  • Киргизүү катары A0 колдонот
  • Ар бир таймерде автоматтык түрдө триггерлер 1 чыгаруу салыштыруу матч Б.
  • Конверсия аяктагандан кийин үзгүлтүккө учуратат

ADC сааты 1 МГцке, системалык саатты (16 МГц) 16га чейин алдын ала коюу менен коюлат. Ар бир конверсия толук масштабда болжол менен 13 саатты талап кылгандыктан, 1/13 = 0,076 МГц = 76 КГц жыштыгында конверсиялоого болот. Тандоо ылдамдыгы ADCге маалыматтарды тандап алууга убакыт берүү үчүн 76 КГцтен кыйла төмөн болушу керек. (fs = 8 KHz тандап алдык).

жараксыз adc_setup () {

ADCSRA = бит (ADEN) | бит (ADIE) | бит (ADIF); // ADC күйгүзүү, ADCSRA аяктагандан кийин үзгүлтүккө учуроону каалоо | = бит (ADPS2); // Prescaler of 16 ADMUX = bit (REFS0) | (adcPin & 7); // ADC кирүүсүн орнотуу ADCSRB = бит (ADTS0) | бит (ADTS2); // Таймер/Счетчик1 Салыштыр матч B триггер булагы ADCSRA | = бит (ADATE); // автоматтык түрдө иштетүүнү күйгүзүү}

Биз vReal массивинде конверттелген маалыматтарды сактоо жана үзгүлтүктү тазалоо үчүн ар бир ADC конверсиясынан кийин чакырыла турган үзгүлтүк иштетүүчү деп жарыялайбыз.

// ADC толук ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; if (resultNumber == үлгүлөрү) {ADCSRA = 0; // ADC өчүрүү}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Сиз Arduino (analogRead) боюнча ADC конверсиясы боюнча толук түшүндүрмө ала аласыз.

3) Орнотуу

Орнотуу функциясында биз ойдон чыгарылган маалымат столун тазалап, таймерди жана ADC орнотуу функцияларын чакырабыз

zeroI (); // бардык ойдон чыгарылган маалыматтарды 0 деп койгон функция - мурунку бөлүмдө түшүндүрүлгөн

timer_setup (); adc_setup ();

3) Цикл

FFT.dcRemoval (); // ADC жерге шилтеме берилгендиктен, бул сигналдын DC компонентин алып салыңыз

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Forward); // Таразалоо маалыматы FFT.compute (FFTDirection:: Forward); // Эсептөө FFT FFT.complexToMagnitude (); // Эсептөө чоңдуктары // спектрди жана ф0 фундаменталдык баскычын басып чыгаруу PrintVector (vReal, (үлгүлөр >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Serial.print ("f0 ="); Serial.print (x, 6); Serial.println ("Гц");

Биз DC компонентин алып салабыз, анткени ADC жерге таандык жана сигнал болжол менен 2,5 вольттун тегерегинде.

Андан кийин биз мурунку мисалда түшүндүрүлгөндөй маалыматтарды эсептейбиз.

8 -кадам: Реалдуу сигналдын анализи - Натыйжалар

Реалдуу сигналдын анализи - Жыйынтыктар
Реалдуу сигналдын анализи - Жыйынтыктар

Чынында, биз бул жөнөкөй сигналда бир гана жыштыкты көрөбүз. Эсептелген негизги жыштык 440.118194 Гц. Бул жерде дагы бир мааниси реалдуу жыштыкка абдан жакын жакындатуу.

9 -кадам: Кысылган синусоидалык сигнал жөнүндө эмне айтууга болот?

Кысылган синусоидалык сигнал жөнүндө эмне айтууга болот?
Кысылган синусоидалык сигнал жөнүндө эмне айтууга болот?

Эми сигналдын амплитудасын 5 вольттон жогорулатуу менен ADCди бир аз ашырып жиберели, андыктан ал кесилет. ADC киргизүүнү жок кылбоо үчүн өтө эле катуу түртпөңүз!

Биз кээ бир гармоникалардын пайда болгонун көрө алабыз. Сигналды кесүү жогорку жыштыктагы компоненттерди түзөт.

Сиз Arduino тактасында FFT анализинин негиздерин көрдүңүз. Эми сиз тандоо ылдамдыгын, үлгүлөрдүн санын жана терезенин параметрин өзгөртүүгө аракет кылсаңыз болот. Китепкана FFTди азыраак тактык менен тезирээк эсептөө үчүн кээ бир параметрлерди кошот. Эгер сиз тандап алуу жыштыгын өтө төмөн койсоңуз, спектралдык бүктөлүүдөн улам эсептелген чоңдуктар таптакыр туура эмес болуп калат.

Сунушталууда: