0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何使用FFT算法分析正弦信號(hào)的頻率和幅值?

簡(jiǎn)儀科技 ? 來源:簡(jiǎn)儀科技 ? 2023-05-04 10:28 ? 次閱讀

當(dāng)使用DAQ模塊時(shí),最常見的操作之一是對(duì)采集到的數(shù)據(jù)進(jìn)行分析,其中最具代表性的操作是FFT(快速傅里葉變換)。本文將結(jié)合ChatGPT模型,演示如何使用FFT算法分析正弦信號(hào)的頻率和幅值。

(1)請(qǐng)使用C#編程,幫我實(shí)現(xiàn)一個(gè)生成幅值為2V、頻率為1000Hz的正弦波,并將數(shù)據(jù)保存到數(shù)組中

以下是用C#編寫生成幅值為2V、頻率為1000Hz的正弦波并將數(shù)據(jù)保存到數(shù)組中的代碼:

double amplitude = 2.0; // 幅值為2V

double frequency = 1000.0; // 頻率為1000Hz

double sampleRate = 44100.0; // 采樣率為44100Hz

double duration = 1.0; // 生成1秒鐘的正弦波

int numSamples = (int)(duration * sampleRate); // 計(jì)算需要生成的樣本數(shù)量

double[] samples = new double[numSamples]; // 創(chuàng)建用于保存生成數(shù)據(jù)的數(shù)組

for (int i = 0; i < numSamples; i++)

{

double time = (double)i / sampleRate; // 計(jì)算當(dāng)前時(shí)間

double value = amplitude * Math.Sin(2.0 * Math.PI * frequency * time);// 計(jì)算當(dāng)前樣本值

samples[i] = value; // 保存當(dāng)前樣本值到數(shù)組中

}

在上述代碼中,我們首先定義了幅值、頻率、采樣率和生成時(shí)長等參數(shù),并根據(jù)這些參數(shù)計(jì)算出需要生成的樣本數(shù)量。然后,我們使用一個(gè) for 循環(huán)逐個(gè)生成樣本,并將每個(gè)樣本值保存到一個(gè)數(shù)組中。

請(qǐng)注意,上述代碼生成的正弦波數(shù)據(jù)是以浮點(diǎn)數(shù)形式保存的,如果需要將其存儲(chǔ)為音頻文件,需要將其轉(zhuǎn)換為對(duì)應(yīng)的音頻格式,例如 WAV、MP3 等。

在button的Click事件中復(fù)制ChatGPT生成的代碼,同時(shí)將代碼生成的正弦信號(hào)顯示到EasyChartX上,并手動(dòng)放大,如圖

5a507ec8-e79b-11ed-ab56-dac502259ad0.png

注:請(qǐng)使用EasyChartX的Plot方法,將數(shù)組中的數(shù)據(jù)顯示在EasyChartX中,代碼調(diào)用如下:easyChartX1.Plot(samples);

在上述操作中,我們將ChatGPT模型應(yīng)用于生成正弦信號(hào),為了證明生成的信號(hào)具有指定的特征,將信號(hào)繪制到EasyChartX控件上,并進(jìn)行手動(dòng)放大。最終的結(jié)果表明,使用ChatGPT生成正弦信號(hào)是完全可行的。

(2)請(qǐng)針對(duì)上述生成的正弦信號(hào)做FFT

為了對(duì)生成的正弦信號(hào)進(jìn)行FFT,我們需要使用一些第三方庫,例如 MathNet.Numerics。

以下是一個(gè)簡(jiǎn)單的示例代碼,演示如何使用 MathNet.Numerics 庫對(duì)生成的正弦信號(hào)進(jìn)行FFT:

using MathNet.Numerics;

using MathNet.Numerics.IntegralTransforms;

double[] samples =// 假設(shè)已經(jīng)生成了正弦波數(shù)據(jù)

// 對(duì)正弦波數(shù)據(jù)進(jìn)行FFT變換

Complex[] fft = Fourier.Transform(samples);

// 計(jì)算FFT變換后每個(gè)頻率的振幅

double[] amplitudes =newdouble[fft.Length];

for(inti = 0; i < fft.Length; i++)

{

amplitudes[i] = fft[i].Magnitude;

}

在上述代碼中,我們首先使用 MathNet.Numerics 庫中的 Fourier.Transform() 函數(shù)對(duì)生成的正弦波數(shù)據(jù)進(jìn)行FFT變換,得到一個(gè)包含復(fù)數(shù)的數(shù)組 fft。然后,我們通過計(jì)算每個(gè)頻率的振幅來獲取FFT變換后的結(jié)果,并將結(jié)果保存到一個(gè)數(shù)組 amplitudes 中。

需要注意的是,由于 FFT 變換后得到的是一個(gè)對(duì)稱的頻譜,因此我們只需要考慮其中一半的數(shù)據(jù)(從下標(biāo) 0 到 N/2)即可。此外,由于 FFT 變換后的結(jié)果是對(duì)數(shù)級(jí)別的振幅,因此我們可能需要對(duì)結(jié)果進(jìn)行對(duì)數(shù)轉(zhuǎn)換或者歸一化處理。

在這里ChatGPT為我們直接提供了現(xiàn)有的類庫直接調(diào)用來對(duì)信號(hào)做FFT,那么我們可不可以讓ChatGPT來幫我們生成一個(gè)FFT的算法呢?

(3)請(qǐng)避免使用各種現(xiàn)有的類庫,請(qǐng)使用代碼幫我生成一個(gè)FFT算法,并分別計(jì)算信號(hào)頻率和幅值并顯示在兩textBox上

好的,以下是一個(gè)基于蝴蝶算法的簡(jiǎn)單FFT實(shí)現(xiàn),這個(gè)算法可以對(duì)長度為2的冪次方的數(shù)據(jù)進(jìn)行FFT變換,同時(shí)使用FFT算法來計(jì)算信號(hào)的頻率和幅值,并將其顯示在文本框。

using System;

using System.Numerics;

namespace FFTExample

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void btnCalculate_Click(object sender, EventArgs e)

{

// 將輸入的字符串轉(zhuǎn)換為 double 類型的數(shù)組

double[] inputSignal = Array.ConvertAll(txtInput.Text.Split(','), Double.Parse);

// 計(jì)算輸入信號(hào)的長度

int signalLength = inputSignal.Length;

// 為 FFT 算法分配輸入數(shù)據(jù)緩沖區(qū)

Complex[] fftBuffer = new Complex[signalLength];

// 將輸入數(shù)據(jù)復(fù)制到緩沖區(qū)中

for (int i = 0; i < signalLength; i++)

{

fftBuffer[i] = new Complex(inputSignal[i], 0);

}

// 執(zhí)行 FFT 算法

FourierTransform.FFT(fftBuffer, FourierTransform.Direction.Forward);

// 計(jì)算頻譜幅值

double[] magnitude = new double[signalLength / 2];

for (int i = 0; i < signalLength / 2; i++)

{

magnitude[i] = 2 * fftBuffer[i].Magnitude / signalLength;

}

// 計(jì)算頻率

double[] frequency = new double[signalLength / 2];

for (int i = 0; i < signalLength / 2; i++)

{

frequency[i] = (double)i / signalLength * 2 * Math.PI;

}

// 在文本框中顯示結(jié)果

txtMagnitude.Text = string.Join(",", magnitude);

txtFrequency.Text = string.Join(",", frequency);

}

}

public static class FourierTransform

{

public enum Direction

{

Forward = 1,

Backward = -1

}

public static void FFT(Complex[] buffer, Direction direction)

{

int n = buffer.Length;

if (n == 1)

{

return;

}

// 分離奇偶元素

Complex[] even = new Complex[n / 2];

Complex[] odd = new Complex[n / 2];

for (int i = 0; i < n / 2; i++)

{

even[i] = buffer[2 * i];

odd[i] = buffer[2 * i + 1];

}

// 遞歸地計(jì)算奇偶元素的 FFT

FFT(even, direction);

FFT(odd, direction);

// 合并結(jié)果

for(int i = 0; i < n / 2; i++)

{

Complex t = Complex.FromPolarCoordinates(1, -2 * (int)direction * Math.PI * i / n) * odd[i];

buffer[i] = even[i] + t;

buffer[i + n / 2] = even[i] - t;

}

}

}

}

在上述代碼中,我們首先檢查輸入數(shù)據(jù)的長度是否為2的冪次方,如果不是則拋出一個(gè)異常。然后,我們使用遞歸的方式對(duì)輸入數(shù)據(jù)進(jìn)行FFT變換。

在每次遞歸中,我們首先將輸入數(shù)據(jù)分為偶數(shù)項(xiàng)和奇數(shù)項(xiàng),并遞歸計(jì)算它們的FFT變換。然后,我們計(jì)算每個(gè)頻率的旋轉(zhuǎn)因子,用它們來組合偶數(shù)項(xiàng)和奇數(shù)項(xiàng)的結(jié)果,得到最終的FFT變換結(jié)果。

需要注意的是,由于我們使用的是遞歸算法,因此對(duì)于較大的數(shù)據(jù)集可能會(huì)導(dǎo)致棧溢出,需要使用適當(dāng)?shù)募记桑ɡ绶沁f歸實(shí)現(xiàn))來解決這個(gè)問題。

至此,ChatGPT為我們提供了FFT算法實(shí)例,該算法適用于長度為2的冪次方的數(shù)據(jù)進(jìn)行FFT變換。然而,在實(shí)際應(yīng)用中,我們需要確保任何情況下都可以完成FFT算法,因此需要解決FFT算法不適用于非2的冪次方數(shù)據(jù)的問題。

(4)若數(shù)組的長度是不是2的冪次方,該如何優(yōu)化算法使其完成FFT分析

如果輸入的數(shù)組長度不是2的冪次方,可以通過填充額外的數(shù)據(jù)使其長度成為2的冪次方,然后再對(duì)填充后的數(shù)據(jù)進(jìn)行FFT變換。

一種常見的填充方式是將輸入數(shù)組長度補(bǔ)齊到最小的2的冪次方,即將輸入數(shù)組的長度n補(bǔ)齊到2的k次方,其中k是滿足2^k >= n的最小整數(shù)??梢詫㈩~外的位置填充為0或者使用一些插值方法來填充。

填充后的數(shù)組長度為2的冪次方,可以使用上面提到的FFT算法來計(jì)算其FFT變換。計(jì)算完成后,可以僅取原始數(shù)據(jù)所占的部分,丟棄填充的0或插值的數(shù)據(jù)。

這種填充方式可能會(huì)引入一些誤差,特別是當(dāng)填充的數(shù)據(jù)與原始數(shù)據(jù)不太相似時(shí),可能會(huì)導(dǎo)致結(jié)果的精度下降。因此,如果輸入數(shù)據(jù)的長度與2的冪次方相差不大,建議直接使用快速傅里葉變換算法庫,否則可以使用上述方法對(duì)輸入數(shù)據(jù)進(jìn)行填充。

(5)最終結(jié)果

通過ChatGPT為我們提供的算法及思路,對(duì)其完成的代碼進(jìn)行修改,并在Form界面上創(chuàng)建兩個(gè)textBox和EasyChartX2,分別在兩個(gè)textBox上顯示通過算法計(jì)算得到的信號(hào)的頻率和幅值以及在EasyChartX2顯示頻譜圖,如下:

5aa10e4c-e79b-11ed-ab56-dac502259ad0.png

注:顯示在EasyChartX上的圖像是經(jīng)過拖動(dòng)放大后的圖像





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • FFT
    FFT
    +關(guān)注

    關(guān)注

    15

    文章

    432

    瀏覽量

    59192
  • ChatGPT
    +關(guān)注

    關(guān)注

    28

    文章

    1523

    瀏覽量

    7249

原文標(biāo)題:如何利用ChatGPT完成FFT算法及計(jì)算信號(hào)的頻率和幅值

文章出處:【微信號(hào):簡(jiǎn)儀科技,微信公眾號(hào):簡(jiǎn)儀科技】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【英飛凌PSoC 6 RTT開發(fā)板試用】信號(hào)處理前端之頻率相位分析

    FFT變換結(jié)果,最大的橫坐標(biāo)對(duì)應(yīng)信號(hào)頻率,縱坐標(biāo)對(duì)應(yīng)幅度。
    的頭像 發(fā)表于 07-14 09:02 ?1228次閱讀
    【英飛凌PSoC 6 RTT開發(fā)板試用】<b class='flag-5'>信號(hào)</b>處理前端之<b class='flag-5'>頻率</b><b class='flag-5'>幅</b><b class='flag-5'>值</b>相位<b class='flag-5'>分析</b>

    FFT對(duì)應(yīng)的頻率點(diǎn)不對(duì)

    使用定時(shí)器來采集ADC,采集頻率10k,采集點(diǎn)數(shù)1024, 當(dāng)波形頻率為1562.5Hz時(shí),計(jì)算應(yīng)該在Output[160]處有為1,然而fft
    發(fā)表于 09-13 10:33

    如何測(cè)量正弦信號(hào)?

    測(cè)量正弦信號(hào),超過10v點(diǎn)亮一個(gè)LED。。求給思路,最好電路圖在線等
    發(fā)表于 04-24 09:02

    如何獲取調(diào)幅信號(hào)中的直流信號(hào),以及調(diào)制信號(hào)頻率?

    0Hz的信號(hào),然后用”基本平均直流-均方根“控件能得到一個(gè)近似的,但是不確定是否正確。2、對(duì)于100Hz正弦信號(hào)
    發(fā)表于 11-03 16:29

    分別用矩形窗、漢寧窗、哈明窗、布萊克曼窗+FFT對(duì)信號(hào)進(jìn)行頻譜分析,分析各窗函數(shù)對(duì)信號(hào)FFT變換的影響

    ,并分析不同窗函數(shù)對(duì)頻譜分析的影響。2. 要求(1)產(chǎn)生一個(gè)諧波信號(hào),并顯示,要求信號(hào)
    發(fā)表于 07-14 09:50

    求問大神關(guān)于信號(hào)FFT頻域分析的問題

    求問大神?。∥野?b class='flag-5'>正弦+均勻白噪聲疊加的信號(hào)源經(jīng)過IIR濾波器濾波后,通過FFT頻譜(-相位)函數(shù)進(jìn)行頻域
    發(fā)表于 03-14 22:09

    正弦波發(fā)生電路頻率

    有人知道如何分析正弦波發(fā)生電路頻率么,十分感謝
    發(fā)表于 10-14 13:28

    正弦信號(hào)提取和相位信息方法

    利用DSP28335采集的100kHz的正弦信號(hào),想要提取信號(hào)和相位信息,應(yīng)該采用哪種方法,求大神指導(dǎo)(利用
    發(fā)表于 10-07 20:17

    分析種基于FPGA實(shí)現(xiàn)的FFT正弦頻率估計(jì)新算法

    本文結(jié)合FPGA的并行處理優(yōu)勢(shì),提出了一種利用信號(hào)FFT系數(shù)的幅度和相位信息來構(gòu)造頻率修正項(xiàng)的新算法。
    發(fā)表于 04-29 06:02

    示波器測(cè)量正弦交流信號(hào)和相位的分析

    在昨天博文使用數(shù)字示波器DS6104測(cè)量交流信號(hào)和相位 中對(duì)于使用示波器測(cè)量正弦交流信號(hào)
    發(fā)表于 08-09 06:20

    利用STM32 FFT算法計(jì)算THD

    的頻譜。包括信號(hào)在頻譜上各點(diǎn)的頻率和該點(diǎn)的。由上面的調(diào)制信號(hào)和已調(diào)信號(hào)的頻譜圖,我們可以觀察
    發(fā)表于 08-12 06:57

    求解分析正弦信號(hào),或者信號(hào)強(qiáng)度

    用接收天線接收磁棒天線發(fā)出的28.843k的正弦信號(hào),接收端用24位的ADC去采集分析,該如何用采集到的數(shù)據(jù)分析信號(hào)強(qiáng)度或
    發(fā)表于 12-15 10:14

    基于FFT正弦信號(hào)頻率估計(jì)算法

    為了進(jìn)一步提高加性高斯白噪聲背景中正弦信號(hào)頻率估計(jì)精度,提出了一種新的基于插快速傅里葉變換( FFT)的
    發(fā)表于 12-29 16:56 ?5次下載

    正弦穩(wěn)態(tài)電路的三要素(頻率、、初相位)

    本文主要介紹了正弦穩(wěn)態(tài)電路的三要素(頻率、、初相位)。周期是正弦量變化一周所需要的時(shí)間,用符號(hào)T表示,單位是秒(s)。
    發(fā)表于 03-13 11:31 ?8.9w次閱讀
    <b class='flag-5'>正弦</b>穩(wěn)態(tài)電路的三要素(<b class='flag-5'>頻率</b>、<b class='flag-5'>幅</b><b class='flag-5'>值</b>、初相位)

    什么是FFT分析的負(fù)頻率

    通常我們分析信號(hào)是一個(gè)純實(shí)數(shù)信號(hào),沒有虛部。經(jīng)典的例子當(dāng)然是用正弦波。當(dāng)我們用傅立葉變換分析,通常是F
    的頭像 發(fā)表于 05-05 10:02 ?1956次閱讀
    什么是<b class='flag-5'>FFT</b><b class='flag-5'>分析</b>的負(fù)<b class='flag-5'>頻率</b>