Isi kandungan:

EasyFFT: Transformasi Fourier Cepat (FFT) untuk Arduino: 6 Langkah
EasyFFT: Transformasi Fourier Cepat (FFT) untuk Arduino: 6 Langkah

Video: EasyFFT: Transformasi Fourier Cepat (FFT) untuk Arduino: 6 Langkah

Video: EasyFFT: Transformasi Fourier Cepat (FFT) untuk Arduino: 6 Langkah
Video: Digital Signal Processing (3MB) Alarm Kerusakan Mesin Cuci dengan Algoritma FFT Berbasis Arduino UNO 2024, September
Anonim
Image
Image

Pengukuran frekuensi dari isyarat yang ditangkap boleh menjadi tugas yang sukar, terutama pada Arduino kerana ia memiliki daya komputasi yang lebih rendah. Terdapat kaedah yang tersedia untuk menangkap persilangan sifar di mana frekuensi ditangkap dengan memeriksa berapa kali isyarat melintasi garis sifar dalam masa yang ditentukan. Kaedah sedemikian mungkin tidak berfungsi apabila isyarat adalah gabungan pelbagai frekuensi.

Ini agak sukar untuk dikodkan jika anda bukan dari latar belakang seperti itu. Tetapi menjadi pengingat kod ini mungkin sangat berguna untuk pelbagai projek yang berkaitan dengan muzik, analisis isyarat. Motif projek ini adalah untuk menyiapkan kod yang mudah dilaksanakan di Arduino tanpa masuk ke latar belakangnya.

Projek ini tidak menjelaskan Cara Kerja FFT tetapi menjelaskan penerapan fungsi FFT. Proses yang sama juga dijelaskan dalam video yang dilampirkan.

Sekiranya anda hanya berminat dengan penerapan kod dan bukan untuk menerangkannya. Anda boleh melangkah terus ke langkah no 3.

Langkah 1: Pengenalan Transformasi Frekuensi

Pengenalan Transformasi Frekuensi
Pengenalan Transformasi Frekuensi
Pengenalan Transformasi Frekuensi
Pengenalan Transformasi Frekuensi

Segala isyarat boleh terdiri daripada gabungan pelbagai gelombang sinusoidal. Oleh itu, isyarat berdasarkan masa boleh ditunjukkan sebagai gabungan pelbagai sinus dengan amplitud yang berbeza.

Saya cuba menjelaskan cara kerja DFT (transformasi Fourier diskrit) dalam salah satu arahan sebelumnya (https://www.instructables.com/id/Arduino-Frequency…). Kaedah ini sangat perlahan untuk sebarang aplikasi masa nyata. yang menjadikannya hampir tidak berguna.

Dalam gambar, isyarat ditunjukkan yang merupakan gabungan dua frekuensi f2 dan f5. Isyarat ini didarabkan dengan gelombang sinus ujian dari nilai f1 hingga f5.

Ini dapat ditunjukkan secara matematis bahawa -simpalan pendaraban dua set data harmonik yang mempunyai frekuensi yang berlainan cenderung menjadi sifar (jumlah data yang lebih tinggi dapat menyebabkan hasil pemukul). Dalam kes kita, Sekiranya kedua frekuensi pendaraban ini mempunyai frekuensi yang sama (atau sangat dekat) maka jumlah pendaraban adalah nombor bukan nol.

Jadi jika isyarat kita didarabkan dengan penjumlahan pendaraban f1 akan menjadi sifar (hampir kepada sifar untuk aplikasi sebenar). sama seperti f3, f4. Walau bagaimanapun untuk nilai, output f2 dan f5 tidak akan menjadi sifar, tetapi jauh lebih tinggi daripada nilai yang lain.

Di sini isyarat diuji dengan 5 frekuensi, jadi isyarat perlu didarab dengan lima frekuensi. Pengiraan yang begitu sengit memerlukan masa yang lebih tinggi. Secara matematik ditunjukkan bahawa untuk bilangan sampel N diperlukan pendaraban kompleks N * N.

Langkah 2: Transformasi Fourier Cepat

Untuk membuat pengiraan DFT lebih cepat algoritma FFT dikembangkan oleh James Cooley dan John Tukey. Algoritma ini juga dianggap sebagai salah satu algoritma terpenting abad ke-20. Ia membahagi isyarat menjadi bahagian ganjil dan sekuens yang menjadikan sebilangan pengiraan yang diperlukan lebih rendah. Dengan menggunakannya jumlah pendaraban kompleks yang diperlukan dapat dikurangkan menjadi NlogN. yang merupakan peningkatan yang ketara.

Anda boleh merujuk rujukan di bawah yang saya rujuk semasa menulis kod untuk pemahaman terperinci mengenai matematik di sebalik FFT:

1.

2.

3.

4.

Langkah 3: Penjelasan Kod

1. Sinus cepat dan Cosine:

Pengiraan FFT mengambil nilai pelbagai sinus dan kosinus berkali-kali. Fungsi built-in Arduino tidak cukup pantas dan memerlukan banyak masa untuk memberikan nilai yang diperlukan. Yang menjadikan kod lebih perlahan (masa dua kali ganda untuk 64 sampel). Untuk mengatasi masalah ini, nilai sinus untuk 0 hingga 90 darjah disimpan sebanyak 255. Melakukannya akan menghilangkan keperluan menggunakan nombor penyimpanan sebagai apungan dan kita dapat menyimpannya sebagai bait yang mengambil ruang 1/4 di Arduino. Sine_data perlu menampal di atas kod untuk menyatakannya sebagai pemboleh ubah global.

Selain dari sine_data, array yang disebut f_peaks dinyatakan sebagai pemboleh ubah global. Selepas setiap fungsi FFT dijalankan, array ini dikemas kini. Di mana f_peaks [0] adalah frekuensi yang paling dominan dan nilai selanjutnya dalam urutan menurun.

byte sine_data [91] = {0, 4, 9, 13, 18, 22, 27, 31, 35, 40, 44, 49, 53, 57, 62, 66, 70, 75, 79, 83, 87, 91, 96, 100, 104, 108, 112, 116, 120, 124, 127, 131, 135, 139, 143, 146, 150, 153, 157, 160, 164, 167, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 206, 209, 211, 214, 216, 219, 221, 223, 225, 227, 229, 231, 233, 235, 236, 238, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255, 255}; terapung f_peaks [5];

Oleh kerana kita telah menyimpan nilai sinus untuk 0 hingga 90 darjah, sebarang nilai sinus atau kosinus dapat dikira. Di bawah berfungsi pusingan pertama nombor hingga titik perpuluhan sifar dan nilai kembali dari data yang disimpan. kaedah ini hanya memerlukan satu bahagian terapung. Ini dapat dikurangkan lagi dengan menyimpan nilai sinus secara langsung (bukan 255 gandaan). tetapi itu memakan memori tinggi di Arduino.

Menggunakan prosedur di atas mengurangkan ketepatan tetapi meningkatkan kelajuan. Untuk 64 mata, ia memberikan kelebihan 8ms dan untuk 128 mata memberikan kelebihan 20ms.

Langkah 4: Penjelasan Kod: Fungsi FFT

FFT hanya dapat dilakukan untuk ukuran sampel 2, 4, 8, 16, 32, 64 dan seterusnya. jika nilainya tidak 2 ^ n, maka nilainya akan menjadi sisi bawah. Sebagai contoh, jika kita memilih ukuran sampel 70 maka ia hanya akan mempertimbangkan 64 sampel pertama dan menghilangkan selebihnya.

Selalu disarankan untuk mempunyai ukuran sampel 2 ^ n. yang boleh:

2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, …

Dua float out_r dan out_im akan mengambil memori yang tinggi. untuk Arduino nano tidak akan berfungsi untuk sampel yang lebih tinggi daripada 128 (dan dalam beberapa kes 128) kerana kekurangan memori yang ada.

data int yang tidak ditandatangani [13] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};

