开源GD32F103数字信号处理和机器学习算法

[复制链接]
3913|40
 楼主| zeshoufx 发表于 2023-1-3 19:24 | 显示全部楼层 |阅读模式
GD32F103单片机开源测试基于ARM CMSIS-DSPCMSIS-NN,其中ARM CMSIS-DSP包含了:电机变换(克拉克变换、帕克变换)、卷积、离散余弦变换、傅里叶变换、滤波、高斯朴素贝叶斯估计、插值、矩阵运算、PID、支持向量机及排序算法(双调排序(Bitonic sort)、冒泡排序(Bubble sort)、堆排序(Heap sort)、插入排序(Insertion sort)、快速排序(Quick sort)、选择排序(Selection sort)六种排序算法)。
其中CMSIS-NN及自己编写的机器学习和神经网络包含了:卡尔曼滤波自适应滤波蚁群优化、卷积神经网络、遗传算法、强化学习、线性回归 归纳学习、循环神经网络

开源地址:        1、神经网络机器学习:https://gitee.com/zhang_en/expand.git
2、数字信号处理:https://gitee.com/zhang_en/arm-cmsis-dsp-test.git

测试板子:GD32F103VKT6
file:///C:/Users/zes/AppData/Local/Temp/ksohtml9352/wps1.png
1231163b4106f945a8.png
 楼主| zeshoufx 发表于 2023-1-3 19:25 | 显示全部楼层
# ARM CMSIS-DSP测试
#### 介绍
ARM DSP基本就完了,包含了:
        电机变换(克拉克变换、帕克变换)、卷积、
离散余弦变换、傅里叶变换、滤波、高斯朴素贝叶斯估计、
插值、矩阵运算、PID、支持向量机
1.  克拉克变换:在三相电系统里,经常使用坐标变换,实现三相变两相、两相变三相,测试采用正弦函数模拟三相电,
幅值为1,频率为50Hz,相位差互差120度,采样频率为6.4kHz,调用函数arm_sin_f32即可,由于三相电瞬时电流代数和为0
只用给出AB两相即可,克拉克变换函数arm_clarke_f32
  1. float32_t ia[128]={0.};                //输入A相电流
  2. float32_t ib[128]={0.};                //输入B相电流

  3. float32_t ia1[128]={0.};        //输出阿法轴电流
  4. float32_t ib1[128]={0.};        //输出贝塔轴电流

  5. void dsp_test(void)
  6. {
  7.         u8 i=0;
  8.        
  9.         for(i=0;i<128;i++)
  10.         {
  11.                 ia[i]=arm_sin_f32(100*PI*i/6400);
  12.                 ib[i]=arm_sin_f32(100*PI*i/6400+PI*2/3);
  13.         }
  14.        
  15.         for(i=0;i<128;i++)
  16.         {
  17.                 arm_clarke_f32(ia[i],ib[i],&ia1[i],&ib1[i]);
  18.         }
  19.        
  20.         for(i=0;i<128;i++)
  21.         {
  22.                 printf("%f        %f        %f        %f\r\n",ia[i],ib[i],ia1[i],ib1[i]);
  23.         }
  24. }
1232363b410ba75995.png

 楼主| zeshoufx 发表于 2023-1-3 19:26 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:25
# ARM CMSIS-DSP测试 #### 介绍ARM DSP基本就完了,包含了:        电机变换(克拉克变换、帕克变换)、卷积、离 ...

2.  卷积:卷积在数字信号处理算是一个重点内容,在各个变换里基本都讨论到卷积。卷积函数arm_conv_f32。测试采用
一个频率为50Hz的正弦波与一个长度为64的矩形窗函数进行卷积。
  1. float32_t data[64]={0.};                //输入序列1
  2. float32_t data1[32]={0.};                //输入序列2
  3. float32_t data2[95]={0.};        //输出序列

  4. void dsp_test(void)
  5. {
  6.         u8 i=0;
  7.        
  8.         printf("***************\r\n");
  9.         for(i=0;i<64;i++)
  10.         {
  11.                 data[i]=arm_sin_f32(100*PI*i/6400);
  12.                
  13.         }
  14.        
  15.         for(i=0;i<64;i++)
  16.         {
  17.                 printf("%f\r\n",data[i]);
  18.         }
  19.        
  20.         printf("***************\r\n");
  21.         for(i=0;i<32;i++)
  22.         {
  23.                 data1[i]=1;
  24.         }
  25.        
  26.         for(i=0;i<32;i++)
  27.         {
  28.                 printf("%f\r\n",data1[i]);
  29.         }
  30.        
  31.         arm_conv_f32(data,64,data1,32,data2);
  32.         printf("***************\r\n");
  33.         for(i=0;i<95;i++)
  34.         {
  35.                 printf("%f\r\n",data2[i]);
  36.         }
  37. }
6640863b410eb75b43.png

 楼主| zeshoufx 发表于 2023-1-3 19:27 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:26
2.  卷积:卷积在数字信号处理算是一个重点内容,在各个变换里基本都讨论到卷积。卷积函数arm_conv_f32。 ...

3.  离散余弦变换:离散余弦变换在图像处理中比较常用,主要是图像压缩邻域,例如JPG格式,图像清晰度与原图差不多,
但占用的存储空间却比原图少了很多。离散余弦变换初始化函数arm_dct4_init_f32,离散余弦变换函数arm_dct4_f32。测试
采用对输入序列为1.5+arm_sin_f32(100*PI*i/6400)进行离散余弦变换。
  1. arm_dct4_instance_f32 S;                                //DCT 实例化结构体
  2. arm_rfft_instance_f32  S_RFFT;                        //实序列傅里叶变换实例化结构体
  3. arm_cfft_radix4_instance_f32 S_CFFT;        //复数序列傅里叶变换实例化结构体
  4. float32_t normalize=0.125;                                //归一化因子

  5. float32_t pInlineBuffer[128];                        //输入输出
  6. float32_t pState[128];                                        //state缓存
  7. float32_t data[128]={0.f};





  8. void dsp_test(void)
  9. {
  10.         u16 i=0;
  11.        
  12.        
  13.         for(i=0;i<128;i++)
  14.         {
  15.                 data[i]=1.5f+arm_sin_f32(100*PI*i/6400);
  16.                 printf("%f\r\n",data[i]);
  17.                 pInlineBuffer[i]=data[i];
  18.         }
  19.        
  20.        
  21.         arm_dct4_init_f32(&S,&S_RFFT,&S_CFFT,128,64,normalize);
  22.        
  23.         arm_dct4_f32(&S,pState,pInlineBuffer);
  24.        
  25.         for(i=0;i<128;i++)
  26.         {
  27.                 printf("%f\r\n",pInlineBuffer[i]);
  28.         }
  29. }


 楼主| zeshoufx 发表于 2023-1-3 19:28 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:27
3.  离散余弦变换:离散余弦变换在图像处理中比较常用,主要是图像压缩邻域,例如JPG格式,图像清晰度与 ...

4.傅里叶变换:傅里叶变换在各个领域都有运用,尤其是在频谱分析和谐波检测行业中,傅里叶变换实序列
初始化函数为arm_rfft_init_f32,实序列傅里叶变换函数为arm_rfft_f32。测试采用直流分量为1.5,基波频率
为50Hz,幅值为1,采样率为6.4KHZ,叠加幅值为0.3的3次谐波和幅值为0.5的7次谐波,通过傅里叶变换准确获得各次谐波的幅值。
  1. arm_rfft_instance_f32 S;                                //实序列傅里叶变换结构体
  2. arm_cfft_radix4_instance_f32 S_CFFT;        //傅里叶变换结果复序列结构体

  3. static float32_t pSrc[128]={0.0};           //输入
  4. static float32_t pDst[256]={0.0};                //输出
  5. static float32_t out[128]={0};                        //结果
  6. void dsp_test(void)
  7. {
  8.         u8 i=0,j=0;
  9.         for(i=0;i<128;i++)
  10.         {
  11.                 pSrc[i]=1.6f+arm_sin_f32(100*PI*i/6400)+0.3f*arm_sin_f32(300*PI*i/6400)+0.5f*arm_sin_f32(700*PI*i/6400);
  12.         }
  13.         arm_rfft_init_f32(&S,&S_CFFT,128,0,1);        //初始化
  14.         arm_rfft_f32(&S,pSrc,pDst);                                //傅里叶变换
  15.         for(j=0;j<127;j++)
  16.         {
  17.                 arm_sqrt_f32(pDst[2*j]*pDst[2*j]+pDst[2*j+1]*pDst[2*j+1],&out[j]);//获得幅值
  18.                 if(j==0)
  19.                 {
  20.                         out[j]=out[j]/128;//直流分量需要特殊处理
  21.                 }
  22.                 else
  23.                 {
  24.                         out[j]=out[j]/64;//交流分量
  25.                 }
  26.         }
  27.         for(j=0;j<64;j++)
  28.         {
  29.                 printf("%f\r\n",out[j]);
  30.         }
  31. }
7022063b411470c2d4.png
8853763b41151994b9.png
 楼主| zeshoufx 发表于 2023-1-3 19:29 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:28
4.傅里叶变换:傅里叶变换在各个领域都有运用,尤其是在频谱分析和谐波检测行业中,傅里叶变换实序列
初 ...

5.滤波:滤波在信号处理中特别重要,在模拟前端经硬件滤波后,流入ADC,采集到的数据可能还达不到直接使用
的目的,这时需要进行软件滤波。包括有限冲激响应滤波和无限冲激响应滤波,测试采用50Hz基波叠加9次谐波,
通过IIR滤波将9次谐波滤掉。
  1. //arm_biquad_cascade_df1_init_f32  parameter(初始化结构体)
  2. static arm_biquad_casd_df1_inst_f32  S;        //structure
  3. static uint8_t numStages=2;                           //nums  of 2 order filter (2阶滤波器)

  4. //5*numStages        xishu
  5. static float32_t  pCoeffs[5*2]={1,2,1,1.9184107565980049,-0.92769312589129826,         
  6.                                                                 1,2,1,1.8250960051409635,-0.83392686425555462};       
  7. static float32_t  pState[4*2];                        //4*numStages


  8. //arm_biquad_cascade_df1_f32  parameter
  9. static float32_t  pSrc[512];
  10. static float32_t  pDst[512];
  11. static uint32_t blockSize=1;

  12. void dsp_test(void)
  13. {
  14.         u16 i=0;
  15.         for(i=0;i<512;i++)
  16.         {
  17.                 pSrc[i]=1.5f*arm_sin_f32(100*PI*i/6400)+0.5f*arm_sin_f32(900*PI*i/6400);
  18.         }
  19.        
  20.         arm_biquad_cascade_df1_init_f32(&S,numStages,pCoeffs,pState);
  21.        
  22.         for(i=0;i<(512/blockSize);i++)
  23.         {
  24.                 arm_biquad_cascade_df1_f32(&S,pSrc+i*blockSize,pDst+i*blockSize,blockSize);
  25.         }
  26.        
  27.        
  28.         printf("************\r\n");
  29.         for(i=0;i<512;i++)
  30.         {
  31.                 //Scale Values:                                                
  32.                 //0.0023205923233234451                                       
  33.                 //0.0022077147786478436
  34.                 printf("%f        %f\r\n",pSrc[i],pDst[i]*0.0023205923233234451f*0.0022077147786478436f);
  35.         }
  36. }
2439063b4118291219.png
 楼主| zeshoufx 发表于 2023-1-3 19:29 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:29
5.滤波:滤波在信号处理中特别重要,在模拟前端经硬件滤波后,流入ADC,采集到的数据可能还达不到直接使 ...

6.高斯朴素贝叶斯分类器:高斯朴素贝叶斯分类器属于偏机器学习领域,通过给出符合高斯分布的均值和方差及分类,
输入待分类数据,即可将输入数据按先验数据进行分类。
  1. arm_gaussian_naive_bayes_instance_f32 S;

  2. #define SEMIHOSTING 1                        //使能
  3. #define NB_OF_CLASSES 3                        //类目
  4. #define VECTOR_DIMENSION 2                //向量维数

  5. const float32_t theta[NB_OF_CLASSES*VECTOR_DIMENSION] = {
  6.   1.4539529436590528f, 0.8722776016801852f,
  7.   -1.5267934452462473f, 0.903204577814203f,
  8.   -0.15338006360932258f, -2.9997913665803964f
  9. }; /**< 高斯分布的均值 */

  10. const float32_t sigma[NB_OF_CLASSES*VECTOR_DIMENSION] = {
  11.   1.0063470889514925f, 0.9038018246524426f,
  12.   1.0224479953244736f, 0.7768764290432544f,
  13.   1.1217662403241206f, 1.2303890106020325f
  14. }; /**< 高斯分布的方差 */

  15. const float32_t classPriors[NB_OF_CLASSES] = {
  16.   0.3333333333333333f, 0.3333333333333333f, 0.3333333333333333f
  17. }; /**< 类先验概率 */


  18. void dsp_test(void)
  19. {
  20.         /* 输入数组 */
  21.   float32_t in[2];

  22.   /* 分类器结果 */
  23.   float32_t result[NB_OF_CLASSES];
  24.   float32_t maxProba;
  25.   uint32_t index;
  26.   
  27.   S.vectorDimension = VECTOR_DIMENSION;         //向量空间维数
  28.   S.numberOfClasses = NB_OF_CLASSES;                 //不同类数目
  29.   S.theta = theta;                                                         //高斯分布均值         
  30.   S.sigma = sigma;                                                         //高斯分布方差        
  31.   S.classPriors = classPriors;                          //先验概率  
  32.   S.epsilon=4.328939296523643e-09f;                 //方差的叠加值

  33.   in[0] = 1.5f;
  34.   in[1] = 1.0f;

  35.   index = arm_gaussian_naive_bayes_predict_f32(&S, in,result);

  36.   maxProba = result[index];
  37. #if defined(SEMIHOSTING)
  38.   printf("Class = %d\n", index);
  39.   printf("Max proba = %f\n", (double)maxProba);
  40. #endif

  41.   in[0] = -1.5f;
  42.   in[1] = 1.0f;

  43.   index = arm_gaussian_naive_bayes_predict_f32(&S, in,result);

  44.   maxProba = result[index];
  45. #if defined(SEMIHOSTING)
  46.   printf("Class = %d\n", index);
  47.   printf("Max proba = %f\n", (double)maxProba);
  48. #endif

  49.   in[0] = 0.0f;
  50.   in[1] = -3.0f;

  51.   index = arm_gaussian_naive_bayes_predict_f32(&S, in,result);

  52.   maxProba = result[index];
  53. #if defined(SEMIHOSTING)
  54.   printf("Class = %d\n", index);
  55.   printf("Max proba = %f\n", (double)maxProba);
  56. #endif


  57. }


 楼主| zeshoufx 发表于 2023-1-3 19:30 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:29
6.高斯朴素贝叶斯分类器:高斯朴素贝叶斯分类器属于偏机器学习领域,通过给出符合高斯分布的均值和方差及 ...

7.插值:插值在数据分析和处理中较常用,有时数据量不够,可以通过一些插值手段,将数据进行丰富,方便分析。
常规的插值有线性插值、样条插值。测试主要针对样条插值,给出32点的正弦信号,通过插值方法将数据点拓展到
128点,分别对自然样条插值和抛物样条插值进行测试和对比。
  1. void dsp_test(void)
  2. {
  3.         u8 i=0;
  4.         float32_t data[128]={0.};
  5.         for(i=0;i<128;i++)
  6.         {
  7.                 data[i]=1.6f+arm_sin_f32(100*PI*i/6400)+0.3f*arm_sin_f32(300*PI*i/6400)+0.5f*arm_sin_f32(700*PI*i/6400);
  8.                 printf("%f\r\n",data[i]);
  9.         }
  10. }



  11. //arm_spline_init_f32  parameter
  12. static arm_spline_instance_f32  S;                                //样条插值结构体
  13. static arm_spline_type type=ARM_SPLINE_NATURAL;        //自然样条插值
  14. static float32_t  x[32];                                                //原始数据x
  15. static float32_t  y[32];                                                //原始数据y
  16. static uint32_t n=32;                                                        //原始数据个数
  17. static float32_t  coeffs[3*(32-1)];
  18. static float32_t  tempBuffer[2*(32-1)];
  19.         

  20. //arm_spline_f32   parameter
  21. static float32_t  xq[128];
  22. static float32_t  pDst[128];
  23. static uint32_t blockSize=128;

  24. #define num_tab 128/32

  25. void interp_test(u8 mode)
  26. {
  27.         if(mode)
  28.         {
  29.                 type=ARM_SPLINE_NATURAL;//自然样条插值
  30.         }
  31.         else
  32.         {
  33.                 type=ARM_SPLINE_PARABOLIC_RUNOUT;//抛物样条插值
  34.         }
  35.         
  36.         u8 i=0;
  37.         for(i=0;i<32;i++)
  38.         {
  39.                 x[i]=i*num_tab;
  40.                 y[i]=1.f+arm_sin_f32(100.f*PI*i/256.f+PI/3.f);
  41.         }
  42.         
  43.         for(i=0;i<128;i++)
  44.         {
  45.                 xq[i]=i;
  46.         }
  47.         
  48.         arm_spline_init_f32(&S,type,x,y,n,coeffs,tempBuffer);
  49.         arm_spline_f32(&S,xq,pDst,blockSize);
  50.         
  51.         printf("*****x********\r\n");
  52.         for(i=0;i<32;i++)
  53.         {
  54.                 printf("%f\r\n",x[i]);
  55.         }
  56.         printf("*****y********\r\n");
  57.         for(i=0;i<32;i++)
  58.         {
  59.                 printf("%f\r\n",y[i]);
  60.         }
  61.         
  62.         
  63.         printf("*****x1********\r\n");
  64.         for(i=0;i<128;i++)
  65.         {
  66.                 printf("%f\r\n",xq[i]);
  67.         }
  68.         
  69.         printf("*****y1********\r\n");
  70.         for(i=0;i<128;i++)
  71.         {
  72.                 printf("%f\r\n",pDst[i]);
  73.         }
  74. }
