Tartalomjegyzék:

1024 minta FFT spektrumanalizátor Atmega1284 használatával: 9 lépés
1024 minta FFT spektrumanalizátor Atmega1284 használatával: 9 lépés

Videó: 1024 minta FFT spektrumanalizátor Atmega1284 használatával: 9 lépés

Videó: 1024 minta FFT spektrumanalizátor Atmega1284 használatával: 9 lépés
Videó: 📡 Siglent SSA3032X Spectrum Analyzer Review & Experiments 2024, Július
Anonim
1024 minta FFT spektrumanalizátor Atmega1284 segítségével
1024 minta FFT spektrumanalizátor Atmega1284 segítségével
1024 minta FFT spektrumanalizátor Atmega1284 segítségével
1024 minta FFT spektrumanalizátor Atmega1284 segítségével

Ez a viszonylag egyszerű bemutató (figyelembe véve a téma összetettségét) megmutatja, hogyan készíthet egy nagyon egyszerű 1024 mintás spektrum elemzőt egy Arduino típusú tábla (1284 Narrow) és a soros plotter segítségével. Bármilyen Arduino -kompatibilis kártya megteszi, de minél több RAM -mal rendelkezik, annál jobb frekvenciafelbontást kap. Több mint 8 KB RAM -ra lesz szüksége az FFT 1024 mintával történő kiszámításához.

A spektrumanalízist használjuk a jel fő frekvenciaösszetevőinek meghatározására. Sok hang (például egy hangszer által előállított) alapfrekvenciából és néhány harmonikusból áll, amelyek frekvenciája az alapfrekvencia egész többszöröse. A spektrumanalizátor megmutatja ezeket a spektrális komponenseket.

Érdemes ezt a beállítást frekvenciaszámlálóként használni, vagy ellenőrizni minden olyan jelet, amelyről feltételezi, hogy valamilyen zajt hoz létre az elektronikus áramkörben.

Itt a szoftver részre összpontosítunk. Ha állandó áramkört szeretne létrehozni egy adott alkalmazáshoz, akkor erősítenie és szűrnie kell a jelet. Ez az előkondícionálás teljesen függ a vizsgálni kívánt jeletől, annak amplitúdójától, impedanciájától, maximális frekvenciájától stb. Függően … Ellenőrizheti a

1. lépés: A könyvtár telepítése

Az ArduinoFFT könyvtárat fogjuk használni, amelyet Enrique Condes írt. Mivel a RAM -ot a lehető legnagyobb mértékben szeretnénk kímélni, ennek a tárnak a fejlesztési ágát fogjuk használni, amely lehetővé teszi a float adattípus használatát (kettős helyett) a mintavételezett és számított adatok tárolására. Tehát manuálisan kell telepítenünk. Ne aggódjon, csak töltse le az archívumot, és bontsa ki az Arduino könyvtármappájában (például a Windows 10 alapértelmezett konfigurációjában: C: / Users / _your_user_name_ / Documents / Arduino / libraries)

Ellenőrizheti, hogy a könyvtár helyesen van -e telepítve, ha összeállítja a megadott példák egyikét, például az "FFT_01.ino" -t.

2. lépés: Fourier -transzformáció és FFT -fogalmak

Figyelmeztetés: ha nem bírja látni a matematikai jelöléseket, akkor érdemes átugrani a 3. lépésre. Mindenesetre, ha nem kapja meg az egészet, fontolja meg a szakasz végén található következtetést.

A frekvenciaspektrumot egy gyors Fourier -transzformációs algoritmus segítségével kapjuk meg. Az FFT egy digitális megvalósítás, amely közelíti a Fourier -transzformáció matematikai koncepcióját. E koncepció szerint, ha megkapja a jel evolúcióját egy időtengely után, megismerheti annak ábrázolását egy frekvenciatartományban, amely összetett (valós + képzeletbeli) értékekből áll. A koncepció kölcsönös, tehát ha ismeri a frekvenciatartomány ábrázolását, akkor átalakíthatja azt vissza az időtartományba, és pontosan úgy kaphatja vissza a jelet, mint az átalakítás előtt.

De mit fogunk kezdeni ezzel a számított komplex értékkészlettel az időtartományban? Nos, a legtöbbet mérnökökre bízzák. Számunkra egy másik algoritmust fogunk hívni, amely ezeket az összetett értékeket spektrális sűrűségű adatokká alakítja át: ez az egyes frekvenciasávokhoz tartozó nagyságrendű (= intenzitás) érték. A frekvenciasávok száma megegyezik a minták számával.

Ön bizonyára ismeri a hangszínszabályzó koncepcióját, mint ez Vissza az 1980 -as évekhez A grafikus hangszínszabályzóval. Nos, ugyanazokat az eredményeket fogjuk elérni, de 16 helyett 1024 sávval és sokkal nagyobb intenzitással. Amikor a hangszínszabályozó átfogó képet ad a zenéről, a finom spektrális elemzés lehetővé teszi az 1024 sáv mindegyikének intenzitásának pontos kiszámítását.

Tökéletes koncepció, de:

  1. Mivel az FFT a Fourier -transzformáció digitalizált változata, közelíti a digitális jelet, és elveszít néhány információt. Tehát szigorúan véve az FFT eredménye, ha visszafordítjuk egy fordított FFT algoritmussal, nem adja meg pontosan az eredeti jelet.
  2. Ezenkívül az elmélet olyan jelet vesz figyelembe, amely nem véges, de ez egy állandó, állandó jel. Mivel csak egy bizonyos ideig digitalizáljuk (azaz mintákat), további hibákat vezetünk be.
  3. Végül az analóg -digitális átalakítás felbontása befolyásolja a számított értékek minőségét.

Gyakorlatban

1) A mintavételi gyakoriság (jegyzett fs)

1/fs másodpercenként mintát veszünk, azaz megmérjük annak amplitúdóját. fs a mintavételi frekvencia. Például, ha 8 KHz -en veszünk mintát, a chip fedélzetén található ADC (analóg -digitális átalakító) 1/8000 másodpercenként mérést végez.

2) A minták száma (feltüntetett N vagy minták a kódban)

Mivel az FFT futtatása előtt meg kell szereznünk az összes értéket, ezeket tárolnunk kell, és így korlátozni fogjuk a minták számát. Az FFT algoritmusnak számos mintára van szüksége, amelyek teljesítménye 2. Minél több mintánk van, annál jobb, de sok memóriát igényel, annál is inkább szükségünk lesz az átalakított adatok tárolására, amelyek összetett értékek. Az Arduino FFT könyvtár némi helyet takarít meg a használatával

  • Az egyik „vReal” nevű tömb tárolja a mintavételezett adatokat, majd az átalakított adatok valódi részét
  • Az egyik tömb "vImag" az átalakított adatok képzeletbeli részének tárolására

A szükséges RAM mennyiség 2 (tömb) * 32 (bit) * N (minta).

Tehát az Atmega1284 -ben, amely szép 16 KB RAM -mal rendelkezik, maximum N = 16000*8/64 = 2000 értéket tárolunk. Mivel az értékek számának 2 -nek kell lennie, maximum 1024 értéket tárolunk.

3) A frekvencia felbontása

Az FFT annyi frekvenciasávot fog kiszámítani, mint a minták száma. Ezek a sávok 0 HZ -tól a mintavételi frekvenciáig (fs) terjednek. Ezért a frekvencia felbontása:

Feloldás = fs / N

A felbontás jobb, ha alacsonyabb. Tehát a jobb felbontás érdekében (alacsonyabb) szeretnénk:

  • több minta, és/vagy
  • egy alacsonyabb fs

De…

4) Minimális fs

Mivel sok frekvenciát szeretnénk látni, némelyik sokkal magasabb, mint az "alapfrekvencia", ezért nem állíthatjuk túl alacsonyra az f -eket. Valójában létezik a Nyquist – Shannon mintavételi tétel, amely arra kényszerít bennünket, hogy a mintavételi frekvencia jóval meghaladja a tesztelni kívánt maximális frekvencia kétszeresét.

Például, ha a 0 Hz -től egészen 15 KHz -ig terjedő spektrumot elemezni szeretnénk, ami körülbelül a maximális frekvencia, amit a legtöbb ember határozottan hall, akkor a mintavételi frekvenciát 30 KHz -re kell állítanunk. Valójában az elektronikusok gyakran 2,5 (vagy akár 2,52) * -ra állítják a maximális gyakoriságot. Ebben a példában ez 2,5 * 15 KHz = 37,5 KHz lenne. A professzionális hang szokásos mintavételi frekvenciája 44,1 KHz (audio CD felvétel), 48 KHz és több.

Következtetés:

Az 1-4. Pontok a következőkhöz vezetnek: a lehető legtöbb mintát szeretnénk felhasználni. Esetünkben 16 KB RAM -eszköz esetén 1024 mintát veszünk figyelembe. A lehető legalacsonyabb mintavételi gyakorisággal szeretnénk mintát venni, amennyiben elég magas ahhoz, hogy elemezzük a jelünkben elvárható legmagasabb frekvenciát (legalább 2,5 * ez a frekvencia).

3. lépés: Jel szimulálása

Jel szimulálása
Jel szimulálása

Első próbálkozásunkhoz kissé módosítjuk a könyvtárban megadott TFT_01.ino példát, hogy elemezzük a

  • Az alapfrekvencia 440 Hz -re van beállítva (zenei A)
  • 3. felharmonikus az alap teljesítmény felénél ("-3 dB")
  • 5. felharmonikus az alapvető teljesítmény 1/4-én ("-6 dB)

A kapott jel felett látható képen látható. Valójában nagyon hasonlít egy valódi jelre, amelyet néha egy oszcilloszkópon ("Batman" -nak neveznék) láthatunk abban a helyzetben, amikor egy szinuszos jel kivágása történik.

4. lépés: Szimulált jel - kódolás elemzése

0) Tartalmazza a könyvtárat

#include "arduinoFFT.h"

1) Fogalommeghatározások

A nyilatkozatok szakaszban van

const bájt adcPin = 0; A0

const uint16_t minták = 1024; // Ennek az értéknek MINDIG 2 konstansnak kell lennie uint16_t samplingFrequency = 8000; // Befolyásolja az időzítő maximális értékét a timer_setup () SYSCLOCK/8/samplingFrekvenciában egésznek kell lennie

Mivel a jelnek 5. harmonikusa van (ennek a felharmonikusnak a frekvenciája = 5 * 440 = 2200 Hz), a mintavételi frekvenciát 2,5 * 2200 = 5500 Hz fölé kell állítanunk. Itt a 8000 Hz -et választottam.

Emellett deklaráljuk azokat a tömböket, ahol a nyers és számított adatokat tároljuk

float vReal [minták];

float vImag [minták];

2) Instantiation

Létrehozunk egy ArduinoFFT objektumot. Az ArduinoFFT fejlesztői verziója sablont használ, így használhatjuk a float vagy a double adattípust. A lebegés (32 bit) elegendő a programunk általános pontosságához.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, minták, samplingFrequency);

3) A jel szimulálása a vReal tömb feltöltésével, ahelyett, hogy ADC értékekkel töltenénk fel.

A ciklus elején feltöltjük a vReal tömböt:

lebegési ciklusok = ((((minták) * jelFrekvencia) / samplingFrequency); // A mintavétel által leolvasott jelciklusok száma

for (uint16_t i = 0; i <minták; i ++) {vReal = float ((amplitúdó * (sin ((i * (TWO_PI * ciklus)) / minták)))))); / * Adatok építése pozitív és negatív értékek */ vReal += float ((amplitúdó * (sin ((3 * i * (TWO_PI * ciklus)))))/ minták)))/ 2.0);/ * Adatok készítése pozitív és negatív értékekkel */ vReal += lebegés ((amplitúdó * (sin ((5 * i * (TWO_PI * ciklus)))) / minták)))) / 4.0); / * Adatok készítése pozitív és negatív értékekkel * / vImag = 0,0; // A képzeletbeli részt nullázni kell hurokolás esetén a hibás számítások és túlcsordulások elkerülése érdekében}

Hozzáadjuk az alaphullám és a két kisebb amplitúdójú harmonikus digitalizálását. Inkább inicializáljuk a képzeletbeli tömböt nullákkal. Mivel ezt a tömböt az FFT algoritmus tölti ki, újra kell törölnünk minden új számítás előtt.

4) FFT számítástechnika

Ezután kiszámítjuk az FFT -t és a spektrális sűrűséget

FFT.ablak (FFTWindow:: Hamming, FFTDirection:: Előre);

FFT.compute (FFTDirection:: Előre); / * FFT számítása */ FFT.complexToMagnitude (); / * Nagyságok kiszámítása */

