本項(xiàng)目基于英飛凌PSoC6 RT-Thread開發(fā)板實(shí)現(xiàn)了信號(hào)處理前端-一個(gè)信號(hào)處理的工具集。包括虛擬示波器,音頻采集分析,諧波分析,周期幅值相位分析,數(shù)字濾波,極值檢測(cè),可上位機(jī)可視化和命令行人機(jī)交互,可以方便繼續(xù)擴(kuò)展相關(guān)功能,繼續(xù)豐富工具集。視頻:https://www.bilibili.com/video/BV1PM4y147v1/代碼倉(cāng)庫(kù):https://gitee.com/qinyunti/infineon-psoc62.git 二.移植DSP算法庫(kù)
2.1添加代碼git clone https://github.com/ARM-software/CMSIS_5.gitCMSIS_5CMSISDSP下是相關(guān)文件,Source下是源碼將DSP文件夾復(fù)制到自己的工程目錄中,只保留Include,PrivateInclude,Source三個(gè)文件夾Source下的每個(gè)子文件夾都是一類算法,里面的每個(gè)c都對(duì)應(yīng)一個(gè)計(jì)算函數(shù),并且有一個(gè)總文件包括其中所有的單個(gè).c,比如BasicMathFunctions.c中刪除這些總的.c,避免編譯重復(fù)刪除以下文件和所有的非.c和.h文件
1BasicMathFunctions:BasicMathFunctions.c,BasicMathFunctionsF16.c 2BayesFunctions:BayesFunctions.c,BayesFunctionsF16.c 3CommonTables:CommonTables.c,CommonTablesF16.c 4ComplexMathFunctions:ComplexMathFunctions.c,ComplexMathFunctionsF16.c 5ControllerFunctions:ControllerFunctions.c 6DistanceFunctions:DistanceFunctions.c,DistanceFunctionsF16.c 7FastMathFunctions:FastMathFunctions.c,FastMathFunctionsF16.c 8FilteringFunctions:FilteringFunctions.c,FilteringFunctionsF16.c 9InterpolationFunctions:InterpolationFunctions.c,InterpolationFunctionsF16.c 10MatrixFunctions:MatrixFunctions.c,MatrixFunctionsF16.c 11QuaternionMathFunctions:QuaternionMathFunctions.c 12StatisticsFunctions:StatisticsFunctions.c,StatisticsFunctionsF16.c 13SupportFunctions:SupportFunctions.c,SupportFunctionsF16.c 14SVMFunctions:SVMFunctions.c,SVMFunctionsF16.c 15TransformFunctions:TransformFunctions.c,TransformFunctionsF16.c,arm_bitreversal2.S 工程設(shè)置添加相關(guān)頭文件包含路徑 2.2測(cè)試復(fù)制CMSIS_5CMSISDSPExamplesARMarm_fft_bin_example下的arm_fft_bin_data.c和arm_fft_bin_example_f32.c到自己的工程目錄arm_fft_bin_example_f32.c下的int32_t main(void)改為int32_t ffttest_main(void)并添加#define SEMIHOSTING以使能printf打印,我們已經(jīng)重定向?qū)崿F(xiàn)了printf打印到串口。由于 arm_cfft_f32(&varInstCfftF32, testInput_f32_10khz, ifftFlag, doBitReverse);會(huì)修改testInput_f32_10khz的內(nèi)容,所以添加一個(gè)緩存,以便能重復(fù)測(cè)試
1float32_ttesttmp_f32_10khz[2048]; 2/*ProcessthedatathroughtheCFFT/CIFFTmodule*/ 3memcpy(testtmp_f32_10khz,testInput_f32_10khz,sizeof(testInput_f32_10khz)); 4arm_cfft_f32(&varInstCfftF32,testtmp_f32_10khz,ifftFlag,doBitReverse); 5/*ProcessthedatathroughtheComplexMagnitudeModulefor 6calculatingthemagnitudeateachbin*/ 7arm_cmplx_mag_f32(testtmp_f32_10khz,testOutput,fftSize); 在自己的main函數(shù)中申明并調(diào)用int32_t ffttest_main(void);ffttest_main();編譯運(yùn)行可以看到串口打印SUCCESS說(shuō)明測(cè)試OK。將輸入輸出數(shù)據(jù)打印
1printf("SUCCESS "); 2for(inti=0;i
三.音頻采集
3.1原理圖從原理圖看到有6路模擬輸入,分別對(duì)應(yīng)P10.0~P10.5, VREF為模擬參考電壓。使用的是MAX4466的MIC,接到ADC0,如下圖所示 ?3.2配置模擬采集引腳 ?3.3代碼Adc.c
1#include"cy_pdl.h" 2#include"cyhal.h" 3#include"cybsp.h" 4#include"cy_retarget_io.h" 5#defineVPLUS_CHANNEL_0(P10_0) 6/*Conversionfactor*/ 7#defineMICRO_TO_MILLI_CONV_RATIO(1000u) 8/*Acquistiontimeinnanosecond*/ 9#defineACQUISITION_TIME_NS(116680u) 10/*ADCScandelayinmillisecond*/ 11#defineADC_SCAN_DELAY_MS(200u) 12/******************************************************************************* 13*EnumeratedTypes 14*******************************************************************************/ 15/*ADCChannelconstants*/ 16enumADC_CHANNELS 17{ 18CHANNEL_0=0, 19NUM_CHANNELS 20}adc_channel; 21/******************************************************************************* 22*GlobalVariables 23*******************************************************************************/ 24/*ADCObject*/ 25cyhal_adc_tadc_obj; 26/*ADCChannel0Object*/ 27cyhal_adc_channel_tadc_chan_0_obj; 28/*DefaultADCconfiguration*/ 29constcyhal_adc_config_tadc_config={ 30.continuous_scanning=false,//ContinuousScanningisdisabled 31.average_count=1,//Averagecountdisabled 32.vref=CYHAL_ADC_REF_VDDA,//VREFforSingleendedchannelsettoVDDA 33.vneg=CYHAL_ADC_VNEG_VSSA,//VNEGforSingleendedchannelsettoVSSA 34.resolution=12u,//12-bitresolution 35.ext_vref=NC,//Noconnection 36.bypass_pin=NC};//Noconnection 37/*Asynchronousreadcompleteflag,usedinEventHandler*/ 38staticboolasync_read_complete=true; 39#defineNUM_SCAN(1000) 40#defineNUM_CHANNELS(1) 41/*Variabletostoreresultsfrommultiplechannelsduringasynchronousread*/ 42int32_tresult_arr[NUM_CHANNELS*NUM_SCAN]={0}; 43staticvoidadc_event_handler(void*arg,cyhal_adc_event_tevent) 44{ 45if(0u!=(event&CYHAL_ADC_ASYNC_READ_COMPLETE)) 46{ 47/*Setasyncreadcompleteflagtotrue*/ 48async_read_complete=true; 49} 50} 51intadc_init(void) 52{ 53/*Variabletocapturereturnvalueoffunctions*/ 54cy_rslt_tresult; 55/*InitializeADC.TheADCblockwhichcanconnecttothechannel0inputpinisselected*/ 56result=cyhal_adc_init(&adc_obj,VPLUS_CHANNEL_0,NULL); 57if(result!=CY_RSLT_SUCCESS) 58{ 59printf("ADCinitializationfailed.Error:%ld ",(longunsignedint)result); 60CY_ASSERT(0); 61} 62/*ADCchannelconfiguration*/ 63constcyhal_adc_channel_config_tchannel_config={ 64.enable_averaging=false,//Disableaveragingforchannel 65.min_acquisition_ns=ACQUISITION_TIME_NS,//Minimumacquisitiontimesetto1us 66.enabled=true};//SamplethischannelwhenADCperformsascan 67/*Initializeachannel0andconfigureittoscanthechannel0inputpininsingleendedmode.*/ 68result=cyhal_adc_channel_init_diff(&adc_chan_0_obj,&adc_obj,VPLUS_CHANNEL_0, 69CYHAL_ADC_VNEG,&channel_config); 70if(result!=CY_RSLT_SUCCESS) 71{ 72printf("ADCfirstchannelinitializationfailed.Error:%ld ",(longunsignedint)result); 73CY_ASSERT(0); 74} 75/*Registeracallbacktohandleasynchronousreadcompletion*/ 76cyhal_adc_register_callback(&adc_obj,&adc_event_handler,result_arr); 77/*Subscribetotheasyncreadcompleteeventtoprocesstheresults*/ 78cyhal_adc_enable_event(&adc_obj,CYHAL_ADC_ASYNC_READ_COMPLETE,CYHAL_ISR_PRIORITY_DEFAULT,true); 79printf("ADCisconfiguredinmultichannelconfiguration. "); 80printf("Channel0isconfiguredinsingleendedmode,connectedtothe "); 81printf("channel0inputpin.Provideinputvoltageatthechannel0inputpin "); 82return0; 83} 84intadc_samp(void) 85{ 86/*Variabletocapturereturnvalueoffunctions*/ 87cy_rslt_tresult; 88/*VariabletostoreADCconversionresultfromchannel0*/ 89int32_tadc_result_0=0; 90/*Clearasyncreadcompleteflag*/ 91async_read_complete=false; 92/*Initiateanasynchronousreadoperation.Theeventhandlerwillbecalled 93*whenitiscomplete.*/ 94memset(result_arr,0,sizeof(result_arr)); 95cyhal_gpio_write_internal(CYBSP_USER_LED,true); 96result=cyhal_adc_read_async_uv(&adc_obj,NUM_SCAN,result_arr); 97if(result!=CY_RSLT_SUCCESS) 98{ 99printf("ADCasyncreadfailed.Error:%ld ",(longunsignedint)result); 100CY_ASSERT(0); 101} 102while(async_read_complete==false); 103cyhal_gpio_write_internal(CYBSP_USER_LED,false); 104/* 105*Readdatafromresultlist,inputvoltageintheresultlistisin 106*microvolts.Convertitmillivoltsandprintinputvoltage 107* 108*/ 109for(inti=0;i
Adc.h
1#ifndefADC_H 2#defineADC_H 3intadc_init(void); 4intadc_samp(void); 5#endif
Main.c調(diào)用adc_init();adc_samp(); 3.4時(shí)鐘源時(shí)鐘源是100Mhz,12分頻=8.33M,滿足1.8MHz~18MHz之間的要求默認(rèn)是按照8M配置
?3.5采樣時(shí)間采樣前后翻轉(zhuǎn)LED用示波器測(cè)量時(shí)間
1intadc_samp(void) 2{ 3/*Variabletocapturereturnvalueoffunctions*/ 4cy_rslt_tresult; 5/*VariabletostoreADCconversionresultfromchannel0*/ 6int32_tadc_result_0=0; 7/*Clearasyncreadcompleteflag*/ 8async_read_complete=false; 9/*Initiateanasynchronousreadoperation.Theeventhandlerwillbecalled 10*whenitiscomplete.*/ 11memset(result_arr,0,sizeof(result_arr)); 12cyhal_gpio_write_internal(CYBSP_USER_LED,true); 13result=cyhal_adc_read_async_uv(&adc_obj,NUM_SCAN,result_arr); 14if(result!=CY_RSLT_SUCCESS) 15{ 16printf("ADCasyncreadfailed.Error:%ld ",(longunsignedint)result); 17CY_ASSERT(0); 18} 19while(async_read_complete==false); 20cyhal_gpio_write_internal(CYBSP_USER_LED,false); 21/* 22*Readdatafromresultlist,inputvoltageintheresultlistisin 23*microvolts.Convertitmillivoltsandprintinputvoltage 24* 25*/ 26for(inti=0;i
采樣1000次,分別設(shè)置采樣時(shí)間為2uS和1uS對(duì)比。#define ACQUISITION_TIME_NS (2000u)10.28mS
#define ACQUISITION_TIME_NS (1000u)9.32mS
10.28-9.32=0.96mS 1000次約1mS,1次剛好是1uS。而1000次除去采樣時(shí)間其他時(shí)間為8.32mS,即一次8.32uS。因?yàn)榍懊嬖O(shè)置了時(shí)鐘為8.33MHz, 從前面時(shí)序一節(jié)可以看到,除去采樣時(shí)間,其他轉(zhuǎn)換時(shí)間等需要14個(gè)CLK,所以需要14/8.33uS=1.7uS. 剩余的8.32-1.7為數(shù)據(jù)搬運(yùn),軟件處理等時(shí)間。 3.6 采樣值正確性1.545V和示波器采集為1.54V差不多是正確的,這里沒(méi)有高精度的萬(wàn)用表就不對(duì)測(cè)試精度了,只測(cè)試了正確性。
3.7音頻采集一次采集1000次然后串口打印,使用SerialStudio可視化顯示
1intadc_samp(void) 2{ 3/*Variabletocapturereturnvalueoffunctions*/ 4cy_rslt_tresult; 5/*VariabletostoreADCconversionresultfromchannel0*/ 6int32_tadc_result_0=0; 7/*Clearasyncreadcompleteflag*/ 8async_read_complete=false; 9/*Initiateanasynchronousreadoperation.Theeventhandlerwillbecalled 10*whenitiscomplete.*/ 11memset(result_arr,0,sizeof(result_arr)); 12cyhal_gpio_write_internal(CYBSP_USER_LED,true); 13result=cyhal_adc_read_async_uv(&adc_obj,NUM_SCAN,result_arr); 14if(result!=CY_RSLT_SUCCESS) 15{ 16printf("ADCasyncreadfailed.Error:%ld ",(longunsignedint)result); 17CY_ASSERT(0); 18} 19while(async_read_complete==false); 20cyhal_gpio_write_internal(CYBSP_USER_LED,false); 21/* 22*Readdatafromresultlist,inputvoltageintheresultlistisin 23*microvolts.Convertitmillivoltsandprintinputvoltage 24* 25*/ 26for(inti=0;i
四.信號(hào)處理前端
4.1 電能質(zhì)量,諧波分析4.1.1添加命令行在電能檢測(cè)應(yīng)用中,電能質(zhì)量一項(xiàng)分析即諧波分析,諧波分量大,說(shuō)明電能質(zhì)量不好,基于本板信號(hào)處理前端也實(shí)現(xiàn)了該功能。shell_fun.h中
1voidFftFun(void*param); shell_fun.c中
1include"fft.h" shell_cmd_list中添加一行
1{(constuint8_t*)"fft",FftFun,"fft"},/*打印幫助信息*/ 添加命令執(zhí)行函數(shù)
1voidFftFun(void*param) 2{ 3fft_main(); 4} 4.1.2添加實(shí)現(xiàn)Fft.c
1#include"arm_math.h" 2#include"arm_const_structs.h" 3#include
1#ifndefFFT_H 2#defineFFT_H 3intfft_main(void); 4#endif
測(cè)試
4.2 周期(頻率),幅值,相位分析4.2.1 原理FFT變換結(jié)果,幅值最大的橫坐標(biāo)對(duì)應(yīng)信號(hào)頻率,縱坐標(biāo)對(duì)應(yīng)幅度。幅值最大的為out[m]=val;則信號(hào)頻率f0=(Fs/N)m ,信號(hào)幅值Vpp=val/(N/2)。N為FFT的點(diǎn)數(shù),F(xiàn)s為采樣頻率。相位Pha=atan2(a, b)弧度制,其中ab是輸出虛數(shù)結(jié)果的實(shí)部和虛部。 4.2.2添加命令行shell_fun.h中
1voidFrqFun(void*param); shell_fun.c中include "frq.h"shell_cmd_list中添加一行
1{(constuint8_t*)"frt",FrqFun,"frq"}, 添加命令執(zhí)行函數(shù)
1voidFrqFun(void*param) 2{ 3Frq_main(); 4}
4.2.3實(shí)現(xiàn)代碼Frq.c
1#include"arm_math.h" 2#include"arm_const_structs.h" 3#include
1#ifndefFRQ_H 2#defineFRQ_H 3intfrq_main(void); 4#endif
4.2.4測(cè)試輸入frq開始測(cè)試印如下實(shí)時(shí)采集測(cè)試此時(shí)采集的是音頻背景聲,噪聲很小,所以頻率為0
4.3數(shù)字濾波信號(hào)前端4.3.1原理CMSIS-DSP提供直接I型IIR庫(kù)支持Q7,Q15,Q31和浮點(diǎn)四種數(shù)據(jù)類型。其中Q15和Q31提供了快速版本。直接I型IIR濾波器是基于二階Biquad級(jí)聯(lián)的方式來(lái)實(shí)現(xiàn)的。每個(gè)Biquad由一個(gè)二階的濾波器組成:y[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2] + a1 y[n-1] + a2 * y[n-2]直接I型算法每個(gè)階段需要5個(gè)系數(shù)和4個(gè)狀態(tài)變量。y[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2] - a1 y[n-1] - a2 * y[n-2]matlab使用上面的公式實(shí)現(xiàn),在使用fdatool工具箱生成的a系數(shù)需要取反才能用于直接I型IIR濾波器的函數(shù)中。高階IIR濾波器的實(shí)現(xiàn)是采用二階Biquad級(jí)聯(lián)的方式來(lái)實(shí)現(xiàn)的。其中參數(shù)numStages就是用來(lái)做指定二階Biquad的個(gè)數(shù)。比如8階IIR濾波器就可以采用numStages=4個(gè)二階Biquad來(lái)實(shí)現(xiàn)。如果要實(shí)現(xiàn)9階IIR濾波器就需要將numStages=5,這時(shí)就需要其中一個(gè)Biquad配置成一階濾波器(也就是b2=0,a2=0)。 4.3.2添加命令行shell_fun.h中void IirFun(void* param);shell_fun.c中
1include"iir.h" shell_cmd_list中添加一行
1{(constuint8_t*)"iir",IirFun,“iir"},
添加命令執(zhí)行函數(shù)
1voidIirFun(void*param) 2{ 3Iir_main(); 4} 4.3.3實(shí)現(xiàn)代碼Iir.c
1#include"arm_math.h" 2#include"arm_const_structs.h" 3#include
1#ifndefIIR_H 2#defineIIR_H 3intiir_main(void); 4#endif
4.3.4測(cè)試輸入iir回車,查看波形見(jiàn)視頻以下可以看到濾波導(dǎo)致了滯后,黃色線有滯后
以下是實(shí)時(shí)采集濾波4.4 極大值檢測(cè)在電力等行業(yè),分析電壓極值,是一項(xiàng)重要的參數(shù)分析,可以分析電壓的波動(dòng);示波器中也有自動(dòng)測(cè)量極值的功能更。本板作為信號(hào)處理前端也實(shí)現(xiàn)了該功能。 4.4.1 算法算法來(lái)源于論文https://www.mdpi.com/1999-4893/5/4/588/htm核心代碼如下
1voidampd(int32_t*data,int32_tlen) 2{ 3introw_sum; 4for(intk=1;k
1{(constuint8_t*)"max",MaxFun,"max"},/*打印幫助信息*/ 2voidMaxFun(void*param) 3{ 4max_test(); 5} 6voidMaxFun(void*param);測(cè)試代碼如下,串口命令行輸入命令max,開始采集ADC值,并計(jì)算極值,打印到PC串口通過(guò)seraistudio可視化顯示
1intmax_test(void) 2{ 3for(inti=0;i<10;i++) 4{ 5memset(p_data,0,sizeof(p_data)); 6//adc_samp(sim_data_buffer,1000); 7sim_data(); 8ampd(sim_data_buffer,sizeof(sim_data_buffer)/sizeof(sim_data_buffer[0])); 9for(intk=0;k<sizeof(sim_data_buffer)/sizeof(sim_data_buffer[0]);k++) 10{ 11if(p_data[k]==max_window_length) 12{ 13/*極大值*/ 14printf("/*%ld,%ld*/ ",sim_data_buffer[k],sim_data_buffer[k]); 15} 16else 17{ 18printf("/*%ld,%d*/ ",sim_data_buffer[k],0); 19} 20cyhal_system_delay_ms(10); 21} 22} 23return0; 24}
4.4.3 測(cè)試效果如下IN是原始數(shù)據(jù),MAX是檢測(cè)到的極大值,如果檢測(cè)極小值將原始數(shù)據(jù)取反即可。
檢測(cè)語(yǔ)音,效果如下 ?五.總結(jié)
得益于開發(fā)板出色的處理性能,和外設(shè)性能,以及官方可視化的代碼配置工具,可以方便的搭建開發(fā)環(huán)境,實(shí)現(xiàn)外設(shè)采集信號(hào)比如ADC,移植DSP庫(kù),實(shí)現(xiàn)各種算法。本Demo實(shí)現(xiàn)了諧波分析,周期幅值相位分析,數(shù)字濾波,極大值檢測(cè)等功能,是一個(gè)小的工具集,還可以繼續(xù)擴(kuò)展,設(shè)計(jì)了人機(jī)交互命令行,方便實(shí)用和測(cè)試,具備一定實(shí)用價(jià)值。
原文:https://club.rt-thread.org/ask/article/889e7c861bc93340.html———————End———————
點(diǎn)擊閱讀原文進(jìn)入官網(wǎng)
?
?
原文標(biāo)題:基于 Infineon PSoC?62開發(fā)板的信號(hào)處理前端虛擬示波器-工具集
文章出處:【微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
RT-Thread
+關(guān)注
關(guān)注
31文章
1261瀏覽量
39840
原文標(biāo)題:基于 Infineon PSoC?62開發(fā)板的信號(hào)處理前端虛擬示波器-工具集
文章出處:【微信號(hào):RTThread,微信公眾號(hào):RTThread物聯(lián)網(wǎng)操作系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論