【电赛2023H】信号分离装置
这是本人第一篇CSDN博客,旨在分享电赛思路,方便后来的学者,也是记录自己的一段岁月。虽然CSND风评存在问题,但是需要肯定的是,这确实是新手小白最需要的、最方便的平台,曾经我的学习之路上也多有CSDN的帮助,现在也希望同样对新手们能起到一点帮助。之所以第一篇选择2023H题,是因为我觉得这最能体现STM32F407数字信号处理特性,并且最适合入门的一道题目。一个非常经典的信号处理,对基础的算法进
作者:SHR-sky
全国大学生电子设计大赛系列
第一站 :【电赛2023H】信号分离装置
文章目录
前言
这是本人第一篇CSDN博客,旨在分享电赛思路,方便后来的学者,也是记录自己的一段岁月。虽然CSND风评存在问题,但是需要肯定的是,这确实是新手小白最需要的、最方便的平台,曾经我的学习之路上也多有CSDN的帮助,现在也希望同样对新手们能起到一点帮助。
之所以第一篇选择2023H题,是因为我觉得这最能体现STM32F407数字信号处理特性,并且最适合入门的一道题目。
正文
一、题目分析
1.读题
提炼一下:将一定频率的信号混合,然后分离出来,并且这些信号的频率是离散、可列举的
题目要求如下
本文工程已上传GitHub,链接如下,欢迎star:SHR-sky/2023-H: 2023年电赛H题工程,完成所有问题。主控采用STM32,软件上采用DFT与FFT算法,通过控制定时器实现精准延时,从而实现相位校准,抑制漂移 (github.com)
2. 思路
所以,我们目标有五个:
- 合成信号
- 分离不同频率正弦波信号
- 判断信号类型(waveform)
- 分离不同类型、不同频率的信号
- 控制分离后信号的相位差
读完题目,显然,采用纯模拟的方法非常不可行。在不同类型信号(三角和正弦)的分离中,模拟滤波器显然非常难以设计。过多的滤波器同样也会造成比赛过程中焊接、调试的困难。
所以,面对这些问题,自然而然地,我们会想到从频域上进行分析,我们就会采用数字系统。在频谱中,我们可以简单地得到,各个信号分量的频率,得到信号的类型。当我们分析得到混合信号的频谱信息后,我们当然可以通过这些信息,采用不同的参数、类型数字滤波器对信号进行分离。但是,数字滤波器的设计显然会非常麻烦,需要非常高阶的滤波器。
我们不妨转换一下思路。既然我们采用数字方案,我们为什么不直接采用DDS(直接数字频率合成)技术,根据频谱信息,重建出信号?甚至于,由于题目只有有限几种频率的信号,我们为什么不直接采用打表加上DAC的方法,直接产生重建波形?
当意识到这点后,我们唯一需要解决的问题就是“相位飘移”问题。如果重建信号不同源,那么由于晶振间微小的频率差异,会导致波形并非成倍数关系,会在示波器上“跑起来”。原因其实就是,频率非整数倍数,波形之间的相位差随时间在变化,表现为波形之间的相互运动,以其中一个信号为触发信源,另一个就会“飘移”。
为了解决这点,首先,可以采取FPGA驱动DAC,由于保证了相同的时钟,所以最终不会存在细微的频率差;同样,我们也可以采用多通道的DDS模块(此处非常不建议采用飞线让两块DDS共用一个晶振),使得输出信号同源,这里推荐AD9959模块,使用方法详见本人博客;然而,第二种方法无法产生三角波,根据芯片手册,STM32F07的DAC速率,在本题频率较低的条件下,是足够的。本博客采用方案三。
但是,方案三,实际上仍然存在波形偏移(本人尝试过FPGA方案,同样也存在这种情况,只有DDS可以完全避免),所以需要相位校正。
一点杂谈:其实在知乎上看到一种说法“电赛越来越成为一种烧钱比赛,买好的模块就可以解决问题,比赛者开始轻视‘奇技淫巧’的技术”。我觉得本题的这种解法就是一种很好的回应,只用到单片机内部的ADC和DAC,即可完成所有要求。
二、解题步骤
首先给出系统框图
1.数字正交分解——得到频率信息
首先,利用matlab制作一张正/余弦值表,用于运算和DA重建。由于数值过多,此处不放具体代码。每行都是两百个点,表达一种特定频率的波形。(后续三角波的重建也需要制表)
由于CSDN自带的Latex公式不大好看,所以此处推导过程用截图替代。
2.FFT——得到波形信息
此处一定注意,修改堆栈大小,不然FFT会爆栈,导致出现奇怪的结果
首先,要安装DSP库,这样才能使用,DSP库的安装我是按照这篇教程来的:
判断的理论依据是:三角波在奇次谐波上存在谐波分量。先对3次谐波的能量进行计算——并将其与基频功率进行比较,当达到一定比例时就认为这些频点上存在谐波失真,也就是输入是三角波。但是当被测信号C中混合的A、B两个单频信号中的一个的频率刚好是另一个信号频率的3倍时(例如A为10KHz,B为30KHz时),低频信号的3次谐波会和较高频率信号的能量混淆在一起,从而使算法是无法判断低频信号是三角波还是正弦波的。所以进一步对低频信号的五次谐波进行判断,方法与其他频点上对三次谐波的判断相同。
3.TIM.cnt——实现相位延迟校正
一种非常有效的,精准延时的方法,思路来自:2023全国大学生电子设计竞赛H题全解 [原创www.cnblogs.com/helesheng] - helesheng - 博客园
为什么要这样做呢?
4. 加法器——信号混和
作为本解法唯一的硬件,这里做一点提示。
很基础的模电知识,这里不做讲解。
三、核心代码
在main函数中描述了控制逻辑。
在实际实验中,发现利用串口屏改变模式之后,需要软重启一下。然后采用goto回到程序的入口。
extern u8 do_ad_flag1;
extern u8 do_ad_flag2;
int main()
{
again:
int cnt0 = 0;
int cnt1 = 0;
wave_type[0] = 0;
wave_type[1] = 0;
Serial_Init();
ADC_GPIO_Init(); // ADC引脚初始化。
TIM3_Config(); // 触发ADC采样频率,采样频率2MHz
ADC_Config(); // ADC 2000K采样频率,采集6000个数据,需要花费3ms
ADC_DMA_Trig( ADC1_DMA_Size ); // 开始AD采集,设置采样点数
for(int i=0; i<10000; i++);
cal_2frqs(fre);
fft_cal_2types(fre,wave_type);
diff_phi_per5_1 = 1166.666666/(fre[1]*5+10);
diff_phi_per5_0 = 1166.666666/(fre[0]*5+10);
for(int i=0; i<200; i++)
{
meDA1_Value[i] = DAC_SIN[i];
}
TIM4_Init();
DA1_Init();
//TIM4->CNT = 65535-(4438)-TIM4->CNT;
TIM6_Init();
DA2_Init();
TIM_Cmd(TIM4, ENABLE);
TIM_Cmd(TIM6, ENABLE);
while(1);
if(wave_type[0]==0)
{
for(int i=0; i<200; i++)
{
meDA1_Value[i] = DAC_SIN[(fre[0])*200+i];
}
}
else
{
for(int i=0; i<200; i++)
{
meDA1_Value[i] = Tri_Wave[(fre[0])*200+i];
}
}
if(wave_type[1]==0)
{
for(int i=0; i<200; i++)
{
meDA2_Value[i] = DAC_SIN[(fre[1])*200+i];
}
}
else
{
for(int i=0; i<200; i++)
{
meDA2_Value[i] = Tri_Wave[(fre[1])*200+i];
}
}
TIM4_Init();
DA1_Init();
TIM6_Init();
DA2_Init();
TIM_Cmd(TIM4, ENABLE);
TIM_Cmd(TIM6, ENABLE);
while (1)
{
if(mode_flag==0)
{
do_ad_flag2 = 0;
while(do_ad_flag2==0);
ADC_DMA_Trig( ADC1_DMA_Size );
get_pos_angle();
delayTime1 = (8400.0*pos_angle_1 / (3.1415926*((double)fre[1]+ 2.0))+0.5);
TIM6->CNT = 65535 - (delayTime1-TIM6->CNT);
do_ad_flag1 = 0;
while(do_ad_flag1==0);
ADC_DMA_Trig( ADC1_DMA_Size );
get_pos_angle();
delayTime0 = (8400.0*pos_angle_0 / (3.1415926*((double)fre[0]+ 2.0))+0.5);
TIM4->CNT = 65535 - (delayTime0-TIM4->CNT);
}
else
{
int t= (double)change_phi/360.0 * (1000.0/(fre[1]*2.0+10.0))*29.71;
if(change_phi!=0)
{
TIM4->CNT = 65535-(t)-TIM4->CNT;
change_phi = 0;
}
}
if(flag == 1)
{
NVIC_SystemReset();
for(int i=0; i<=10000; i++);
NVIC_SystemReset();
wave_type[0] = 0;
wave_type[1] = 0;
flag = 0;
change_phi = 0;
goto again;
}
}
}
四、注意事项
- FFT需要修改堆栈大小
- DSP库需要移植,并且选择 Single Precison
- 定时器使用前查询手册,确定是32位还是64位
总结
一个非常经典的信号处理,对基础的算法进行考察的题目。在题目中,硬件上只需要加法器(其实片内ADC采样之后,做加法,再用DAC输出也行,不过这样就有点“炫技”之意,没有必要为了“纯软件”而多花时间和浪费单片机资源),其余均为软件完成,体现了“最少资源”的特点。
完整工程可见本人仓库:GitHub - SHR-sky/2023-H: 2023年电赛H题工程,完成所有问题。主控采用STM32,软件上采用DFT与FFT算法,通过控制定时器实现精准延时,从而实现相位校准,抑制漂移
更多推荐
所有评论(0)