int a, c1, f, o, x; a = N; untuk (int i = 0; i <12; i ++) // mengira tahap {if (data <= a) {o = i;}} int in_ps [data [o] = {}; // input untuk penjujukan float out_r [data [o] = {}; // bahagian sebenar transform float out_im [data [o] = {}; // bahagian transformasi yang berimaginasi

Aliran selanjutnya adalah seperti berikut:

1. Kod menghasilkan susunan sedikit terbalik untuk ukuran sampel yang diberikan (perincian mengenai pembalikan bit pada rujukan: langkah 2)

2. Data input dipesan mengikut pesanan yang dihasilkan, 3. FFT dilakukan

4. Amplitud bilangan kompleks dikira, 5. Puncak dikesan dan disusun mengikut urutan menurun

6. hasil boleh diakses dari f_peaks.

[untuk mengakses data lain (selain frekuensi puncak) kod harus diubah, sehingga pemboleh ubah tempatan dapat disalin ke beberapa pemboleh ubah global yang telah ditentukan]

Langkah 5: Menguji Kod

Menguji Kod
Menguji Kod
Menguji Kod
Menguji Kod

Contoh gelombang segitiga diberikan sebagai input. untuk frekuensi pensampelan gelombang ini ialah 10 Hz dan frekuensi gelombang itu sendiri adalah 1.25 Hz.

Seperti yang dapat ditunjukkan dari output mentah, nilainya sepadan dengan FFT yang dikira oleh Scilab. namun, nilai-nilai ini tidak sama persis dengan ketepatan rendah tetapi gelombang sinus lebih pantas.

Dalam frekuensi output frekuensi array adalah 1.25 dan 3.75. tidak perlu mendapatkan nilai yang tepat setiap masa. biasanya nombor ini dipanggil tong frekuensi. jadi nilai output mungkin berada di mana saja dalam tong sampah yang ditentukan.

Kelajuan:

untuk Arduino nano diperlukan:

16 Mata: 4ms32 Mata: 10ms 64 Mata: 26ms 128 Mata: 53ms

Langkah 6: Kesimpulannya

Kod FFT ini dapat digunakan dalam aplikasi masa nyata. Oleh kerana memerlukan kira-kira 30 ms untuk menyelesaikan pengiraan. Walau bagaimanapun, penyelesaiannya dibatasi oleh sebilangan sampel. Bilangan sampel dibatasi oleh memori Arduino. Dengan menggunakan Arduino Mega atau ketepatan papan prestasi lebih tinggi yang lain dapat ditingkatkan.

jika anda mempunyai pertanyaan, cadangan, atau pembetulan, sila beri komen.

Kemas kini (2/5/21)

Kemas kini: // ----------------------------- Fungsi FFT --------------- ------------------------------- // float FFT (int di , int N, Frekuensi apungan)

Jenis data N diubah menjadi Integer (Byte yang ada) untuk menyokong> 255 ukuran sampel. Sekiranya saiz sampel <= 128, jenis data bait harus digunakan.

Disyorkan: