Isi kandungan:

1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284: 9 Langkah
1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284: 9 Langkah

Video: 1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284: 9 Langkah

Video: 1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284: 9 Langkah
Video: #828 Using Oscilloscope as a Spectrum Analyzer (FFT) 2024, Julai
Anonim
1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284
1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284
1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284
1024 Sampel FFT Spectrum Analyzer Menggunakan Atmega1284

Tutorial yang agak mudah ini (memandangkan kerumitan perkara ini) akan menunjukkan kepada anda bagaimana anda dapat membuat penganalisis spektrum 1024 sampel yang sangat mudah menggunakan papan jenis Arduino (1284 Narrow) dan plotter bersiri. Apa-apa jenis papan serasi Arduino akan dilakukan, tetapi semakin banyak RAM yang dimilikinya, resolusi frekuensi terbaik akan anda dapatkan. Ia memerlukan lebih dari 8 KB RAM untuk mengira FFT dengan 1024 sampel.

Analisis spektrum digunakan untuk menentukan komponen frekuensi utama suatu isyarat. Banyak bunyi (seperti yang dihasilkan oleh alat muzik) terdiri daripada frekuensi asas dan beberapa harmonik yang mempunyai frekuensi yang merupakan gandaan bilangan bulat dari frekuensi asas. Penganalisis spektrum akan menunjukkan kepada anda semua komponen spektrum ini.

Anda mungkin ingin menggunakan penyediaan ini sebagai pembilang frekuensi atau untuk memeriksa sebarang jenis isyarat yang anda disyaki membawa bunyi bising di litar elektronik anda.

Kami akan memberi tumpuan di sini pada bahagian perisian. Sekiranya anda ingin membuat litar tetap untuk aplikasi tertentu, anda perlu memperkuat dan menyaring isyarat. Pra-penyesuaian ini bergantung sepenuhnya pada isyarat yang ingin anda kaji, bergantung pada amplitud, impedans, frekuensi maksimum dan lain-lain… Anda boleh menyemak

Langkah 1: Memasang Perpustakaan

Kami akan menggunakan perpustakaan ArduinoFFT yang ditulis oleh Enrique Condes. Oleh kerana kami ingin mengosongkan RAM sebanyak mungkin, kami akan menggunakan cawangan pengembangan repositori ini yang memungkinkan untuk menggunakan jenis data apungan (bukannya dua kali ganda) untuk menyimpan data sampel dan dikira. Oleh itu, kita mesti memasangnya secara manual. Jangan bimbang, muat turun arkib dan padamkannya di folder perpustakaan Arduino anda (contohnya pada konfigurasi lalai Windows 10: C: / Users / _your_user_name_ / Documents / Arduino / library)

Anda boleh memastikan perpustakaan dipasang dengan betul dengan menyusun salah satu contoh yang disediakan, seperti "FFT_01.ino."

Langkah 2: Konsep Transformasi Fourier dan FFT

Amaran: jika anda tidak tahan melihat notasi matematik anda mungkin ingin melangkah ke Langkah 3. Bagaimanapun, jika anda tidak mendapatkan semuanya, pertimbangkan kesimpulan di akhir bahagian.

Spektrum frekuensi diperoleh melalui algoritma Transformasi Fourier Cepat. FFT adalah pelaksanaan digital yang menghampiri konsep matematik Transformasi Fourier. Di bawah konsep ini apabila anda mendapat evolusi isyarat mengikut paksi masa, anda dapat mengetahui perwakilannya dalam domain frekuensi, yang terdiri daripada nilai kompleks (nyata + khayalan). Konsepnya bersifat timbal balik, jadi apabila anda mengetahui perwakilan domain frekuensi, anda dapat mengubahnya kembali ke domain waktu dan mendapatkan kembali isyarat seperti sebelum transformasi.

Tetapi apa yang akan kita lakukan dengan set nilai kompleks yang dikira dalam domain masa ini? Sebilangan besarnya akan diserahkan kepada jurutera. Bagi kami, kami akan memanggil algoritma lain yang akan mengubah nilai kompleks ini menjadi data kepadatan spektrum: iaitu nilai magnitud (= intensiti) yang dikaitkan dengan setiap jalur frekuensi. Bilangan frekuensi akan sama dengan bilangan sampel.

Anda pastinya biasa dengan konsep penyamaan, seperti ini Kembali ke 1980-an Dengan Grafik EQ. Kita akan memperoleh hasil yang sama tetapi dengan 1024 band dan bukannya 16 dan resolusi intensiti yang lebih banyak. Apabila penyamaan memberikan pandangan muzik global, analisis spektrum halus memungkinkan untuk mengira secara tepat intensiti setiap 1024 band.

Konsep yang sempurna, tetapi:

  1. Oleh kerana FFT adalah versi digital dari transformasi Fourier, ia mendekati isyarat digital, dan kehilangan beberapa maklumat. Jadi, secara tegas, hasil FFT jika diubah dengan algoritma FFT terbalik tidak akan memberikan isyarat yang tepat.
  2. Teorinya juga menganggap isyarat yang tidak terbatas, tetapi itu adalah isyarat berterusan yang kekal. Oleh kerana kami akan mendigitalkannya hanya untuk jangka waktu tertentu (contohnya), beberapa lagi kesalahan akan diperkenalkan.
  3. Akhirnya resolusi penukaran analog ke digital akan mempengaruhi kualiti nilai yang dikira.

Dalam latihan

1) Kekerapan pensampelan (diperhatikan fs)

Kami akan mengambil sampel isyarat, iaitu mengukur amplitudnya, setiap 1 / fs saat. fs adalah frekuensi persampelan. Sebagai contoh jika kita mengambil sampel pada 8 KHz, ADC (analog ke digital converter) yang berada di atas cip akan memberikan pengukuran setiap 1/8000 saat.

2) Jumlah sampel (dinyatakan N atau sampel dalam kod)

Oleh kerana kita perlu mendapatkan semua nilai sebelum menjalankan FFT, kita harus menyimpannya dan oleh itu kita akan menghadkan bilangan sampel. Algoritma FFT memerlukan sejumlah sampel iaitu kekuatan 2. Semakin banyak sampel yang kita miliki lebih baik tetapi memerlukan banyak memori, lebih-lebih lagi kita juga perlu menyimpan data yang diubah, yang merupakan nilai yang kompleks. Perpustakaan Arduino FFT menjimatkan sedikit ruang dengan menggunakan

  • Satu array bernama "vReal" untuk menyimpan data sampel dan kemudian bahagian sebenar dari data yang diubah
  • Satu array bernama "vImag" untuk menyimpan bahagian khayalan dari data yang diubah

Jumlah RAM yang diperlukan sama dengan 2 (tatasusila) * 32 (bit) * N (sampel).

Jadi di Atmega1284 kami yang mempunyai 16 KB RAM yang bagus, kami akan menyimpan maksimum N = 16000 * 8/64 = 2000 nilai. Oleh kerana bilangan nilai mestilah kekuatan 2, kami akan menyimpan maksimum 1024 nilai.

3) Resolusi frekuensi

FFT akan menghitung nilai untuk jalur frekuensi seberapa banyak bilangan sampel. Jalur ini akan merangkumi dari 0 HZ hingga frekuensi persampelan (fs). Oleh itu, resolusi frekuensi adalah:

Fresolution = fs / N

Resolusi lebih baik apabila lebih rendah. Oleh itu, untuk resolusi yang lebih baik (lebih rendah) kami mahukan:

  • lebih banyak sampel, dan / atau
  • fs yang lebih rendah

Tetapi …

4) Minimum fs

Oleh kerana kita ingin melihat banyak frekuensi, beberapa di antaranya jauh lebih tinggi daripada "frekuensi asas" kita tidak dapat menetapkan fs terlalu rendah. Sebenarnya ada teorema persampelan Nyquist-Shannon yang memaksa kita untuk mempunyai frekuensi persampelan jauh di atas dua kali frekuensi maksimum yang ingin kita uji.

Sebagai contoh, jika kita ingin menganalisis semua spektrum dari 0 Hz hingga 15 KHz, yang merupakan frekuensi maksimum yang dapat didengar oleh kebanyakan manusia, kita harus menetapkan frekuensi pengambilan sampel pada 30 KHz. Malah, pakar elektronik sering menetapkannya pada frekuensi maksimum 2.5 (atau bahkan 2.52) *. Dalam contoh ini ialah 2.5 * 15 KHz = 37.5 KHz. Frekuensi pensampelan biasa dalam audio profesional ialah 44.1 KHz (rakaman CD audio), 48 KHz dan banyak lagi.

Kesimpulan:

Titik 1 hingga 4 membawa kepada: kami mahu menggunakan seberapa banyak sampel. Dalam kes kami dengan peranti RAM 16 KB, kami akan mempertimbangkan 1024 sampel. Kami ingin mengambil sampel pada frekuensi persampelan serendah mungkin, selagi cukup tinggi untuk menganalisis frekuensi tertinggi yang kami jangkakan dalam isyarat kami (sekurang-kurangnya 2.5 * frekuensi ini).

Langkah 3: Meniru Isyarat

Meniru Isyarat
Meniru Isyarat

Untuk percubaan pertama kami, kami sedikit akan mengubah contoh TFT_01.ino yang diberikan di perpustakaan, untuk menganalisis isyarat yang terdiri daripada

  • Frekuensi asas, ditetapkan ke 440 Hz (muzikal A)
  • Harmonik ke-3 pada separuh daya asas ("-3 dB")
  • Harmonik ke-5 pada 1/4 kekuatan asas ("-6 dB)

Anda dapat melihat dalam gambar di atas isyarat yang dihasilkan. Ia kelihatan seperti isyarat nyata yang kadang-kadang dapat dilihat pada osiloskop (saya akan menyebutnya "Batman") dalam keadaan apabila terdapat kliping isyarat sinusoidal.

Langkah 4: Analisis Isyarat Simulasi - Pengekodan

0) Sertakan perpustakaan

#sertakan "arduinoFFT.h"

1) Definisi

Di bahagian deklarasi, kita ada

const byte adcPin = 0; // A0

const uint16_t sampel = 1024; // Nilai ini HARUS SELALU menjadi kekuatan 2 const uint16_t samplingFrequency = 8000; // Akan mempengaruhi nilai maksimum pemasa dalam timer_setup () SYSCLOCK / 8 / samplingFrequency harus berupa bilangan bulat

Oleh kerana isyarat mempunyai harmonik ke-5 (frekuensi harmonik ini = 5 * 440 = 2200 Hz) kita perlu menetapkan frekuensi persampelan di atas 2.5 * 2200 = 5500 Hz. Di sini saya memilih 8000 Hz.

Kami juga menyatakan susunan tempat kami menyimpan data mentah dan dikira

float vReal [sampel];

float vImag [sampel];

2) Instantiasi

Kami membuat objek ArduinoFFT. Versi dev dari ArduinoFFT menggunakan templat sehingga kita dapat menggunakan jenis data float atau data ganda. Float (32 bit) cukup berkaitan dengan ketepatan keseluruhan program kami.

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, sampel, samplingFrequency);

3) Mensimulasikan isyarat dengan mengisi array vReal, dan bukannya mengisi dengan nilai ADC.

Pada awal Loop kami mengisi array vReal dengan:

kitaran apungan = (((sampel) * signalFrequency) / samplingFrequency); // Bilangan kitaran isyarat yang akan dibaca oleh sampel

untuk (uint16_t i = 0; i <samples; i ++) {vReal = float ((amplitudo * (sin ((i * (TWO_PI * cycle)) / sampel))))); / * Membina data dengan positif dan nilai negatif * / vReal + = float ((amplitudo * (sin ((3 * i * (TWO_PI * cycle)) / sampel))) / 2.0); / * Membina data dengan nilai positif dan negatif * / vReal + = terapung ((amplitudo * (sin ((5 * i * (DUA_PI * kitaran)) / sampel))) / 4.0); / * Bina data dengan nilai positif dan negatif * / vImag = 0.0; // Bahagian khayalan mesti disifatkan sekiranya berlaku gelung untuk mengelakkan pengiraan dan limpahan yang salah}

Kami menambah digitalisasi gelombang asas dan dua harmonik dengan amplitud yang kurang. Daripada kita memulakan array khayalan dengan angka nol. Oleh kerana tatasusunan ini dihuni oleh algoritma FFT, kita perlu menghapusnya lagi sebelum setiap pengiraan baru.

4) Pengkomputeran FFT

Kemudian kami mengira FFT dan kepadatan spektrum

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

FFT.compute (FFTDirection:: Maju); / * Hitung FFT * / FFT.complexToMagnitude (); / * Hitungkan magnitud * /

Operasi FFT.windowing (…) mengubah data mentah kerana kami menjalankan FFT pada jumlah sampel yang terhad. Sampel pertama dan terakhir menunjukkan ketakselanjaran (tidak ada "apa-apa" di sebelahnya). Ini adalah sumber ralat. Operasi "Window" cenderung mengurangkan ralat ini.

FFT.compute (…) dengan arah "Maju" menghitung transformasi dari domain waktu ke domain frekuensi.

Kemudian kami menghitung nilai magnitud (iaitu intensiti) untuk setiap jalur frekuensi. Susunan vReal kini dipenuhi dengan nilai magnitud.

5) Lukisan plotter bersiri

Mari cetak nilai pada plotter bersiri dengan memanggil fungsi printVector (…)

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

Ini adalah fungsi generik yang memungkinkan untuk mencetak data dengan paksi masa atau paksi frekuensi.

Kami juga mencetak frekuensi jalur yang mempunyai nilai magnitud tertinggi

terapung x = FFT.majorPeak ();

Serial.print ("f0 ="); Cetakan bersiri (x, 6); Serial.println ("Hz");

Langkah 5: Analisis Isyarat Simulasi - Hasil

Analisis Isyarat Simulasi - Hasil
Analisis Isyarat Simulasi - Hasil

Kami melihat 3 lonjakan yang sesuai dengan frekuensi asas (f0), harmonik ke-3 dan ke-5, dengan separuh dan 1/4 magnitud f0, seperti yang diharapkan. Kita boleh membaca di bahagian atas tetingkap f0 = 440.430114 Hz. Nilai ini tidak betul-betul 440 Hz, kerana semua alasan yang dijelaskan di atas, tetapi sangat dekat dengan nilai sebenarnya. Sangat mustahak untuk menunjukkan begitu banyak perpuluhan yang tidak signifikan.

Langkah 6: Analisis Isyarat Sebenar - Pendawaian ADC

Analisis Isyarat Sebenar - Pendawaian ADC
Analisis Isyarat Sebenar - Pendawaian ADC

Oleh kerana kami tahu bagaimana meneruskan teori, kami ingin menganalisis isyarat sebenar.

Pendawaiannya sangat sederhana. Sambungkan tanah bersama dan garis isyarat ke pin A0 papan anda melalui perintang siri dengan nilai 1 KOhm hingga 10 KOhm.

Perintang siri ini akan melindungi input analog dan mengelakkan berdering. Ia mesti setinggi mungkin untuk mengelakkan deringan, dan serendah mungkin untuk menyediakan arus yang mencukupi untuk mengecas ADC dengan cepat. Rujuk ke lembar data MCU untuk mengetahui jangkaan impedans isyarat yang disambungkan pada input ADC.

Untuk demo ini saya menggunakan generator fungsi untuk memberi isyarat sinusoidal frekuensi 440 Hz dan amplitud sekitar 5 volt (lebih baik jika amplitudnya antara 3 hingga 5 volt sehingga ADC digunakan hampir skala penuh), melalui perintang 1.2 KOhm.

Langkah 7: Analisis Isyarat Sebenar - Pengekodan

0) Sertakan perpustakaan

#sertakan "arduinoFFT.h"

1) Pengisytiharan dan penekanan

Di bahagian deklarasi kita menentukan input ADC (A0), jumlah sampel dan frekuensi pengambilan sampel, seperti pada contoh sebelumnya.

const byte adcPin = 0; // A0

const uint16_t sampel = 1024; // Nilai ini HARUS SELALU menjadi kekuatan 2 const uint16_t samplingFrequency = 8000; // Akan mempengaruhi nilai maksimum pemasa dalam timer_setup () SYSCLOCK / 8 / samplingFrequency harus berupa bilangan bulat

Kami membuat objek ArduinoFFT

ArduinoFFT FFT = ArduinoFFT (vReal, vImag, sampel, samplingFrequency);

2) Penyediaan pemasa dan ADC

Kami menetapkan pemasa 1 sehingga berputar pada frekuensi persampelan (8 KHz) dan menimbulkan gangguan pada perbandingan output.