Az FFT.windowing (…) művelet módosítja a nyers adatokat, mert az FFT -t korlátozott számú mintán futtatjuk. Az első és az utolsó minta diszkontinuitást mutat (egyik oldalon nincs "semmi"). Ez hibaforrás. Az "ablak" művelet általában csökkenti ezt a hibát.

Az "Előre" irányú FFT.compute (…) kiszámítja az átalakítást az időtartományból a frekvenciatartományba.

Ezután kiszámítjuk az egyes frekvenciasávok nagyságrendi (azaz intenzitási) értékeit. A vReal tömb most nagyságrendekkel van tele.

5) Soros plotter rajz

Nyomtassuk ki az értékeket a soros plotterre a printVector (…) függvény meghívásával

PrintVector (vReal, (minták >> 1), SCL_FREQUENCY);

Ez egy általános funkció, amely lehetővé teszi adatok nyomtatását idő- vagy frekvenciatengellyel.

A sáv frekvenciáját is kinyomtatjuk, amelynek a legnagyobb a magnitúdója

float x = FFT.majorPeak ();

Soros.nyomtatás ("f0 ="); Sorozatnyomat (x, 6); Soros.println ("Hz");

5. lépés: Szimulált jel elemzése - eredmények

Szimulált jel elemzése - eredmények
Szimulált jel elemzése - eredmények

Látunk 3 tüskét, amelyek megfelelnek az alapfrekvenciának (f0), a 3. és 5. harmonikusnak, a várakozásoknak megfelelően az f0 nagyságának felével és 1/4 részével. Az ablak tetején olvashatjuk f0 = 440,430114 Hz. A fenti okok miatt ez az érték nem pontosan 440 Hz, de nagyon közel van a valós értékhez. Igazából nem volt szükség ennyi jelentéktelen tizedes mutatására.

6. lépés: Valódi jel elemzése - Az ADC bekötése

Valódi jel elemzése - Az ADC bekötése
Valódi jel elemzése - Az ADC bekötése

Mivel elméletben tudjuk, hogyan kell továbblépni, szeretnénk egy valódi jelet elemezni.

A huzalozás nagyon egyszerű. Csatlakoztassa a földeléseket és a jelvezetéket az alaplap A0 -as csatlakozójához 1 KOhm és 10 KOhm közötti ellenálláson keresztül.

Ez a soros ellenállás megvédi az analóg bemenetet és elkerüli a csengetést. A lehető legmagasabbnak kell lennie, hogy elkerülje a csengetést, és a lehető legalacsonyabbnak ahhoz, hogy elegendő áramot biztosítson az ADC gyors feltöltéséhez. Tekintse meg az MCU adatlapját, hogy megtudja az ADC bemenetre csatlakoztatott jel várható impedanciáját.

Ehhez a bemutatóhoz egy funkciógenerátort használtam egy 440 Hz frekvenciájú és 5 volt körüli amplitúdójú szinuszos jel táplálásához (a legjobb, ha az amplitúdó 3 és 5 volt között van, így az ADC -t a teljes skála közelében használják), 1,2 KOhm ellenálláson keresztül.

7. lépés: Valódi jel elemzése - kódolás

0) Tartalmazza a könyvtárat

#include "arduinoFFT.h"

1) Nyilatkozatok és példák

A nyilatkozat részben definiáljuk az ADC bemenetet (A0), a minták számát és a mintavételi gyakoriságot, mint az előző példában.

const bájt adcPin = 0; A0

const uint16_t minták = 1024; // Ennek az értéknek MINDIG 2 konstansnak kell lennie uint16_t samplingFrequency = 8000; // Befolyásolja az időzítő maximális értékét a timer_setup () SYSCLOCK/8/samplingFrekvenciában egésznek kell lennie

Létrehozzuk az ArduinoFFT objektumot

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, minták, samplingFrequency);

2) Időzítő és ADC beállítás

Az 1. időzítőt úgy állítottuk be, hogy a mintavételi frekvencián (8 KHz) ciklusozzon, és megszakítást eredményez a kimeneti összehasonlításban.

void timer_setup () {

// reset Timer 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bit (CS11) | bit (WGM12); // CTC, előbeosztó 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000 /8) / mintavételi gyakoriság) -1; }

És állítsa be az ADC -t

  • Az A0 -t használja bemenetként
  • Automatikusan aktivál minden egyes időzítő 1 kimenetén összehasonlítja a B egyezést
  • Megszakítást generál, amikor az átalakítás befejeződött

Az ADC órajele 1 MHz -re van beállítva a rendszeróra (16 MHz) 16 -os előskálázásával. Mivel minden átalakítás körülbelül 13 órát vesz igénybe teljes skálán, az átalakítás 1/13 = 0,076 MHz = 76 KHz frekvencián érhető el. A mintavételi gyakoriságnak lényegesen alacsonyabbnak kell lennie, mint 76 KHz, hogy az ADC -nek legyen ideje az adatok mintavételére. (fs = 8 KHz -et választottunk).

void adc_setup () {

ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // az ADC bekapcsolása, megszakítás befejezése után ADCSRA | = bit (ADPS2); // Előrehívó 16 ADMUX = bit (REFS0) | (adcPin & 7); // az ADC bemenet beállítása ADCSRB = bit (ADTS0) | bit (ADTS2); // Időzítő/számláló1 Hasonlítsa össze a B egyezési trigger forrást ADCSRA | = bit (ADATE); // bekapcsolni az automatikus indítást}

Kijelentjük a megszakításkezelőt, amelyet minden ADC -konverzió után meghívnak, hogy tárolja a konvertált adatokat a vReal tömbben, és törölje a megszakítást

// ADC teljes ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; if (resultNumber == minták) {ADCSRA = 0; // az ADC kikapcsolása}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Kimerítő magyarázatot kaphat az Arduino ADC konverziójáról (analogRead).

3) Beállítás

A beállítási funkcióban töröljük a képzeletbeli adattáblát, és meghívjuk az időzítő és az ADC beállítási funkcióit

nullaI (); // olyan függvény, amely az összes képzeletbeli adatot 0 -ra állította - az előző részben ismertettük

timer_setup (); adc_setup ();

3) Hurok

FFT.dcRemoval (); // Távolítsa el a jel egyenáramú összetevőjét, mivel az ADC földre van hivatkozva

FFT.ablak (FFTWindow:: Hamming, FFTDirection:: Előre); // Adatok mérése FFT.compute (FFTDirection:: Előre); // FFT kiszámítása FFT.complexToMagnitude (); // Nagyságok kiszámítása // a spektrum és az alapvető frekvencia nyomtatása f0 PrintVector (vReal, (minták >> 1), SCL_FREQUENCY); float x = FFT.majorPeak (); Soros.nyomtatás ("f0 ="); Sorozatnyomat (x, 6); Soros.println ("Hz");

Az egyenáramú komponenst eltávolítjuk, mert az ADC a földre van hivatkozva, és a jel körülbelül 2,5 volt körüli középpontban van.

Ezután kiszámítjuk az adatokat az előző példában leírtak szerint.

8. lépés: Valódi jel elemzése - eredmények

Valódi jel elemzése - eredmények
Valódi jel elemzése - eredmények

Valójában csak egy frekvenciát látunk ebben az egyszerű jelben. A számított alapfrekvencia 440,118194 Hz. Itt is az érték a valós frekvencia nagyon közelítő közelítése.

9. lépés: Mi a helyzet a levágott szinuszos jellel?

Mi a helyzet a kivágott szinuszos jelzéssel?
Mi a helyzet a kivágott szinuszos jelzéssel?

Most engedjük egy kicsit túlhajtani az ADC -t azáltal, hogy a jel amplitúdóját 5 volt fölé növeljük, így le van vágva. Ne nyomjon túl pépet, nehogy megsemmisítse az ADC bemenetet!

Láthatunk néhány felharmonikus megjelenését. A jel kivágása nagyfrekvenciás komponenseket hoz létre.

Látta az FFT elemzés alapjait egy Arduino táblán. Most megpróbálhatja megváltoztatni a mintavételi gyakoriságot, a minták számát és az ablak paramétert. A könyvtár néhány paramétert is hozzáad az FFT gyorsabb és kisebb pontosságú kiszámításához. Észre fogja venni, hogy ha túl alacsonyra állítja a mintavételi frekvenciát, a számított nagyságok teljesen hibásnak tűnnek a spektrális hajtogatás miatt.

Ajánlott: