STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)

摘要:
FFT也叫快速傅里叶变换,是离散时间傅里叶变换的一种实现手段,变换的本质还是离散时间傅里叶变换。傅里叶变换可以将信号从时域展开到频域,通过FFT变换即可实现对信号基波和谐波分量的计算。STM32F4进行FFT如果不熟悉傅里叶变换,也无关紧要,你只要知道FFT变换可以得到信号在各个频率上的分量,以STM32F407VGx为例,我们可以使用ST提供的DSP库快速实现FFT变换。

注: 本篇内容意在使不理解FFT变换的读者也可以通过使用FFT来计算总谐波失真

FFT变换

根据总谐波失真的定义:

[THD = frac{sqrt{sum_{n=0}^{infty}{G_{n}^{2}}}}{G_0} (G_0为基波,G_n 为高次谐波) ]

可知,要计算THD需要知道基波分量和各个谐波分量的大小。

​ FFT也叫快速傅里叶变换,是离散时间傅里叶变换的一种实现手段,变换的本质还是离散时间傅里叶变换(DTFT)。傅里叶变换可以将信号从时域展开到频域,通过FFT变换即可实现对信号基波和谐波分量的计算。

STM32F4进行FFT

​ 如果不熟悉傅里叶变换,也无关紧要,你只要知道FFT变换可以得到信号在各个频率上的分量,以STM32F407VGx为例,我们可以使用ST提供的DSP库快速实现FFT变换。

​ 这里使用cube MX生成一个简单的工程作为模板,首先加入一些使用DSP库所需要的宏定义:

,ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第1张

然后,进入CubeMX的安装目录,找到DSP库下的几个文件

首先lib文件:

​ arm_cortexM4lf_math.lib

cortexM4 是指 arm的cortexM4内核,后面的l 是指芯片使用小端存放,f是浮点运算,STM32F4 默认是小端存放所以使用这个库文件

位置C:UsersUsernameSTM32CubeRepositorySTM32Cube_FW_F4_V1.25.1DriversCMSISLibARM 下、

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第2张

然后是头文件

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第3张

位置在

C:UsersUsernameSTM32CubeRepositorySTM32Cube_FW_F4_V1.25.1DriversCMSISDSPInclude

将这三个文件加入工程中

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第4张

注意:

如果是和我一样通过CubeMX生成的工程,且在code Generator中选择了Copy all library into the floder 如图

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第5张

则可以在工程文件夹下找到所需要的的文件,文件目录结构与cubeMX下的路径相同

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第6张

如果觉得上述操作过于麻烦,

可以使用cubeMX自带的例程模板,在此模板的基础上进行改进

DSP库的Example 位于:安装目录STM32CubeRepositorySTM32Cube_FW_F4_V1.25.1DriversCMSISDSPExamples

有ARM和GCC两个版本,这里以ARM为例,

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第7张

STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)第8张

不过此工程并未未添加宏定义,且使用的cortexM0内核,需要做一定的修改。个人不推荐使用此文件构建工程,这个工程更适合与用来熟悉函数的用法和功能。

然后在已经配置好的工程中编写代码,测试一下

首先引入头文件,然后定义一些用到的量

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "arm_math.h"
#include "arm_const_structs.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define Half_FFT_LENGTH	64
#define FFT_LENGTH      128				// FFT长度,默认是1024点FFT


uint16_t ADC_Value[FFT_LENGTH]; 		// ADC转换结果
float fft_inputbuf[FFT_LENGTH*2];		// FFT输入数组
float fft_outputbuf[FFT_LENGTH];		// FFT输出数组
/* USER CODE END PTD */

然后编写FFT变换的函数

void FFT(void)
{
	int i = 0;
	
	for(i=0;i < FFT_LENGTH;i++)
	{
		fft_inputbuf[i*2] = ADC_Value[i];
		fft_inputbuf[2*i +1] = 0;
	}
	
	arm_cfft_f32(&arm_cfft_sR_f32_len128,fft_inputbuf,0,1); // 执行FFT变换,arm_cfft_sR_f32_len128为宏,定义旋转因子
	arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);    // 把运算结果复数求模得幅值
}

这里要说明一下

DSP库提供的fft变换,是可以同时进行正反变换的,为了兼容反变换,我们在进行FFT时,要将虚部赋值为0,即fft_inputbuf的内容应该为:ADC_Value1, 0, ADC_Value2, 0 .... 有效的值只有fft_inputbuf长度的一半,要进行的FFT也只有fft_inputbuf的一半,所以,要进行1024点的fft变换,就需要输入2048长度的数组。

如果进行的是1024点的FFT变换,则得到1024长度的结果数组,其中,由于FFT的性质,这个数组是对称的,也就是说,1024个值,中前半部分和后半部分是对称,重复的,有意义的值只有512个值,取出数组中前512个值进行谐波分析就可以得到频率分量。

总谐波失真(THD)计算

首先,我们要知道经过FFT变换后得到的数组有什么物理意义,每个数组的值代表什么,这里直接说结论

[设f_s 为采样频率,N为FFT点数(进行变换的FFT序列的长度),进行FFT变换后得数组下标为k的值代表的频率为f_k 则: ]
[f_k = frac{k}{N}*f_s ]

也就是说,如果ADC的采样频率为1024Hz 进行2048点的FFT变换,则FFT变换后数组下标为5的位置对应的频率为$$ f_5 = frac{5}{1024} *2048 = 10hz$$ 也就是说,fft_outputbuf[5] 值的大小代表信号中10hz信号强度的大小。

明白了这个道理后,再来看如何计算总谐波失真,根据公式:

[ THD = frac{sqrt{sum_{n=0}^{infty}{G_{n}^{2}}}}{G_0} (G_0为基波,G_n 为高次谐波) ]

我们需要知道基波和谐波分量的大小,就可以轻易的计算出来THD的大小

对E题来说,信号的频率是固定的,只要采样频率(f_s)固定,点数N固定就可以很方便的得到基波分量,和谐波分量的位置

可以通过定时器来产生固定频率的采样信号,由于原信号为1k,谐波分量为2k、3k、4k、5k、6k... 采样频率应该大于最高频率的3-5倍,

但,本题中我在题目中加入了波形显示,根据采样算出来的30k的采样信号在LCD上的显示效果不好,同时又为了方便计算,我的采样频率选择为102.4kHz, 通过计算可以知道,fft_outputbuf[10]的大小就是基波分量的大小,二次谐波在fft_outputbuf[20]、三次谐波在fft_ouptubuf[30]... 依次类推, 这样总谐波失真就可以很简单的计算出来了。

void THD(void)
{
	thd_basic = fft_outputbuf[10];

	u[0] = fft_outputbuf[20];
	u[1] = fft_outputbuf[30];
	u[2] = fft_outputbuf[40];
	u[3] = fft_outputbuf[50];
	u[4] = fft_outputbuf[60];

	arm_power_f32(&u[0], 4, &sum);
	arm_sqrt_f32(sum, &thd_high);

	THD = thd_high / thd_basic;

}

免责声明:文章转载自《STM32使用FFT变换计算THD(20年四川省电子设计大赛E题软件部分)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇armv8 汇编入门vue,基于element的tree组件封装下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

UOS怎么访问windows共享的文件夹

先在windows中建一个共享文件夹,此处就先忽略步骤,共享文件夹相关信息如下图: 在UOS桌面上面建一个文件夹,比如,我在这里建了一个 winshare 再在桌面右键点击鼠标,选择在终端中打开 然后再在终端中输入以下命令,期间有提示需要密码,则直接输入密码,如果有提示需要进入开发者模式,则对应的开启一下开发者模式,如果不清楚,看此链接(https...

openwrt-智能路由器hack技术(1)---"DNS劫持"

openwrt-智能路由器hack技术(1)---"DNS劫持" 1导读 PS:之前写的一个文章,现在发现结构内容排版不是太好,导致阅读体验太差,影响传播和SEO,所以现在整理拆分一下,从小处写起, 本系列介绍了两个关于智能路由器的hack技术,供大家赏玩一下。 本文提到的两个基于网络的hack技术: DNS劫持 数据抓包 基本本质上就是路由器设备的...

打造数字化软件工厂 —— 一站式 DevOps 平台全景解读

本文为 CODING 协同产品总监张路宇 在腾讯云 CIF 工程效能峰会上所做的分享。文末可前往峰会官网,观看回放并下载 PPT。 欢迎各位朋友,来到腾讯云 CIF 工程效能峰会的分论坛,我是 CODING 的产品经理路宇,很高兴能以这种方式与大家见面。在接下来的主题环节中,会由我先为大家带来 CODING DevOps 研发平台的产品理念和全景解读,我们...

使用360对app安全进行加固

在写了第一个app之后,打算上架到各个渠道看看,无意间看到了360的app加固工具 http://jiagu.360.cn/ 自己体验了一把,加固过程很傻瓜化, 加固好了之后,还要对app进行二次签名, 最终app体积略微增加了160KB 我们知道app的逆向编译,主要是针对dex进行操作, 查看了加固后的结果,发现dex体积减小了,然后多了Lib目录;猜...

Windows App开发之开发准备

操作系统及SDK 操作系统 显而易见,想要开发Windows App就得在Windows 8/8.1/10上进行,老旧的Windows XP/Vista/7已经不能满足时代的需要了。当然,在Windows App的发展过程中,其本身也有着较大的变动,为了使用新的特性,建议使用Windows 10。我在写这个教程时,Windows 10正式版并未面世,因此...

CODING 项目协同 2.0 —— 让协作有条不紊

本文为 CODING 高级产品经理王海明 在腾讯云 CIF 工程效能峰会上所做的分享。文末可前往峰会官网,观看回放并下载 PPT。 大家好,我是 CODING 高级产品经理王海明,今天与大家分享的是项目协同 2.0 的设计理念及应用场景。 研发团队现状 在一切上云的数字化时代,将诞生越来越多的软件公司和数字科技企业,传统研发管理方式和理念不能满足这些企业的...