2125463b411ead0032.png

 楼主| zeshoufx 发表于 2023-1-3 19:32 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:30
7.插值:插值在数据分析和处理中较常用,有时数据量不够,可以通过一些插值手段,将数据进行丰富,方便分 ...

8.矩阵运算:矩阵运算包括矩阵加、减、乘、逆运算、转置、数乘等
  1. arm_matrix_instance_f32  S;
  2. arm_matrix_instance_f32  S1;
  3. arm_matrix_instance_f32  S2;
  4. uint16_t nRows=5;
  5. uint16_t nColumns=5;


  6. static void dsp_test1(void)
  7. {
  8.         float32_t  pData[25]={17,24,1,8,15,
  9.                                                 23,5,7,14,16,
  10.                                                 4,6,13,20,22,
  11.                                                 10,12,19,21,3,
  12.                                                 11,18,25,2,9};

  13.         float32_t  pData1[25]={3,3,3,3,3,
  14.                                                 3,3,3,3,3,
  15.                                                 3,3,3,3,3,
  16.                                                 3,3,3,3,3,
  17.                                                 3,3,3,3,3};       

  18.         float32_t  pData2[25]={0,0,0,0,0,
  19.                                                 0,0,0,0,0,
  20.                                                 0,0,0,0,0,
  21.                                                 0,0,0,0,0,
  22.                                                 0,0,0,0,0};       
  23.        
  24.         u8 i=0;
  25.         arm_mat_init_f32(&S,nRows,nColumns,pData);
  26.         arm_mat_init_f32(&S1,nRows,nColumns,pData1);
  27.         arm_mat_init_f32(&S2,nRows,nColumns,pData2);
  28.        
  29.        
  30.         printf("矩阵A=\r\n");
  31.         for(i=0;i<25;i++)
  32.         {
  33.                 printf("%f        ",S.pData[i]);
  34.                 if(i%5==4)
  35.                 {
  36.                         printf("\r\n");
  37.                 }
  38.         }
  39.        
  40.         printf("\r\n");
  41.         printf("矩阵B=\r\n");
  42.         for(i=0;i<25;i++)
  43.         {
  44.                 printf("%f        ",S1.pData[i]);
  45.                 if(i%5==4)
  46.                 {
  47.                         printf("\r\n");
  48.                 }
  49.         }
  50.        
  51.         arm_mat_add_f32(&S,&S1,&S2);
  52.         printf("\r\n");
  53.         printf("矩阵A+B=\r\n");
  54.         for(i=0;i<25;i++)
  55.         {
  56.                 printf("%f        ",S2.pData[i]);
  57.                 if(i%5==4)
  58.                 {
  59.                         printf("\r\n");
  60.                 }
  61.         }
  62.        
  63.         arm_mat_mult_f32(&S,&S1,&S2);
  64.         printf("\r\n");
  65.         printf("矩阵A*B=\r\n");
  66.         for(i=0;i<25;i++)
  67.         {
  68.                 printf("%f        ",S2.pData[i]);
  69.                 if(i%5==4)
  70.                 {
  71.                         printf("\r\n");
  72.                 }
  73.         }
  74.        
  75.         arm_mat_inverse_f32(&S,&S2);
  76.         printf("\r\n");
  77.         printf("矩阵A的逆矩阵=\r\n");
  78.         for(i=0;i<25;i++)
  79.         {
  80.                 printf("%f        ",S2.pData[i]);
  81.                 if(i%5==4)
  82.                 {
  83.                         printf("\r\n");
  84.                 }
  85.         }
  86.        
  87. }

  88. static void dsp_test2(void)
  89. {
  90.         u8 i=0;
  91.        
  92.         float32_t  pData[25]={17,24,1,8,15,
  93.                                                 23,5,7,14,16,
  94.                                                 4,6,13,20,22,
  95.                                                 10,12,19,21,3,
  96.                                                 11,18,25,2,9};

  97.         float32_t  pData1[25]={3,3,3,3,3,
  98.                                                 3,3,3,3,3,
  99.                                                 3,3,3,3,3,
  100.                                                 3,3,3,3,3,
  101.                                                 3,3,3,3,3};       

  102.         float32_t  pData2[25]={0,0,0,0,0,
  103.                                                 0,0,0,0,0,
  104.                                                 0,0,0,0,0,
  105.                                                 0,0,0,0,0,
  106.                                                 0,0,0,0,0};       
  107.        
  108.         arm_mat_init_f32(&S,nRows,nColumns,pData);
  109.         arm_mat_init_f32(&S1,nRows,nColumns,pData1);
  110.         arm_mat_init_f32(&S2,nRows,nColumns,pData2);
  111.        
  112.         arm_mat_scale_f32(&S,0.1f,&S2);
  113.         printf("\r\n");
  114.         printf("矩阵A*0.1=\r\n");
  115.         for(i=0;i<25;i++)
  116.         {
  117.                 printf("%f        ",S2.pData[i]);
  118.                 if(i%5==4)
  119.                 {
  120.                         printf("\r\n");
  121.                 }
  122.         }
  123.        
  124.        
  125.         arm_mat_sub_f32(&S,&S1,&S2);
  126.         printf("\r\n");
  127.         printf("矩阵A-B=\r\n");
  128.         for(i=0;i<25;i++)
  129.         {
  130.                 printf("%f        ",S2.pData[i]);
  131.                 if(i%5==4)
  132.                 {
  133.                         printf("\r\n");
  134.                 }
  135.         }
  136.        
  137.        
  138.         arm_mat_trans_f32(&S,&S2);
  139.         printf("\r\n");
  140.         printf("矩阵A的转置=\r\n");
  141.         for(i=0;i<25;i++)
  142.         {
  143.                 printf("%f        ",S2.pData[i]);
  144.                 if(i%5==4)
  145.                 {
  146.                         printf("\r\n");
  147.                 }
  148.         }
  149. }

  150. void dsp_test(void)
  151. {
  152.         dsp_test1();
  153.         dsp_test2();
  154. }
490063b412468f589.png

6592663b412559c96d.png

 楼主| zeshoufx 发表于 2023-1-3 19:33 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:32
8.矩阵运算:矩阵运算包括矩阵加、减、乘、逆运算、转置、数乘等

9.PID控制:PID控制在工业领域较为常用,尤其是自动化控制。PID初始化函数arm_pid_init_f32PID控制函数为
arm_pid_f32,测试采用DAC输出连接到ADC输入,PID控制调节DAC输入参数,让ADC采集结果稳定输出在2678
  1. arm_pid_instance_f32 S;                //定义PID结构体
  2. float ref=2678./4095*3.3;        //ADC参考目标值:2678

  3. void ad_da_init(void)
  4. {
  5.         //时钟配置
  6.         rcu_periph_clock_enable(RCU_GPIOA);
  7.         rcu_periph_clock_enable(RCU_AF);
  8.         rcu_periph_clock_enable(RCU_ADC0);
  9.         rcu_periph_clock_enable(RCU_DAC);
  10.        
  11.         rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);
  12.        
  13.         //接口配置
  14.         gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4);
  15.         gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
  16.        
  17.         //ADC输入配置
  18.         adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);
  19.         adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
  20.         adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);
  21.         adc_regular_channel_config(ADC0,0,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);
  22.         adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,DISABLE);
  23.        
  24.         adc_enable(ADC0);
  25.         delay_ms(1);
  26.         adc_calibration_enable(ADC0);
  27.        
  28.         //DAC输出配置
  29.         dac_trigger_source_config(DAC0,DAC_TRIGGER_SOFTWARE);
  30.         dac_trigger_enable(DAC0);
  31.         dac_wave_mode_config(DAC0,DAC_WAVE_DISABLE);
  32.         dac_output_buffer_enable(DAC0);
  33.        
  34.         dac_enable(DAC0);
  35.        
  36.         //PID参数初始化
  37.         S.Kd=0;
  38.         S.Ki=16;
  39.         S.Kp=100;

  40.         arm_pid_init_f32(&S,1);
  41. }



  42. volatile float adc_get=0.;

  43. void dsp_test(void)
  44. {
  45.          
  46.         float32_t pid_num=0.;
  47.        
  48.         pid_num=arm_pid_f32(&S,ref-adc_get);        //PID处理,输入为误差信号

  49.         if(pid_num>=4095)
  50.         {
  51.                 pid_num=4095;
  52.         }
  53.     dac_data_set(DAC0, DAC_ALIGN_12B_R, (u16)pid_num);
  54.       
  55.     dac_software_trigger_enable(DAC0);
  56.        
  57.         adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);
  58.         if(adc_flag_get(ADC0,ADC_FLAG_EOC))
  59.         {
  60.                 adc_flag_clear(ADC0,ADC_FLAG_EOC);
  61.                 adc_get = adc_regular_data_read(ADC0)/4095.*3.3;
  62.         }
  63.        
  64.         printf("%f        %d        %d\r\n",adc_get,(u16)pid_num,adc_regular_data_read(ADC0));
  65. }
6103963b41284d73c0.png

 楼主| zeshoufx 发表于 2023-1-3 19:34 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:33
9.PID控制:PID控制在工业领域较为常用,尤其是自动化控制。PID初始化函数arm_pid_init_f32,PID控制函数 ...

10。支持向量机分类器:支持向量机与贝叶斯分类器同属于机器学习领域,支持向量机分类器有线性和非线性,
对类A和类B进行标识,输入数据AB,通过分类器计算结果,对输入数据进行分类,因为例程提供的是线性的SVM分类器,
截距为-1.6617
  1. #define SEMIHOSTING 1                                //使能打印


  2. //支持向量机实例化结构体,所有参数可以通过python生成
  3. arm_svm_polynomial_instance_f32 params;


  4. //通过使用scikit-learn包和一些随机输入数据对SVM分类器进行训练生成的参数
  5. #define NB_SUPPORT_VECTORS 11  //向量个数


  6. //向量空间的维数
  7. #define VECTOR_DIMENSION 2

  8. const float32_t dualCoefficients[NB_SUPPORT_VECTORS]={-0.01628988f, -0.0971605f,
  9.   -0.02707579f,  0.0249406f,   0.00223095f,  0.04117345f,
  10.   0.0262687f,   0.00800358f,  0.00581823f,  0.02346904f,  0.00862162f}; /* Dual coefficients */

  11. const float32_t supportVectors[NB_SUPPORT_VECTORS*VECTOR_DIMENSION]={ 1.2510991f,   0.47782799f,
  12. -0.32711859f, -1.49880648f, -0.08905047f,  1.31907242f,
  13.   1.14059333f,  2.63443767f, -2.62561524f,  1.02120701f,
  14. -1.2361353f,  -2.53145187f,
  15.   2.28308122f, -1.58185875f,  2.73955981f,  0.35759327f,
  16.   0.56662986f,  2.79702016f,
  17. -2.51380816f,  1.29295364f, -0.56658669f, -2.81944734f}; /* Support vectors */


  18. //类A标识为“0”,类B标识为“1”
  19. const int32_t   classes[2]={0,1};


  20. void dsp_test(void)
  21. {
  22.                 /* 输入数据 */
  23.         float32_t in[VECTOR_DIMENSION];
  24.        
  25.         /* 分类器结果 */
  26.         int32_t result;
  27.        
  28.        
  29.        
  30.                 //初始化支持向量机实例化结构体
  31.         arm_svm_polynomial_init_f32(¶ms,        //实例化结构体
  32.                 NB_SUPPORT_VECTORS,                                        //向量个数
  33.                 VECTOR_DIMENSION,                                        //向量维数
  34.                 -1.661719f,                                                //截距
  35.                 dualCoefficients,                                        //双系数
  36.                 supportVectors,                                                //支持向量
  37.                 classes,                                                        //类ID标识
  38.                 3,                                                         //多项式次数
  39.                 1.100000f,                                                 //python scikit-learn包专用系数
  40.                 0.500000f                                                  //python scikit-learn包专用系数
  41.         );
  42.        
  43.        
  44.         //输入测试数据,类A
  45.         in[0] = 0.4f;
  46.         in[1] = 0.1f;
  47.        
  48.         arm_svm_polynomial_predict_f32(¶ms, in, &result);
  49.        
  50.         //根据分类标识:如果分类器结果为A,则标识必为“0”
  51.         #if defined(SEMIHOSTING)
  52.         printf("Result = %d\n", result);
  53.         #endif
  54.        
  55.         //输入测试数据,类B
  56.         in[0] = 3.0f;
  57.         in[1] = 0.0f;
  58.        
  59.         arm_svm_polynomial_predict_f32(¶ms, in, &result);
  60.        
  61.         //根据分类标识:如果分类器结果为A,则标识必为“1”
  62.         #if defined(SEMIHOSTING)
  63.         printf("Result = %d\n", result);
  64.         #endif
  65.        
  66. }
1.  采用ARM官方提供的DSP
2.  所有测试经过与MATLAB测试对比
3.  软件采用MDK 5.35DSP采用1.8.0版本,单片机采用GD32F103VKT6

 楼主| zeshoufx 发表于 2023-1-3 19:37 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:34
10。支持向量机分类器:支持向量机与贝叶斯分类器同属于机器学习领域,支持向量机分类器有线性和非线性, ...

1、自适应滤波:采用基波叠加9次谐波,滤除9次谐波,对比了不同阶数和迭代次数的结果
  1. #include "dsp_test.h"
  2. #include "systick.h"

  3. #define F_COUNT 512
  4. #define M 16

  5. /* xn--------输入的信号序列(列向量)
  6. * itr-------迭代次数,标量,默认为xn的长度,M<itr<sizeof(xn)
  7. * en--------误差序列(itr*1)列向量
  8. * dn--------所期望的响应序列(列向量)
  9. * M---------滤波器的阶数(标量)
  10. * mu--------收敛因子(步长)标量
  11. * W---------滤波器权值矩阵,大小为M*itr
  12. * yn--------实际输出序列(列向量)*/


  13. /*LMS具体算法*/
  14. //float * LMS_Filter(int itr, const float *xn, const float *dn, float mu, int length);
  15. void LMS_Filter(int itr, const float *xn, const float *dn, float mu, int length,float *yn)
  16. {
  17.     static int i = 0;
  18.     static int k = 0;
  19.     static float y = 0.0;
  20.     static float en[F_COUNT];
  21.     static float W[M][F_COUNT];
  22.     static float x[M];

  23.     /*创建一个en全零矩阵,en(k)表示第k次迭代时预期输出与实际输入的误差*/
  24.     for (i=0; i<itr; i++)
  25.     {
  26.         en[i] = 0;
  27.     }

  28.     /*创建一个W全零矩阵,每一行代表一个加权参量,每一列代表一次迭代*/
  29.     for (i=0; i<M; i++)
  30.         for (k=0; k<itr; k++)
  31.             W[i][k] = 0;

  32.     /*创建一个x全零矩阵*/
  33.     for (i=0; i<M; i++)
  34.         x[i] = 0;

  35.     /*迭代计算*/
  36.     for (k=M; k<=itr; k++)
  37.     {
  38.         /* 滤波器M个抽头的输入:从xn第k-1个值倒序取出M个样点的值放入x
  39.          * y为滤波器输出:W的第K-2列与x的积的和*/
  40.         for (i=0; i<M; i++)
  41.         {
  42.             x[i] = xn[k-i-1];
  43.             y += W[i][k-2] * x[i];
  44.         }        

  45.         en[k-1] = dn[k-1] - y;  //第k次迭代的误差

  46.         /*滤波器权值计算的迭代式*/
  47.         for (i=0; i<M; i++)
  48.         {
  49.             W[i][k-1] = W[i][k-2] + 2*mu*en[k-1]*x[i];
  50.         }

  51.         y = 0.0;
  52.     }

  53.     /*创建一个yn全无穷大矩阵,维数与xn一样*/
  54.     for (i=0; i<itr; i++)
  55.     {
  56.         yn[i] = 0.0;
  57.     }

  58.     /*求最优时滤波器的输出序列*/
  59.     for (k=M; k<=length; k++)
  60.     {
  61.         for (i=0; i<M; i++)
  62.         {
  63.             x[i] = xn[k-i-1];
  64.             y += W[i][itr-1]*x[i];
  65.         }

  66.         yn[k-1] = y;
  67.         y = 0.0;

  68.     }

  69. }


  70. float xn[512]={0.},dn[512]={0.};
  71. float yn[512]={0.};

  72. void dsp_test(void)
  73. {
  74.         u16 i=0;
  75.         for(i=0;i<512;i++)
  76.         {
  77.                 xn[i]=1.5f*arm_sin_f32(100*PI*i/6400)+0.5f*arm_sin_f32(900*PI*i/6400);
  78.         }
  79.        
  80.         for(i=0;i<512;i++)
  81.         {
  82.                 dn[i]=1.5f*arm_sin_f32(100*PI*i/6400);
  83.         }
  84.        
  85.        
  86.         LMS_Filter(128, xn, dn, 0.0008, 512,yn);
  87.        
  88.        
  89.         for(i=0;i<512;i++)
  90.         {
  91.                 printf("%f        %f        %f\r\n",xn[i],dn[i],yn[i]);
  92.         }
  93. }
20阶迭代22次结果:
6291763b4131bbf5f5.png

20阶迭代100次结果:
152263b4133290dc2.png

20阶迭代300次结果:
4343463b41346530f5.png

10100次迭代结果:
8568063b41358b6e42.png

32100次迭代结果:
7235463b4136c255d0.png

16128次迭代结果:
6826063b4137fbbc30.png



 楼主| zeshoufx 发表于 2023-1-3 19:38 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:37
1、自适应滤波:采用基波叠加9次谐波,滤除9次谐波,对比了不同阶数和迭代次数的结果20阶迭代22次结果:
...

蚁群算法:蚁群算法作为群体智能优化的代表,与全局搜索算法比较具有速度快的特点
  1. #include "dsp_test.h"



  2. /*Include头文件*/
  3. #include <stdio.h>
  4. #include <stdlib.h>

  5. /*   符号常数的定义                 */
  6. #define NOA 10 /*蚂蚁的个体数*/
  7. #define ILIMIT 50 /*循环次数*/
  8. #define Q 3 /*信息素更新的常数*/
  9. #define RHO 0.8 /*挥发常数*/
  10. #define STEPS 10 /*路程的步数*/
  11. #define EPSILON 0.15 /*确定行动选择的随机性*/
  12. #define SEED 32768 /*随机数的Seed*/


  13. /*   函数原型声明      */
  14. void printp(double pheromone[2][STEPS]) ;/*显示*/
  15. void printmSTEPS(int mSTEPS[NOA][STEPS]) ;
  16.                              /*显示蚂蚁的行动*/
  17. void walk(int cost[2][STEPS]
  18.           ,double pheromone[2][STEPS]
  19.           ,int mSTEPS[NOA][STEPS] ) ;/*使蚂蚁步行*/
  20. void update(int cost[2][STEPS]
  21.          ,double pheromone[2][STEPS]
  22.         ,int mSTEPS[NOA][STEPS] ) ;/*更新信息素*/
  23. double rand1(void) ;/*返回0~1实数的随机函数*/
  24. int rand01(void) ;/*返回0、1的随机函数*/




  25. /**************************/
  26. /*    update()函数        */
  27. /*    更新信息素          */
  28. /**************************/
  29. void update(int cost[2][STEPS]
  30.         ,double pheromone[2][STEPS]
  31.         ,int mSTEPS[NOA][STEPS] )
  32. {
  33.         int m ;/*蚂蚁个体的号码*/
  34.         int lm ;/*蚂蚁步行的距离*/
  35.         int i,j ;
  36.         double sum_lm=0 ;/*蚂蚁步行的总体距离*/
  37.        
  38.         /*信息素的挥发*/
  39.         for(i=0;i<2;++i)
  40.                 for(j=0;j<STEPS;++j)
  41.                         pheromone[i][j]*=RHO ;
  42.        
  43.         /*蚂蚁的覆盖*/
  44.         for(m=0;m<NOA;++m)
  45.         {
  46.         /*个体m的移动距离lm的计算*/
  47.         lm=0 ;
  48.         for(i=0;i<STEPS;++i)
  49.                 lm+=cost[mSTEPS[m][i]][i] ;
  50.        
  51.         /*信息素的覆盖*/
  52.         for(i=0;i<STEPS;++i)
  53.                 pheromone[mSTEPS[m][i]][i]+=Q*(1.0/lm) ;
  54.         sum_lm+=lm ;
  55.         }
  56.         /*蚂蚁步行的平均距离的输出*/
  57.         printf("%lf\n",sum_lm/NOA) ;
  58. }

  59. /**************************/
  60. /*    walk()函数          */
  61. /*    使蚂蚁步行          */
  62. /**************************/
  63. void walk(int cost[2][STEPS]
  64. ,double pheromone[2][STEPS],int mSTEPS[NOA][STEPS])
  65. {
  66.         int m ;/*蚂蚁个体的号码*/
  67.         int s ;/*蚂蚁现在所处的位置*/
  68.        
  69.         for(m=0;m<NOA;++m)
  70.         {
  71.                 for(s=0;s<STEPS;++s)
  72.                 {
  73.                         /*基于ε-greedy的行动选择*/
  74.                         if((rand1()<EPSILON)||(abs(pheromone[0][s]-pheromone[1][s])<1e-9))
  75.                         {
  76.                                 /*随机行动*/
  77.                                 mSTEPS[m][s]=rand01() ;
  78.                         }
  79.                         else
  80.                         {/*基于信息素的选择*/
  81.                                 if(pheromone[0][s]>pheromone[1][s])
  82.                                         mSTEPS[m][s]=0 ;
  83.                                 else
  84.                                         mSTEPS[m][s]=1 ;
  85.                         }
  86.                 }
  87.         }
  88. /*输出蚂蚁的行动*/
  89. printmSTEPS(mSTEPS) ;
  90. }

  91. /**************************/
  92. /*  printmSTEPS()函数      */
  93. /*   显示蚂蚁的行动       */
  94. /**************************/
  95. void printmSTEPS(int mSTEPS[NOA][STEPS])
  96. {
  97.         int i,j ;
  98.        
  99.         printf("*mSTEPS\n") ;
  100.         for(i=0;i<NOA;++i)
  101.         {
  102.                 for(j=0;j<STEPS;++j)
  103.                 printf("%d ",mSTEPS[i][j]) ;
  104.                 printf("\n") ;
  105.         }
  106. }


  107. /**************************/
  108. /*    printp()函数        */
  109. /*   显示信息素           */
  110. /**************************/
  111. void printp(double pheromone[2][STEPS])
  112. {
  113.         int i,j ;
  114.        
  115.         for(i=0;i<2;++i)
  116.         {
  117.                 for(j=0;j<STEPS;++j)
  118.                 printf("%4.2lf ",pheromone[i][j]) ;
  119.                 printf("\n") ;
  120.         }
  121. }

  122. /**************************/
  123. /*    rand1()函数         */
  124. /*返回0~1的实数的随机函数*/
  125. /**************************/
  126. double rand1(void)
  127. {
  128.         /*随机数的计算*/
  129.         return (double)rand()/RAND_MAX ;

  130. }

  131. /****************************/
  132. /*     rand01()函数         */
  133. /*返回0、1的随机函数        */
  134. /****************************/
  135. int rand01(void)
  136. {
  137.         int rnd ;
  138.        
  139.         /*去除随机数的最大值*/
  140.         while((rnd=rand())==RAND_MAX) ;
  141.         /*计算随机数*/
  142.         return (int)((double)rnd/RAND_MAX*2) ;

  143. }


  144. void dsp_test(void)
  145. {
  146.         int cost[2][STEPS]={/*各步的代价(距离)*/
  147.          {1,1,1,1,1,1,1,1,1,1},
  148.          {5,5,5,5,5,5,5,5,5,5}};
  149.         double pheromone[2][STEPS]={0} ;/*各步的信息素量*/
  150.         int mSTEPS[NOA][STEPS] ;/*蚂蚁走过的过程*/
  151.         int i;/*循环次数的控制*/
  152.        
  153.         /*随机数的初始化*/
  154.         srand(SEED) ;
  155.        
  156.         /*最优化的主体*/
  157.         for(i=0;i<ILIMIT;++i)
  158.         {
  159.                 /*信息素的状态的输出*/
  160.                 printf("%d:\n",i) ;
  161.                 printp(pheromone) ;
  162.                 /*使蚂蚁步行*/
  163.                 walk(cost,pheromone,mSTEPS) ;
  164.                 /*更新信息素*/
  165.                 update(cost,pheromone,mSTEPS) ;
  166.         }
  167.         /*信息素状态的输出*/
  168.         printf("%d:\n",i) ;
  169.         printp(pheromone) ;
  170. }


 楼主| zeshoufx 发表于 2023-1-3 19:40 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:38
蚁群算法:蚁群算法作为群体智能优化的代表,与全局搜索算法比较具有速度快的特点

...

卷积神经网络:卷积神经网络在图像处理等领域中运用广泛,在ARM官方提供的CMSIS-NN库中,就包含了卷积神经网络,
本例就是移植官方的例子,在分类器中的运用。
  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include "arm_math.h"
  4. #include "arm_nnexamples_cifar10_parameter.h"
  5. #include "arm_nnexamples_cifar10_weights.h"

  6. #include "arm_nnfunctions.h"
  7. #include "arm_nnexamples_cifar10_inputs.h"

  8. #ifdef _RTE_
  9. #include "RTE_Components.h"
  10. #ifdef RTE_Compiler_EventRecorder
  11. #include "EventRecorder.h"
  12. #endif
  13. #endif

  14. // include the input and weights

  15. static q7_t conv1_wt[CONV1_IM_CH * CONV1_KER_DIM * CONV1_KER_DIM * CONV1_OUT_CH] = CONV1_WT;
  16. static q7_t conv1_bias[CONV1_OUT_CH] = CONV1_BIAS;

  17. static q7_t conv2_wt[CONV2_IM_CH * CONV2_KER_DIM * CONV2_KER_DIM * CONV2_OUT_CH] = CONV2_WT;
  18. static q7_t conv2_bias[CONV2_OUT_CH] = CONV2_BIAS;

  19. static q7_t conv3_wt[CONV3_IM_CH * CONV3_KER_DIM * CONV3_KER_DIM * CONV3_OUT_CH] = CONV3_WT;
  20. static q7_t conv3_bias[CONV3_OUT_CH] = CONV3_BIAS;

  21. static q7_t ip1_wt[IP1_DIM * IP1_OUT] = IP1_WT;
  22. static q7_t ip1_bias[IP1_OUT] = IP1_BIAS;

  23. /* Here the image_data should be the raw uint8 type RGB image in [RGB, RGB, RGB ... RGB] format */
  24. uint8_t   image_data[CONV1_IM_CH * CONV1_IM_DIM * CONV1_IM_DIM] = IMG_DATA;
  25. q7_t      output_data[IP1_OUT];

  26. //vector buffer: max(im2col buffer,average pool buffer, fully connected buffer)
  27. q7_t      col_buffer[2 * 5 * 5 * 32 * 2];

  28. q7_t      scratch_buffer[32 * 32 * 10 * 4];




  29. void dsp_test(void)
  30. {
  31.        
  32. #ifdef RTE_Compiler_EventRecorder
  33.   EventRecorderInitialize (EventRecordAll, 1);  // initialize and start Event Recorder
  34.   #endif

  35.   printf("start execution\n");
  36.   /* start the execution */

  37.   q7_t     *img_buffer1 = scratch_buffer;
  38.   q7_t     *img_buffer2 = img_buffer1 + 32 * 32 * 32;

  39.   /* input pre-processing */
  40.   int mean_data[3] = INPUT_MEAN_SHIFT;
  41.   unsigned int scale_data[3] = INPUT_RIGHT_SHIFT;
  42.   for (int i=0;i<32*32*3; i+=3) {
  43.     img_buffer2[i] =   (q7_t)__SSAT( ((((int)image_data[i]   - mean_data[0])<<7) + (0x1<<(scale_data[0]-1)))
  44.                              >> scale_data[0], 8);
  45.     img_buffer2[i+1] = (q7_t)__SSAT( ((((int)image_data[i+1] - mean_data[1])<<7) + (0x1<<(scale_data[1]-1)))
  46.                              >> scale_data[1], 8);
  47.     img_buffer2[i+2] = (q7_t)__SSAT( ((((int)image_data[i+2] - mean_data[2])<<7) + (0x1<<(scale_data[2]-1)))
  48.                              >> scale_data[2], 8);
  49.   }
  50.   
  51.   // conv1 img_buffer2 -> img_buffer1
  52.   arm_convolve_HWC_q7_RGB(img_buffer2, CONV1_IM_DIM, CONV1_IM_CH, conv1_wt, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PADDING,
  53.                           CONV1_STRIDE, conv1_bias, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, img_buffer1, CONV1_OUT_DIM,
  54.                           (q15_t *) col_buffer, NULL);

  55.   arm_relu_q7(img_buffer1, CONV1_OUT_DIM * CONV1_OUT_DIM * CONV1_OUT_CH);

  56.   // pool1 img_buffer1 -> img_buffer2
  57.   arm_maxpool_q7_HWC(img_buffer1, CONV1_OUT_DIM, CONV1_OUT_CH, POOL1_KER_DIM,
  58.                      POOL1_PADDING, POOL1_STRIDE, POOL1_OUT_DIM, NULL, img_buffer2);

  59.   // conv2 img_buffer2 -> img_buffer1
  60.   arm_convolve_HWC_q7_fast(img_buffer2, CONV2_IM_DIM, CONV2_IM_CH, conv2_wt, CONV2_OUT_CH, CONV2_KER_DIM,
  61.                            CONV2_PADDING, CONV2_STRIDE, conv2_bias, CONV2_BIAS_LSHIFT, CONV2_OUT_RSHIFT, img_buffer1,
  62.                            CONV2_OUT_DIM, (q15_t *) col_buffer, NULL);

  63.   arm_relu_q7(img_buffer1, CONV2_OUT_DIM * CONV2_OUT_DIM * CONV2_OUT_CH);

  64.   // pool2 img_buffer1 -> img_buffer2
  65.   arm_maxpool_q7_HWC(img_buffer1, CONV2_OUT_DIM, CONV2_OUT_CH, POOL2_KER_DIM,
  66.                      POOL2_PADDING, POOL2_STRIDE, POOL2_OUT_DIM, col_buffer, img_buffer2);

  67. // conv3 img_buffer2 -> img_buffer1
  68.   arm_convolve_HWC_q7_fast(img_buffer2, CONV3_IM_DIM, CONV3_IM_CH, conv3_wt, CONV3_OUT_CH, CONV3_KER_DIM,
  69.                            CONV3_PADDING, CONV3_STRIDE, conv3_bias, CONV3_BIAS_LSHIFT, CONV3_OUT_RSHIFT, img_buffer1,
  70.                            CONV3_OUT_DIM, (q15_t *) col_buffer, NULL);

  71.   arm_relu_q7(img_buffer1, CONV3_OUT_DIM * CONV3_OUT_DIM * CONV3_OUT_CH);

  72.   // pool3 img_buffer-> img_buffer2
  73.   arm_maxpool_q7_HWC(img_buffer1, CONV3_OUT_DIM, CONV3_OUT_CH, POOL3_KER_DIM,
  74.                      POOL3_PADDING, POOL3_STRIDE, POOL3_OUT_DIM, col_buffer, img_buffer2);

  75.   arm_fully_connected_q7_opt(img_buffer2, ip1_wt, IP1_DIM, IP1_OUT, IP1_BIAS_LSHIFT, IP1_OUT_RSHIFT, ip1_bias,
  76.                              output_data, (q15_t *) img_buffer1);

  77.   arm_softmax_q7(output_data, 10, output_data);

  78.   for (int i = 0; i < 10; i++)
  79.   {
  80.       printf("%d: %d\n", i, output_data[i]);
  81.   }


  82. }


 楼主| zeshoufx 发表于 2023-1-3 19:41 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:40
卷积神经网络:卷积神经网络在图像处理等领域中运用广泛,在ARM官方提供的CMSIS-NN库中,就包含了卷积神 ...

遗传算法:遗传算法也是一种优化算法,模拟背包问题,寻求最优解
  1. /* Include头文件*/
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <limits.h>

  5. /*符号常数的定义*/
  6. #define MAXVALUE 100 /*重量和价值的最大值*/
  7. #define N 30 /*行李个数*/
  8. #define WEIGHTLIMIT (N*MAXVALUE/4) /*重量限制*/
  9. #define POOLSIZE 30 /*染色体个数*/
  10. #define LASTG 50    /*终止后代*/
  11. #define MRATE 0.01  /*突变的概率*/
  12. #define SEED 32767    /*随机数的seed*/
  13. #define YES 1   /*yes对应的整数值*/
  14. #define NO 0    /*no对应的整数值*/

  15. /*函数原型声明*/
  16. void initparcel();/*行李的初始化*/
  17. int evalfit(int gene[]) ; /*计算适应度*/
  18. void mating(int pool[POOLSIZE][N]
  19.         ,int ngpool[POOLSIZE*2][N]) ; /*交叉*/
  20. void mutation(int ngpool[POOLSIZE*2][N]) ; /*突变*/
  21. void printp(int pool[POOLSIZE][N]) ; /*输出结果*/
  22. void initpool(int pool[POOLSIZE][N]) ;
  23. /*生成初始染色体集合*/
  24. int rndn() ; /*生成n之下的随机数   */
  25. int notval(int v) ;/*真值的反转*/
  26. int selectp(int roulette[POOLSIZE],int totalfitness) ;
  27. /*选择父代*/
  28. void crossing(int m[],int p[],int c1[],int c2[]) ;
  29. /* 两个特定染色体的交叉 */
  30. void selectng(int ngpool[POOLSIZE*2][N]
  31.         ,int pool[POOLSIZE][N]) ;/*选择下一代*/

  32. /*全局变量(行李数据)*/
  33. int parcel[N][2] =
  34. {
  35.         {65,27},
  36.         {39,82},
  37.         {9,85},
  38.         {72,71},
  39.         {87,91},
  40.         {91,28},
  41.         {34,92},
  42.         {58,79},
  43.         {3,27},
  44.         {12,82},
  45.         {92,15},
  46.         {39,49},
  47.         {83,54},
  48.         {76,43},
  49.         {6,26},
  50.         {77,2},
  51.         {68,6},
  52.         {24,60},
  53.         {60,47},
  54.         {6,40},
  55.         {91,58},
  56.         {44,68},
  57.         {50,33},
  58.         {91,92},
  59.         {57,62},
  60.         {97,49},
  61.         {96,68},
  62.         {39,77},
  63.         {89,6},
  64.         {24,97}
  65. };/*行李*/



  66. /****************************/
  67. /*      initparcel()函数    */
  68. /*      行李的初始化        */
  69. /****************************/
  70. void initparcel()
  71. {
  72. //        int i=0 ;
  73. //        while((i<N) &&
  74. //                (scanf("%d %d",&parcel[i][0],&parcel[i][1])
  75. //                        !=EOF)){
  76. //                ++i ;
  77. //        }

  78.        
  79. }

  80. /************************/
  81. /*   selectng()函数     */
  82. /*   选择下一代         */
  83. /************************/
  84. void selectng(int ngpool[POOLSIZE*2][N]
  85.         ,int pool[POOLSIZE][N])
  86. {
  87.         int i,j,c ;/* 循环控制参数 */
  88.         int totalfitness=0 ;/*适应度的总计值*/
  89.         int roulette[POOLSIZE*2] ;/*存放适应度*/
  90.         int ball ;/* 球(选择位置的数值)*/
  91.         int acc=0 ;/*适应度的累积值*/
  92.        
  93.         /*循环进行选择*/
  94.         for(i=0;i<POOLSIZE;++i){
  95.                 /* 生成轮盘 */
  96.                 totalfitness=0 ;
  97.                 for(c=0;c<POOLSIZE*2;++c){
  98.                         roulette[c]=evalfit(ngpool[c]) ;
  99.                         /*计算适应度的总计值*/
  100.                         totalfitness+=roulette[c] ;
  101.                 }
  102.                 /*选择一个染色体*/
  103.                 ball=rndn(totalfitness) ;
  104.                 acc=0 ;
  105.                 for(c=0;c<POOLSIZE*2;++c){
  106.                         acc+=roulette[c] ;/*累积评价值*/
  107.                         if(acc>ball) break ;/*对应的基因*/
  108.                 }
  109.                
  110.                 /*染色体的复制*/
  111.                 for(j=0;j<N;++j){
  112.                         pool[i][j]=ngpool[c][j] ;
  113.                 }
  114.         }
  115. }

  116. /************************/
  117. /*   selectp()函数      */
  118. /*    父代的选择        */
  119. /************************/
  120. int selectp(int roulette[POOLSIZE],int totalfitness)
  121. {
  122.         int i ;/* 循环的控制变量 */
  123.         int ball ;/* 球(选择位置的数值)*/
  124.         int acc=0 ;/*评价值的累积值*/
  125.        
  126.         ball=rndn(totalfitness) ;
  127.         for(i=0;i<POOLSIZE;++i){
  128.                 acc+=roulette[i] ;/*评价值的累积*/
  129.                 if(acc>ball) break ;/*对应的基因*/
  130.         }
  131.         return i ;
  132. }


  133. /************************/
  134. /*   mating()函数       */
  135. /*        交叉          */
  136. /************************/
  137. void mating(int pool[POOLSIZE][N]
  138.         ,int ngpool[POOLSIZE*2][N])
  139. {
  140.         int i ;/* 循环的控制变量 */
  141.         int totalfitness=0 ;/*评价值的总计值*/
  142.         int roulette[POOLSIZE] ;/*存放评价值*/
  143.         int mama,papa ;/*父代的基因的号码*/
  144.        
  145.         /* 生成轮盘 */
  146.         for(i=0;i<POOLSIZE;++i){
  147.                 roulette[i]=evalfit(pool[i]) ;
  148.                 /* 计算评价值的总计值*/
  149.                 totalfitness+=roulette[i] ;
  150.         }
  151.        
  152.         /*选择和交叉的循环*/
  153.         for(i=0;i<POOLSIZE;++i){
  154.                 do{/*父代的选择*/
  155.                         mama=selectp(roulette,totalfitness) ;
  156.                         papa=selectp(roulette,totalfitness) ;
  157.                 }while(mama==papa) ;/*删除重复的*/
  158.                
  159.                 /*特定2染色体的交叉*/
  160.                 crossing(pool[mama],pool[papa]
  161.                         ,ngpool[i*2],ngpool[i*2+1])  ;  
  162.         }
  163. }


  164. /************************/
  165. /*  crossing()函数      */
  166. /* 特定2染色体的交叉    */
  167. /************************/
  168. void crossing(int m[],int p[],int c1[],int c2[])
  169. {
  170.         int j ;/* 循环控制变量 */
  171.         int cp ;/*交叉的点*/
  172.        
  173.         /*确定交叉点*/
  174.         cp =rndn(N) ;
  175.        
  176.         /*复制前半部分*/
  177.         for(j=0;j<cp;++j){
  178.                 c1[j]=m[j] ;
  179.                 c2[j]=p[j] ;
  180.         }
  181.         /*复制后半部分*/
  182.         for(;j<N;++j){
  183.                 c2[j]=m[j] ;
  184.                 c1[j]=p[j] ;
  185.         }
  186. }

  187. /************************/
  188. /*   evalfit()函数      */
  189. /*   计算评价值         */
  190. /************************/
  191. int evalfit(int g[])
  192. {
  193.         int pos ;/*指定基因位点*/
  194.         int value=0 ;/*评价值*/
  195.         int weight=0 ;/*重量*/
  196.        
  197.         /*调查各个基因位点计算重量和评价值*/
  198.         for(pos=0;pos<N;++pos){
  199.                 weight+=parcel[pos][0]*g[pos] ;
  200.                 value+=parcel[pos][1]*g[pos] ;
  201.         }
  202.         /*致死基因的处理*/
  203.         if(weight>=WEIGHTLIMIT) value=0 ;
  204.         return value;
  205.        
  206. }

  207. /***********************/
  208. /*   printp()函数      */
  209. /*   输出结果          */
  210. /***********************/
  211. void printp(int pool[POOLSIZE][N])
  212. {
  213.         int i,j ;/* 循环的控制变量 */
  214.         int fitness ;/* 评价值 */
  215.         double totalfitness=0 ;/* 评价值的总计值 */
  216.         int elite,bestfit=0 ;/*精英基因的处理用变量*/
  217.        
  218.         for(i=0;i<POOLSIZE;++i){
  219.                 for(j=0;j<N;++j)
  220.                         printf("%1d",pool[i][j]) ;
  221.                 fitness=evalfit(pool[i]) ;
  222.                 printf("\t%d\n",fitness) ;
  223.                 if(fitness>bestfit){/*精英解*/
  224.                         bestfit=fitness ;
  225.                         elite=i ;
  226.                 }
  227.                 totalfitness+=fitness ;
  228.         }
  229.         /*输出精英解的评价值*/
  230.         printf("%d\t%d \t",elite,bestfit) ;
  231.         /*输出平均评价值*/
  232.         printf("%lf\n",totalfitness/POOLSIZE) ;
  233. }


  234. /***********************/
  235. /*   initpool()函数    */
  236. /*   生成初始染色体集合*/
  237. /***********************/
  238. void initpool(int pool[POOLSIZE][N])
  239. {
  240.         int i,j ;/* 循环控制变量 */
  241.        
  242.         for(i=0;i<POOLSIZE;++i)
  243.                 for(j=0;j<N;++j)
  244.                         pool[i][j]=rndn(2) ;
  245. }


  246. /************************/
  247. /*     rndn()函数       */
  248. /*    n以下随机数的生成 */
  249. /************************/
  250. int rndn(int l)
  251. {
  252.         int rndno ;/*生成的随机数*/
  253.        
  254.         while((rndno=((double)rand()/RAND_MAX)*l)==l) ;
  255.        
  256.         return rndno;
  257. }

  258. /***********************/
  259. /*   mutation()函数    */
  260. /*   突变              */
  261. /***********************/
  262. void mutation(int ngpool[POOLSIZE*2][N])
  263. {
  264.         int i,j ;/* 循环的控制变量 */
  265.        
  266.         for(i=0;i<POOLSIZE*2;++i)
  267.                 for(j=0;j<N;++j)
  268.                         if((double)rndn(100)/100.0<=MRATE)
  269.                                 /*反转的突变*/
  270.                                 ngpool[i][j]=notval(ngpool[i][j]) ;
  271.        
  272. }

  273. /************************/
  274. /*   notval()函数       */
  275. /*   真值的反转         */
  276. /************************/
  277. int notval(int v)
  278. {
  279.         if(v==YES) return NO ;
  280.         else return YES ;
  281. }

  282. int pool[POOLSIZE][N] ; /*染色体集合*/
  283. int ngpool[POOLSIZE*2][N] ; /*下一代染色体集合*/
  284. int generation;/* 现在的代数 */

  285. void dsp_test(void)
  286. {
  287.        
  288.        
  289.         /*随机数的初始化*/
  290.         srand(SEED) ;
  291.        
  292. //        /*行李的初始化*/
  293. //        initparcel() ;
  294.        
  295.         /*生成初始染色体集合*/
  296.         initpool(pool) ;
  297.        
  298.         /*循环直至终止子代*/
  299.         for(generation=0;generation<LASTG;++generation){
  300.                 printf("%d代数\n",generation) ;
  301.                 mating(pool,ngpool) ;/*交叉*/
  302.                 mutation(ngpool) ;/*突变*/
  303.                 selectng(ngpool,pool) ;/*选择下一子代*/
  304.                 printp(pool) ;/*输出结果*/
  305.         }
  306. }


 楼主| zeshoufx 发表于 2023-1-3 19:42 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:41
遗传算法:遗传算法也是一种优化算法,模拟背包问题,寻求最优解

1、卡尔曼滤波:卡尔曼滤波在数据采集中运用广泛,在数据波动的情况下获得真实值。
  1. #include "dsp_test.h"
  2. #include "systick.h"

  3. #define Kk_calc(x,y)    (x)/(x+y)

  4. type_KalmanFilter k;

  5. float RandomNumGenerator(int base, int range)
  6. {
  7.         float k = 0.0;
  8.         float randomNum = 0.0;

  9.         k = 2 * range * 10;

  10.         randomNum = rand() % (int)k;

  11.         k = base - range + (randomNum / 10);
  12.         return k;
  13. }


  14. //Kalman初始化
  15. void Kalman_Init(type_KalmanFilter* kalmanFilter, float FirstMeaValue, float E_mea, float FirstEstValue, float E_est)
  16. {
  17.         kalmanFilter->x_est = FirstEstValue;
  18.         kalmanFilter->x_mea = FirstMeaValue;
  19.         kalmanFilter->e_est = E_est;
  20.         kalmanFilter->e_mea = E_mea;
  21.         kalmanFilter->Kk = Kk_calc(kalmanFilter->e_est, kalmanFilter->e_mea);
  22. }

  23. //Kalman更新
  24. void Kalman_Update(type_KalmanFilter* kalmanFilter, float newMeaValue)
  25. {
  26.         float temp = kalmanFilter->e_est;
  27.         kalmanFilter->x_est = kalmanFilter->x_est + kalmanFilter->Kk * (newMeaValue - kalmanFilter->x_est);
  28.         kalmanFilter->x_mea = newMeaValue;
  29.         kalmanFilter->Kk = Kk_calc(kalmanFilter->e_est, kalmanFilter->e_mea);
  30.         kalmanFilter->e_est = (1 - kalmanFilter->Kk) * temp;
  31. }

  32. void ad_da_init(void)
  33. {
  34.         //时钟配置
  35.         rcu_periph_clock_enable(RCU_GPIOA);
  36.         rcu_periph_clock_enable(RCU_AF);
  37.         rcu_periph_clock_enable(RCU_ADC0);
  38.         rcu_periph_clock_enable(RCU_DAC);
  39.        
  40.         rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);
  41.        
  42.         //接口配置
  43.         gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4);
  44.         gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
  45.        
  46.         //ADC输入配置
  47.         adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);
  48.         adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
  49.         adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);
  50.         adc_regular_channel_config(ADC0,0,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);
  51.         adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,DISABLE);
  52.        
  53.         adc_enable(ADC0);
  54.         delay_ms(1);
  55.         adc_calibration_enable(ADC0);
  56.        
  57.         //DAC输出配置
  58.         dac_trigger_source_config(DAC0,DAC_TRIGGER_SOFTWARE);
  59.         dac_trigger_enable(DAC0);
  60.         dac_wave_mode_config(DAC0,DAC_WAVE_DISABLE);
  61.         dac_output_buffer_enable(DAC0);
  62.        
  63.         dac_enable(DAC0);
  64.         dac_data_set(DAC0, DAC_ALIGN_12B_R, (u16)1024);
  65.     dac_software_trigger_enable(DAC0);
  66.        
  67.         //Kalman初始化
  68.         Kalman_Init(&k, 1024, 2, 1024, 2);
  69. }



  70. void dsp_test(void)
  71. {
  72.         u16 adc_get=0;
  73.        
  74.         adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);
  75.         if(adc_flag_get(ADC0,ADC_FLAG_EOC))
  76.         {
  77.                 adc_flag_clear(ADC0,ADC_FLAG_EOC);
  78.                 adc_get = adc_regular_data_read(ADC0);
  79.                 Kalman_Update(&k,adc_get);
  80.         }
  81.        
  82.         printf("%d        %f        %f\r\n",adc_get,k.x_mea,k.x_est);
  83. }
2036763b41485c9ff2.png

 楼主| zeshoufx 发表于 2023-1-3 19:42 | 显示全部楼层
zeshoufx 发表于 2023-1-3 19:42
1、卡尔曼滤波:卡尔曼滤波在数据采集中运用广泛,在数据波动的情况下获得真实值。
...

1、线性回归:线性回归作为最简单的机器学习
  1. #include "dsp_test.h"


  2. float data_x[12]={187.1,179.5,157.0,197.0,239.4,217.8,227.1,233.4,242.0,251.9,230.0,271.8};
  3. float data_y[12]={25.4,22.8,20.6,21.8,32.4,24.4,29.3,27.9,27.8,34.2,29.2,30.0};


  4. //求线性回归方程:Y=ax+b
  5. //dada_x数组:X;
  6. //data_y数组:Y;
  7. //length:数据个数;
  8. //a,b:返回回归系数
  9. //返回值:无
  10. void LinearRegression(        float *data_x,
  11.                                                 float *data_y,
  12.                                                 u16 length,
  13.                                                 float *a,
  14.                                                 float *b)
  15. {
  16.         u16 i=0;
  17.         float sum_x=0.,sum_y=0.;
  18.         float mean_x=0.,mean_y=0.;
  19.         float Lxy=0.,Lxx=0.;
  20.        
  21.         //分别求和
  22.         for(i=0;i<length;i++)
  23.         {
  24.                 sum_x+=data_x[i];
  25.                 sum_y+=data_y[i];
  26.         }
  27.        
  28.         //取平均
  29.         mean_x=sum_x/length;
  30.         mean_y=sum_y/length;
  31.        
  32.         //计算分母和分子
  33.         for ( i=0; i!=length; i++)
  34.         {
  35.                 Lxy += (data_x[i] - mean_x) * (data_y[i] - mean_y);
  36.                 Lxx += (data_x[i] - mean_x) * (data_x[i] - mean_x);
  37.         }
  38.        
  39.         //计算回归系数
  40.         *a=Lxy/Lxx;
  41.         *b=mean_y-(*a)*mean_x;
  42. }

  43. void dsp_test(void)
  44. {
  45.         float a=0.,b=0.;
  46.         LinearRegression(data_x,data_y,12,&a,&b);
  47.         printf("%f        %f\r\n",a,b);
  48. }
8334663b414b5f11dc.png

caigang13 发表于 2023-1-3 20:47 来自手机 | 显示全部楼层
MCU还能玩神经网络计算?
 楼主| zeshoufx 发表于 2023-1-4 08:59 | 显示全部楼层
caigang13 发表于 2023-1-3 20:47
MCU还能玩神经网络计算?

可以的,,ARM官方提供的CMSIS-NN库,就是针对cortex-M 和cortex-A CPU的,,
cauhorse 发表于 2023-1-5 13:33 | 显示全部楼层
楼主玩得很全面,佩服
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

1991

帖子

15

粉丝
快速回复 在线客服 返回列表 返回顶部