kekosongan timer_setup () {

// tetapkan semula Pemasa 1 TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; TCCR1B = bit (CS11) | bit (WGM12); // CTC, prescaler 8 TIMSK1 = bit (OCIE1B); OCR1A = ((16000000/8) / Frekuensi pensampelan) -1; }

Dan tetapkan ADC supaya

  • Menggunakan A0 sebagai input
  • Pencetus secara automatik pada setiap output pemasa 1 membandingkan perlawanan B
  • Menghasilkan gangguan apabila penukaran selesai

Jam ADC ditetapkan pada 1 MHz, dengan menetapkan preskripsi jam sistem (16 MHz) sebanyak 16. Oleh kerana setiap penukaran mengambil kira-kira13 jam pada skala penuh, penukaran dapat dicapai pada frekuensi 1/13 = 0.076 MHz = 76 KHz. Kekerapan pensampelan harus jauh lebih rendah daripada 76 KHz untuk membiarkan ADC mempunyai masa untuk mengambil sampel data. (kami memilih fs = 8 KHz).

batal adc_setup () {

ADCSRA = bit (ADEN) | bit (ADIE) | bit (ADIF); // hidupkan ADC, mahu gangguan setelah selesai ADCSRA | = bit (ADPS2); // Prescaler 16 ADMUX = bit (REFS0) | (adcPin & 7); // menetapkan input ADC ADCSRB = bit (ADTS0) | bit (ADTS2); // Timer / Counter1 Bandingkan sumber pencetus Match B ADCSRA | = bit (ADATE); // hidupkan pemicu automatik}

Kami menyatakan pengendali interrupt yang akan dipanggil setelah setiap penukaran ADC untuk menyimpan data yang ditukar dalam array vReal, dan membersihkan gangguan

// ADC lengkap ISR

ISR (ADC_vect) {vReal [resultNumber ++] = ADC; jika (resultNumber == sampel) {ADCSRA = 0; // matikan ADC}} EMPTY_INTERRUPT (TIMER1_COMPB_vect);

Anda boleh mendapatkan penjelasan lengkap mengenai penukaran ADC di Arduino (analogRead).

3) Persediaan

Dalam fungsi persediaan kita membersihkan jadual data khayalan dan memanggil fungsi pemasa dan penyediaan ADC

zeroI (); // fungsi yang menetapkan 0 semua data khayalan - dijelaskan di bahagian sebelumnya

pemasa_setup (); adc_setup ();

3) Gelung

Penghapusan FFT.dc (); // Keluarkan komponen DC isyarat ini kerana ADC dirujuk ke tanah

FFT.windowing (FFTWindow:: Hamming, FFTDirection:: Maju); // Timbang data FFT.compute (FFTDirection:: Forward); // Kira FFT FFT.complexToMagnitude (); // Mengira magnitud // mencetak spektrum dan frekuensi asas f0 PrintVector (vReal, (sampel >> 1), SCL_FREQUENCY); terapung x = FFT.majorPeak (); Serial.print ("f0 ="); Cetakan bersiri (x, 6); Serial.println ("Hz");

Kami mengeluarkan komponen DC kerana ADC dirujuk ke tanah dan isyarat berpusat sekitar 2.5 volt lebih kurang.

Kemudian kami menghitung data seperti yang dijelaskan dalam contoh sebelumnya.

Langkah 8: Analisis Isyarat Sebenar - Hasil

Analisis Isyarat Sebenar - Hasil
Analisis Isyarat Sebenar - Hasil

Kita hanya melihat satu frekuensi dalam isyarat sederhana ini. Frekuensi asas yang dikira ialah 440.118194 Hz. Di sini sekali lagi nilainya adalah penghampiran frekuensi sebenar yang sangat dekat.

Langkah 9: Bagaimana dengan Isyarat Sinusoidal yang Dipotong?

Bagaimana dengan Isyarat Sinusoidal yang Dipotong?
Bagaimana dengan Isyarat Sinusoidal yang Dipotong?

Sekarang mari kita melampaui sedikit ADC dengan meningkatkan amplitud isyarat di atas 5 volt, sehingga terpotong. Jangan tekan terlalu banyak agar tidak merosakkan input ADC!

Kita dapat melihat beberapa harmoni muncul. Memotong isyarat menghasilkan komponen frekuensi tinggi.

Anda telah melihat asas analisis FFT di papan Arduino. Sekarang anda boleh mengubah frekuensi pensampelan, bilangan sampel dan parameter berliku. Perpustakaan juga menambah beberapa parameter untuk mengira FFT lebih cepat dengan ketepatan yang lebih sedikit. Anda akan melihat bahawa jika anda menetapkan frekuensi pensampelan terlalu rendah, magnitud yang dikira akan kelihatan salah kerana lipatan spektrum.

Disyorkan: