打印

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

[复制链接]
2558|40
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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

使用特权

评论回复
沙发
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
float32_t ia[128]={0.};                //输入A相电流
float32_t ib[128]={0.};                //输入B相电流

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

void dsp_test(void)
{
        u8 i=0;
       
        for(i=0;i<128;i++)
        {
                ia[i]=arm_sin_f32(100*PI*i/6400);
                ib[i]=arm_sin_f32(100*PI*i/6400+PI*2/3);
        }
       
        for(i=0;i<128;i++)
        {
                arm_clarke_f32(ia[i],ib[i],&ia1[i],&ib1[i]);
        }
       
        for(i=0;i<128;i++)
        {
                printf("%f        %f        %f        %f\r\n",ia[i],ib[i],ia1[i],ib1[i]);
        }
}

使用特权

评论回复
板凳
zeshoufx|  楼主 | 2023-1-3 19:26 | 只看该作者
zeshoufx 发表于 2023-1-3 19:25
# ARM CMSIS-DSP测试 #### 介绍ARM DSP基本就完了,包含了:        电机变换(克拉克变换、帕克变换)、卷积、离 ...

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

void dsp_test(void)
{
        u8 i=0;
       
        printf("***************\r\n");
        for(i=0;i<64;i++)
        {
                data[i]=arm_sin_f32(100*PI*i/6400);
               
        }
       
        for(i=0;i<64;i++)
        {
                printf("%f\r\n",data[i]);
        }
       
        printf("***************\r\n");
        for(i=0;i<32;i++)
        {
                data1[i]=1;
        }
       
        for(i=0;i<32;i++)
        {
                printf("%f\r\n",data1[i]);
        }
       
        arm_conv_f32(data,64,data1,32,data2);
        printf("***************\r\n");
        for(i=0;i<95;i++)
        {
                printf("%f\r\n",data2[i]);
        }
}

使用特权

评论回复
地板
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)进行离散余弦变换。
arm_dct4_instance_f32 S;                                //DCT 实例化结构体
arm_rfft_instance_f32  S_RFFT;                        //实序列傅里叶变换实例化结构体
arm_cfft_radix4_instance_f32 S_CFFT;        //复数序列傅里叶变换实例化结构体
float32_t normalize=0.125;                                //归一化因子

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





void dsp_test(void)
{
        u16 i=0;
       
       
        for(i=0;i<128;i++)
        {
                data[i]=1.5f+arm_sin_f32(100*PI*i/6400);
                printf("%f\r\n",data[i]);
                pInlineBuffer[i]=data[i];
        }
       
       
        arm_dct4_init_f32(&S,&S_RFFT,&S_CFFT,128,64,normalize);
       
        arm_dct4_f32(&S,pState,pInlineBuffer);
       
        for(i=0;i<128;i++)
        {
                printf("%f\r\n",pInlineBuffer[i]);
        }
}


使用特权

评论回复
5
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次谐波,通过傅里叶变换准确获得各次谐波的幅值。
arm_rfft_instance_f32 S;                                //实序列傅里叶变换结构体
arm_cfft_radix4_instance_f32 S_CFFT;        //傅里叶变换结果复序列结构体

static float32_t pSrc[128]={0.0};           //输入
static float32_t pDst[256]={0.0};                //输出
static float32_t out[128]={0};                        //结果
void dsp_test(void)
{
        u8 i=0,j=0;
        for(i=0;i<128;i++)
        {
                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);
        }
        arm_rfft_init_f32(&S,&S_CFFT,128,0,1);        //初始化
        arm_rfft_f32(&S,pSrc,pDst);                                //傅里叶变换
        for(j=0;j<127;j++)
        {
                arm_sqrt_f32(pDst[2*j]*pDst[2*j]+pDst[2*j+1]*pDst[2*j+1],&out[j]);//获得幅值
                if(j==0)
                {
                        out[j]=out[j]/128;//直流分量需要特殊处理
                }
                else
                {
                        out[j]=out[j]/64;//交流分量
                }
        }
        for(j=0;j<64;j++)
        {
                printf("%f\r\n",out[j]);
        }
}


使用特权

评论回复
6
zeshoufx|  楼主 | 2023-1-3 19:29 | 只看该作者
zeshoufx 发表于 2023-1-3 19:28
4.傅里叶变换:傅里叶变换在各个领域都有运用,尤其是在频谱分析和谐波检测行业中,傅里叶变换实序列
初 ...

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

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


//arm_biquad_cascade_df1_f32  parameter
static float32_t  pSrc[512];
static float32_t  pDst[512];
static uint32_t blockSize=1;

void dsp_test(void)
{
        u16 i=0;
        for(i=0;i<512;i++)
        {
                pSrc[i]=1.5f*arm_sin_f32(100*PI*i/6400)+0.5f*arm_sin_f32(900*PI*i/6400);
        }
       
        arm_biquad_cascade_df1_init_f32(&S,numStages,pCoeffs,pState);
       
        for(i=0;i<(512/blockSize);i++)
        {
                arm_biquad_cascade_df1_f32(&S,pSrc+i*blockSize,pDst+i*blockSize,blockSize);
        }
       
       
        printf("************\r\n");
        for(i=0;i<512;i++)
        {
                //Scale Values:                                                
                //0.0023205923233234451                                       
                //0.0022077147786478436
                printf("%f        %f\r\n",pSrc[i],pDst[i]*0.0023205923233234451f*0.0022077147786478436f);
        }
}

使用特权

评论回复
7
zeshoufx|  楼主 | 2023-1-3 19:29 | 只看该作者
zeshoufx 发表于 2023-1-3 19:29
5.滤波:滤波在信号处理中特别重要,在模拟前端经硬件滤波后,流入ADC,采集到的数据可能还达不到直接使 ...

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

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

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

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

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


void dsp_test(void)
{
        /* 输入数组 */
  float32_t in[2];

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

  in[0] = 1.5f;
  in[1] = 1.0f;

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

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

  in[0] = -1.5f;
  in[1] = 1.0f;

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

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

  in[0] = 0.0f;
  in[1] = -3.0f;

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

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


}


使用特权

评论回复
8
zeshoufx|  楼主 | 2023-1-3 19:30 | 只看该作者
zeshoufx 发表于 2023-1-3 19:29
6.高斯朴素贝叶斯分类器:高斯朴素贝叶斯分类器属于偏机器学习领域,通过给出符合高斯分布的均值和方差及 ...

7.插值:插值在数据分析和处理中较常用,有时数据量不够,可以通过一些插值手段,将数据进行丰富,方便分析。
常规的插值有线性插值、样条插值。测试主要针对样条插值,给出32点的正弦信号,通过插值方法将数据点拓展到
128点,分别对自然样条插值和抛物样条插值进行测试和对比。
void dsp_test(void)
{
        u8 i=0;
        float32_t data[128]={0.};
        for(i=0;i<128;i++)
        {
                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);
                printf("%f\r\n",data[i]);
        }
}



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

//arm_spline_f32   parameter
static float32_t  xq[128];
static float32_t  pDst[128];
static uint32_t blockSize=128;

#define num_tab 128/32

void interp_test(u8 mode)
{
        if(mode)
        {
                type=ARM_SPLINE_NATURAL;//自然样条插值
        }
        else
        {
                type=ARM_SPLINE_PARABOLIC_RUNOUT;//抛物样条插值
        }
        
        u8 i=0;
        for(i=0;i<32;i++)
        {
                x[i]=i*num_tab;
                y[i]=1.f+arm_sin_f32(100.f*PI*i/256.f+PI/3.f);
        }
        
        for(i=0;i<128;i++)
        {
                xq[i]=i;
        }
        
        arm_spline_init_f32(&S,type,x,y,n,coeffs,tempBuffer);
        arm_spline_f32(&S,xq,pDst,blockSize);
        
        printf("*****x********\r\n");
        for(i=0;i<32;i++)
        {
                printf("%f\r\n",x[i]);
        }
        printf("*****y********\r\n");
        for(i=0;i<32;i++)
        {
                printf("%f\r\n",y[i]);
        }
        
        
        printf("*****x1********\r\n");
        for(i=0;i<128;i++)
        {
                printf("%f\r\n",xq[i]);
        }
        
        printf("*****y1********\r\n");
        for(i=0;i<128;i++)
        {
                printf("%f\r\n",pDst[i]);
        }
}

使用特权

评论回复
9
zeshoufx|  楼主 | 2023-1-3 19:32 | 只看该作者
zeshoufx 发表于 2023-1-3 19:30
7.插值:插值在数据分析和处理中较常用,有时数据量不够,可以通过一些插值手段,将数据进行丰富,方便分 ...

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


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

        float32_t  pData1[25]={3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3};       

        float32_t  pData2[25]={0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0};       
       
        u8 i=0;
        arm_mat_init_f32(&S,nRows,nColumns,pData);
        arm_mat_init_f32(&S1,nRows,nColumns,pData1);
        arm_mat_init_f32(&S2,nRows,nColumns,pData2);
       
       
        printf("矩阵A=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
        printf("\r\n");
        printf("矩阵B=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S1.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
        arm_mat_add_f32(&S,&S1,&S2);
        printf("\r\n");
        printf("矩阵A+B=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
        arm_mat_mult_f32(&S,&S1,&S2);
        printf("\r\n");
        printf("矩阵A*B=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
        arm_mat_inverse_f32(&S,&S2);
        printf("\r\n");
        printf("矩阵A的逆矩阵=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
}

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

        float32_t  pData1[25]={3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3,
                                                3,3,3,3,3};       

        float32_t  pData2[25]={0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0,
                                                0,0,0,0,0};       
       
        arm_mat_init_f32(&S,nRows,nColumns,pData);
        arm_mat_init_f32(&S1,nRows,nColumns,pData1);
        arm_mat_init_f32(&S2,nRows,nColumns,pData2);
       
        arm_mat_scale_f32(&S,0.1f,&S2);
        printf("\r\n");
        printf("矩阵A*0.1=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
       
        arm_mat_sub_f32(&S,&S1,&S2);
        printf("\r\n");
        printf("矩阵A-B=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
       
       
        arm_mat_trans_f32(&S,&S2);
        printf("\r\n");
        printf("矩阵A的转置=\r\n");
        for(i=0;i<25;i++)
        {
                printf("%f        ",S2.pData[i]);
                if(i%5==4)
                {
                        printf("\r\n");
                }
        }
}

void dsp_test(void)
{
        dsp_test1();
        dsp_test2();
}


使用特权

评论回复
10
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
arm_pid_instance_f32 S;                //定义PID结构体
float ref=2678./4095*3.3;        //ADC参考目标值:2678

void ad_da_init(void)
{
        //时钟配置
        rcu_periph_clock_enable(RCU_GPIOA);
        rcu_periph_clock_enable(RCU_AF);
        rcu_periph_clock_enable(RCU_ADC0);
        rcu_periph_clock_enable(RCU_DAC);
       
        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);
       
        //接口配置
        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4);
        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
       
        //ADC输入配置
        adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);
        adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
        adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);
        adc_regular_channel_config(ADC0,0,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);
        adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,DISABLE);
       
        adc_enable(ADC0);
        delay_ms(1);
        adc_calibration_enable(ADC0);
       
        //DAC输出配置
        dac_trigger_source_config(DAC0,DAC_TRIGGER_SOFTWARE);
        dac_trigger_enable(DAC0);
        dac_wave_mode_config(DAC0,DAC_WAVE_DISABLE);
        dac_output_buffer_enable(DAC0);
       
        dac_enable(DAC0);
       
        //PID参数初始化
        S.Kd=0;
        S.Ki=16;
        S.Kp=100;

        arm_pid_init_f32(&S,1);
}



volatile float adc_get=0.;

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

        if(pid_num>=4095)
        {
                pid_num=4095;
        }
    dac_data_set(DAC0, DAC_ALIGN_12B_R, (u16)pid_num);
      
    dac_software_trigger_enable(DAC0);
       
        adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);
        if(adc_flag_get(ADC0,ADC_FLAG_EOC))
        {
                adc_flag_clear(ADC0,ADC_FLAG_EOC);
                adc_get = adc_regular_data_read(ADC0)/4095.*3.3;
        }
       
        printf("%f        %d        %d\r\n",adc_get,(u16)pid_num,adc_regular_data_read(ADC0));
}

使用特权

评论回复
11
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
#define SEMIHOSTING 1                                //使能打印


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


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


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

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

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


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


void dsp_test(void)
{
                /* 输入数据 */
        float32_t in[VECTOR_DIMENSION];
       
        /* 分类器结果 */
        int32_t result;
       
       
       
                //初始化支持向量机实例化结构体
        arm_svm_polynomial_init_f32(¶ms,        //实例化结构体
                NB_SUPPORT_VECTORS,                                        //向量个数
                VECTOR_DIMENSION,                                        //向量维数
                -1.661719f,                                                //截距
                dualCoefficients,                                        //双系数
                supportVectors,                                                //支持向量
                classes,                                                        //类ID标识
                3,                                                         //多项式次数
                1.100000f,                                                 //python scikit-learn包专用系数
                0.500000f                                                  //python scikit-learn包专用系数
        );
       
       
        //输入测试数据,类A
        in[0] = 0.4f;
        in[1] = 0.1f;
       
        arm_svm_polynomial_predict_f32(¶ms, in, &result);
       
        //根据分类标识:如果分类器结果为A,则标识必为“0”
        #if defined(SEMIHOSTING)
        printf("Result = %d\n", result);
        #endif
       
        //输入测试数据,类B
        in[0] = 3.0f;
        in[1] = 0.0f;
       
        arm_svm_polynomial_predict_f32(¶ms, in, &result);
       
        //根据分类标识:如果分类器结果为A,则标识必为“1”
        #if defined(SEMIHOSTING)
        printf("Result = %d\n", result);
        #endif
       
}
1.  采用ARM官方提供的DSP
2.  所有测试经过与MATLAB测试对比
3.  软件采用MDK 5.35DSP采用1.8.0版本,单片机采用GD32F103VKT6

使用特权

评论回复
12
zeshoufx|  楼主 | 2023-1-3 19:37 | 只看该作者
zeshoufx 发表于 2023-1-3 19:34
10。支持向量机分类器:支持向量机与贝叶斯分类器同属于机器学习领域,支持向量机分类器有线性和非线性, ...

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

#define F_COUNT 512
#define M 16

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


/*LMS具体算法*/
//float * LMS_Filter(int itr, const float *xn, const float *dn, float mu, int length);
void LMS_Filter(int itr, const float *xn, const float *dn, float mu, int length,float *yn)
{
    static int i = 0;
    static int k = 0;
    static float y = 0.0;
    static float en[F_COUNT];
    static float W[M][F_COUNT];
    static float x[M];

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

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

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

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

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

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

        y = 0.0;
    }

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

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

        yn[k-1] = y;
        y = 0.0;

    }

}


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

void dsp_test(void)
{
        u16 i=0;
        for(i=0;i<512;i++)
        {
                xn[i]=1.5f*arm_sin_f32(100*PI*i/6400)+0.5f*arm_sin_f32(900*PI*i/6400);
        }
       
        for(i=0;i<512;i++)
        {
                dn[i]=1.5f*arm_sin_f32(100*PI*i/6400);
        }
       
       
        LMS_Filter(128, xn, dn, 0.0008, 512,yn);
       
       
        for(i=0;i<512;i++)
        {
                printf("%f        %f        %f\r\n",xn[i],dn[i],yn[i]);
        }
}
20阶迭代22次结果:

20阶迭代100次结果:

20阶迭代300次结果:

10100次迭代结果:

32100次迭代结果:

16128次迭代结果:



使用特权

评论回复
13
zeshoufx|  楼主 | 2023-1-3 19:38 | 只看该作者
zeshoufx 发表于 2023-1-3 19:37
1、自适应滤波:采用基波叠加9次谐波,滤除9次谐波,对比了不同阶数和迭代次数的结果20阶迭代22次结果:
...

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



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

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


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




/**************************/
/*    update()函数        */
/*    更新信息素          */
/**************************/
void update(int cost[2][STEPS]
        ,double pheromone[2][STEPS]
        ,int mSTEPS[NOA][STEPS] )
{
        int m ;/*蚂蚁个体的号码*/
        int lm ;/*蚂蚁步行的距离*/
        int i,j ;
        double sum_lm=0 ;/*蚂蚁步行的总体距离*/
       
        /*信息素的挥发*/
        for(i=0;i<2;++i)
                for(j=0;j<STEPS;++j)
                        pheromone[i][j]*=RHO ;
       
        /*蚂蚁的覆盖*/
        for(m=0;m<NOA;++m)
        {
        /*个体m的移动距离lm的计算*/
        lm=0 ;
        for(i=0;i<STEPS;++i)
                lm+=cost[mSTEPS[m][i]][i] ;
       
        /*信息素的覆盖*/
        for(i=0;i<STEPS;++i)
                pheromone[mSTEPS[m][i]][i]+=Q*(1.0/lm) ;
        sum_lm+=lm ;
        }
        /*蚂蚁步行的平均距离的输出*/
        printf("%lf\n",sum_lm/NOA) ;
}

/**************************/
/*    walk()函数          */
/*    使蚂蚁步行          */
/**************************/
void walk(int cost[2][STEPS]
,double pheromone[2][STEPS],int mSTEPS[NOA][STEPS])
{
        int m ;/*蚂蚁个体的号码*/
        int s ;/*蚂蚁现在所处的位置*/
       
        for(m=0;m<NOA;++m)
        {
                for(s=0;s<STEPS;++s)
                {
                        /*基于ε-greedy的行动选择*/
                        if((rand1()<EPSILON)||(abs(pheromone[0][s]-pheromone[1][s])<1e-9))
                        {
                                /*随机行动*/
                                mSTEPS[m][s]=rand01() ;
                        }
                        else
                        {/*基于信息素的选择*/
                                if(pheromone[0][s]>pheromone[1][s])
                                        mSTEPS[m][s]=0 ;
                                else
                                        mSTEPS[m][s]=1 ;
                        }
                }
        }
/*输出蚂蚁的行动*/
printmSTEPS(mSTEPS) ;
}

/**************************/
/*  printmSTEPS()函数      */
/*   显示蚂蚁的行动       */
/**************************/
void printmSTEPS(int mSTEPS[NOA][STEPS])
{
        int i,j ;
       
        printf("*mSTEPS\n") ;
        for(i=0;i<NOA;++i)
        {
                for(j=0;j<STEPS;++j)
                printf("%d ",mSTEPS[i][j]) ;
                printf("\n") ;
        }
}


/**************************/
/*    printp()函数        */
/*   显示信息素           */
/**************************/
void printp(double pheromone[2][STEPS])
{
        int i,j ;
       
        for(i=0;i<2;++i)
        {
                for(j=0;j<STEPS;++j)
                printf("%4.2lf ",pheromone[i][j]) ;
                printf("\n") ;
        }
}

/**************************/
/*    rand1()函数         */
/*返回0~1的实数的随机函数*/
/**************************/
double rand1(void)
{
        /*随机数的计算*/
        return (double)rand()/RAND_MAX ;

}

/****************************/
/*     rand01()函数         */
/*返回0、1的随机函数        */
/****************************/
int rand01(void)
{
        int rnd ;
       
        /*去除随机数的最大值*/
        while((rnd=rand())==RAND_MAX) ;
        /*计算随机数*/
        return (int)((double)rnd/RAND_MAX*2) ;

}


void dsp_test(void)
{
        int cost[2][STEPS]={/*各步的代价(距离)*/
         {1,1,1,1,1,1,1,1,1,1},
         {5,5,5,5,5,5,5,5,5,5}};
        double pheromone[2][STEPS]={0} ;/*各步的信息素量*/
        int mSTEPS[NOA][STEPS] ;/*蚂蚁走过的过程*/
        int i;/*循环次数的控制*/
       
        /*随机数的初始化*/
        srand(SEED) ;
       
        /*最优化的主体*/
        for(i=0;i<ILIMIT;++i)
        {
                /*信息素的状态的输出*/
                printf("%d:\n",i) ;
                printp(pheromone) ;
                /*使蚂蚁步行*/
                walk(cost,pheromone,mSTEPS) ;
                /*更新信息素*/
                update(cost,pheromone,mSTEPS) ;
        }
        /*信息素状态的输出*/
        printf("%d:\n",i) ;
        printp(pheromone) ;
}


使用特权

评论回复
14
zeshoufx|  楼主 | 2023-1-3 19:40 | 只看该作者
zeshoufx 发表于 2023-1-3 19:38
蚁群算法:蚁群算法作为群体智能优化的代表,与全局搜索算法比较具有速度快的特点

...

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

#include "arm_nnfunctions.h"
#include "arm_nnexamples_cifar10_inputs.h"

#ifdef _RTE_
#include "RTE_Components.h"
#ifdef RTE_Compiler_EventRecorder
#include "EventRecorder.h"
#endif
#endif

// include the input and weights

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

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

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

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

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

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

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




void dsp_test(void)
{
       
#ifdef RTE_Compiler_EventRecorder
  EventRecorderInitialize (EventRecordAll, 1);  // initialize and start Event Recorder
  #endif

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

  q7_t     *img_buffer1 = scratch_buffer;
  q7_t     *img_buffer2 = img_buffer1 + 32 * 32 * 32;

  /* input pre-processing */
  int mean_data[3] = INPUT_MEAN_SHIFT;
  unsigned int scale_data[3] = INPUT_RIGHT_SHIFT;
  for (int i=0;i<32*32*3; i+=3) {
    img_buffer2[i] =   (q7_t)__SSAT( ((((int)image_data[i]   - mean_data[0])<<7) + (0x1<<(scale_data[0]-1)))
                             >> scale_data[0], 8);
    img_buffer2[i+1] = (q7_t)__SSAT( ((((int)image_data[i+1] - mean_data[1])<<7) + (0x1<<(scale_data[1]-1)))
                             >> scale_data[1], 8);
    img_buffer2[i+2] = (q7_t)__SSAT( ((((int)image_data[i+2] - mean_data[2])<<7) + (0x1<<(scale_data[2]-1)))
                             >> scale_data[2], 8);
  }
  
  // conv1 img_buffer2 -> img_buffer1
  arm_convolve_HWC_q7_RGB(img_buffer2, CONV1_IM_DIM, CONV1_IM_CH, conv1_wt, CONV1_OUT_CH, CONV1_KER_DIM, CONV1_PADDING,
                          CONV1_STRIDE, conv1_bias, CONV1_BIAS_LSHIFT, CONV1_OUT_RSHIFT, img_buffer1, CONV1_OUT_DIM,
                          (q15_t *) col_buffer, NULL);

  arm_relu_q7(img_buffer1, CONV1_OUT_DIM * CONV1_OUT_DIM * CONV1_OUT_CH);

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

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

  arm_relu_q7(img_buffer1, CONV2_OUT_DIM * CONV2_OUT_DIM * CONV2_OUT_CH);

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

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

  arm_relu_q7(img_buffer1, CONV3_OUT_DIM * CONV3_OUT_DIM * CONV3_OUT_CH);

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

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

  arm_softmax_q7(output_data, 10, output_data);

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


}


使用特权

评论回复
15
zeshoufx|  楼主 | 2023-1-3 19:41 | 只看该作者
zeshoufx 发表于 2023-1-3 19:40
卷积神经网络:卷积神经网络在图像处理等领域中运用广泛,在ARM官方提供的CMSIS-NN库中,就包含了卷积神 ...

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

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

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

/*全局变量(行李数据)*/
int parcel[N][2] =
{
        {65,27},
        {39,82},
        {9,85},
        {72,71},
        {87,91},
        {91,28},
        {34,92},
        {58,79},
        {3,27},
        {12,82},
        {92,15},
        {39,49},
        {83,54},
        {76,43},
        {6,26},
        {77,2},
        {68,6},
        {24,60},
        {60,47},
        {6,40},
        {91,58},
        {44,68},
        {50,33},
        {91,92},
        {57,62},
        {97,49},
        {96,68},
        {39,77},
        {89,6},
        {24,97}
};/*行李*/



/****************************/
/*      initparcel()函数    */
/*      行李的初始化        */
/****************************/
void initparcel()
{
//        int i=0 ;
//        while((i<N) &&
//                (scanf("%d %d",&parcel[i][0],&parcel[i][1])
//                        !=EOF)){
//                ++i ;
//        }

       
}

/************************/
/*   selectng()函数     */
/*   选择下一代         */
/************************/
void selectng(int ngpool[POOLSIZE*2][N]
        ,int pool[POOLSIZE][N])
{
        int i,j,c ;/* 循环控制参数 */
        int totalfitness=0 ;/*适应度的总计值*/
        int roulette[POOLSIZE*2] ;/*存放适应度*/
        int ball ;/* 球(选择位置的数值)*/
        int acc=0 ;/*适应度的累积值*/
       
        /*循环进行选择*/
        for(i=0;i<POOLSIZE;++i){
                /* 生成轮盘 */
                totalfitness=0 ;
                for(c=0;c<POOLSIZE*2;++c){
                        roulette[c]=evalfit(ngpool[c]) ;
                        /*计算适应度的总计值*/
                        totalfitness+=roulette[c] ;
                }
                /*选择一个染色体*/
                ball=rndn(totalfitness) ;
                acc=0 ;
                for(c=0;c<POOLSIZE*2;++c){
                        acc+=roulette[c] ;/*累积评价值*/
                        if(acc>ball) break ;/*对应的基因*/
                }
               
                /*染色体的复制*/
                for(j=0;j<N;++j){
                        pool[i][j]=ngpool[c][j] ;
                }
        }
}

/************************/
/*   selectp()函数      */
/*    父代的选择        */
/************************/
int selectp(int roulette[POOLSIZE],int totalfitness)
{
        int i ;/* 循环的控制变量 */
        int ball ;/* 球(选择位置的数值)*/
        int acc=0 ;/*评价值的累积值*/
       
        ball=rndn(totalfitness) ;
        for(i=0;i<POOLSIZE;++i){
                acc+=roulette[i] ;/*评价值的累积*/
                if(acc>ball) break ;/*对应的基因*/
        }
        return i ;
}


/************************/
/*   mating()函数       */
/*        交叉          */
/************************/
void mating(int pool[POOLSIZE][N]
        ,int ngpool[POOLSIZE*2][N])
{
        int i ;/* 循环的控制变量 */
        int totalfitness=0 ;/*评价值的总计值*/
        int roulette[POOLSIZE] ;/*存放评价值*/
        int mama,papa ;/*父代的基因的号码*/
       
        /* 生成轮盘 */
        for(i=0;i<POOLSIZE;++i){
                roulette[i]=evalfit(pool[i]) ;
                /* 计算评价值的总计值*/
                totalfitness+=roulette[i] ;
        }
       
        /*选择和交叉的循环*/
        for(i=0;i<POOLSIZE;++i){
                do{/*父代的选择*/
                        mama=selectp(roulette,totalfitness) ;
                        papa=selectp(roulette,totalfitness) ;
                }while(mama==papa) ;/*删除重复的*/
               
                /*特定2染色体的交叉*/
                crossing(pool[mama],pool[papa]
                        ,ngpool[i*2],ngpool[i*2+1])  ;  
        }
}


/************************/
/*  crossing()函数      */
/* 特定2染色体的交叉    */
/************************/
void crossing(int m[],int p[],int c1[],int c2[])
{
        int j ;/* 循环控制变量 */
        int cp ;/*交叉的点*/
       
        /*确定交叉点*/
        cp =rndn(N) ;
       
        /*复制前半部分*/
        for(j=0;j<cp;++j){
                c1[j]=m[j] ;
                c2[j]=p[j] ;
        }
        /*复制后半部分*/
        for(;j<N;++j){
                c2[j]=m[j] ;
                c1[j]=p[j] ;
        }
}

/************************/
/*   evalfit()函数      */
/*   计算评价值         */
/************************/
int evalfit(int g[])
{
        int pos ;/*指定基因位点*/
        int value=0 ;/*评价值*/
        int weight=0 ;/*重量*/
       
        /*调查各个基因位点计算重量和评价值*/
        for(pos=0;pos<N;++pos){
                weight+=parcel[pos][0]*g[pos] ;
                value+=parcel[pos][1]*g[pos] ;
        }
        /*致死基因的处理*/
        if(weight>=WEIGHTLIMIT) value=0 ;
        return value;
       
}

/***********************/
/*   printp()函数      */
/*   输出结果          */
/***********************/
void printp(int pool[POOLSIZE][N])
{
        int i,j ;/* 循环的控制变量 */
        int fitness ;/* 评价值 */
        double totalfitness=0 ;/* 评价值的总计值 */
        int elite,bestfit=0 ;/*精英基因的处理用变量*/
       
        for(i=0;i<POOLSIZE;++i){
                for(j=0;j<N;++j)
                        printf("%1d",pool[i][j]) ;
                fitness=evalfit(pool[i]) ;
                printf("\t%d\n",fitness) ;
                if(fitness>bestfit){/*精英解*/
                        bestfit=fitness ;
                        elite=i ;
                }
                totalfitness+=fitness ;
        }
        /*输出精英解的评价值*/
        printf("%d\t%d \t",elite,bestfit) ;
        /*输出平均评价值*/
        printf("%lf\n",totalfitness/POOLSIZE) ;
}


/***********************/
/*   initpool()函数    */
/*   生成初始染色体集合*/
/***********************/
void initpool(int pool[POOLSIZE][N])
{
        int i,j ;/* 循环控制变量 */
       
        for(i=0;i<POOLSIZE;++i)
                for(j=0;j<N;++j)
                        pool[i][j]=rndn(2) ;
}


/************************/
/*     rndn()函数       */
/*    n以下随机数的生成 */
/************************/
int rndn(int l)
{
        int rndno ;/*生成的随机数*/
       
        while((rndno=((double)rand()/RAND_MAX)*l)==l) ;
       
        return rndno;
}

/***********************/
/*   mutation()函数    */
/*   突变              */
/***********************/
void mutation(int ngpool[POOLSIZE*2][N])
{
        int i,j ;/* 循环的控制变量 */
       
        for(i=0;i<POOLSIZE*2;++i)
                for(j=0;j<N;++j)
                        if((double)rndn(100)/100.0<=MRATE)
                                /*反转的突变*/
                                ngpool[i][j]=notval(ngpool[i][j]) ;
       
}

/************************/
/*   notval()函数       */
/*   真值的反转         */
/************************/
int notval(int v)
{
        if(v==YES) return NO ;
        else return YES ;
}

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

void dsp_test(void)
{
       
       
        /*随机数的初始化*/
        srand(SEED) ;
       
//        /*行李的初始化*/
//        initparcel() ;
       
        /*生成初始染色体集合*/
        initpool(pool) ;
       
        /*循环直至终止子代*/
        for(generation=0;generation<LASTG;++generation){
                printf("%d代数\n",generation) ;
                mating(pool,ngpool) ;/*交叉*/
                mutation(ngpool) ;/*突变*/
                selectng(ngpool,pool) ;/*选择下一子代*/
                printp(pool) ;/*输出结果*/
        }
}


使用特权

评论回复
16
zeshoufx|  楼主 | 2023-1-3 19:42 | 只看该作者
zeshoufx 发表于 2023-1-3 19:41
遗传算法:遗传算法也是一种优化算法,模拟背包问题,寻求最优解

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

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

type_KalmanFilter k;

float RandomNumGenerator(int base, int range)
{
        float k = 0.0;
        float randomNum = 0.0;

        k = 2 * range * 10;

        randomNum = rand() % (int)k;

        k = base - range + (randomNum / 10);
        return k;
}


//Kalman初始化
void Kalman_Init(type_KalmanFilter* kalmanFilter, float FirstMeaValue, float E_mea, float FirstEstValue, float E_est)
{
        kalmanFilter->x_est = FirstEstValue;
        kalmanFilter->x_mea = FirstMeaValue;
        kalmanFilter->e_est = E_est;
        kalmanFilter->e_mea = E_mea;
        kalmanFilter->Kk = Kk_calc(kalmanFilter->e_est, kalmanFilter->e_mea);
}

//Kalman更新
void Kalman_Update(type_KalmanFilter* kalmanFilter, float newMeaValue)
{
        float temp = kalmanFilter->e_est;
        kalmanFilter->x_est = kalmanFilter->x_est + kalmanFilter->Kk * (newMeaValue - kalmanFilter->x_est);
        kalmanFilter->x_mea = newMeaValue;
        kalmanFilter->Kk = Kk_calc(kalmanFilter->e_est, kalmanFilter->e_mea);
        kalmanFilter->e_est = (1 - kalmanFilter->Kk) * temp;
}

void ad_da_init(void)
{
        //时钟配置
        rcu_periph_clock_enable(RCU_GPIOA);
        rcu_periph_clock_enable(RCU_AF);
        rcu_periph_clock_enable(RCU_ADC0);
        rcu_periph_clock_enable(RCU_DAC);
       
        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV12);
       
        //接口配置
        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_4);
        gpio_init(GPIOA,GPIO_MODE_AIN,GPIO_OSPEED_50MHZ,GPIO_PIN_6);
       
        //ADC输入配置
        adc_special_function_config(ADC0,ADC_CONTINUOUS_MODE,ENABLE);
        adc_data_alignment_config(ADC0,ADC_DATAALIGN_RIGHT);
        adc_channel_length_config(ADC0,ADC_REGULAR_CHANNEL,1);
        adc_regular_channel_config(ADC0,0,ADC_CHANNEL_6,ADC_SAMPLETIME_55POINT5);
        adc_external_trigger_config(ADC0,ADC_REGULAR_CHANNEL,DISABLE);
       
        adc_enable(ADC0);
        delay_ms(1);
        adc_calibration_enable(ADC0);
       
        //DAC输出配置
        dac_trigger_source_config(DAC0,DAC_TRIGGER_SOFTWARE);
        dac_trigger_enable(DAC0);
        dac_wave_mode_config(DAC0,DAC_WAVE_DISABLE);
        dac_output_buffer_enable(DAC0);
       
        dac_enable(DAC0);
        dac_data_set(DAC0, DAC_ALIGN_12B_R, (u16)1024);
    dac_software_trigger_enable(DAC0);
       
        //Kalman初始化
        Kalman_Init(&k, 1024, 2, 1024, 2);
}



void dsp_test(void)
{
        u16 adc_get=0;
       
        adc_software_trigger_enable(ADC0,ADC_REGULAR_CHANNEL);
        if(adc_flag_get(ADC0,ADC_FLAG_EOC))
        {
                adc_flag_clear(ADC0,ADC_FLAG_EOC);
                adc_get = adc_regular_data_read(ADC0);
                Kalman_Update(&k,adc_get);
        }
       
        printf("%d        %f        %f\r\n",adc_get,k.x_mea,k.x_est);
}

使用特权

评论回复
17
zeshoufx|  楼主 | 2023-1-3 19:42 | 只看该作者
zeshoufx 发表于 2023-1-3 19:42
1、卡尔曼滤波:卡尔曼滤波在数据采集中运用广泛,在数据波动的情况下获得真实值。
...

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


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};
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};


//求线性回归方程:Y=ax+b
//dada_x数组:X;
//data_y数组:Y;
//length:数据个数;
//a,b:返回回归系数
//返回值:无
void LinearRegression(        float *data_x,
                                                float *data_y,
                                                u16 length,
                                                float *a,
                                                float *b)
{
        u16 i=0;
        float sum_x=0.,sum_y=0.;
        float mean_x=0.,mean_y=0.;
        float Lxy=0.,Lxx=0.;
       
        //分别求和
        for(i=0;i<length;i++)
        {
                sum_x+=data_x[i];
                sum_y+=data_y[i];
        }
       
        //取平均
        mean_x=sum_x/length;
        mean_y=sum_y/length;
       
        //计算分母和分子
        for ( i=0; i!=length; i++)
        {
                Lxy += (data_x[i] - mean_x) * (data_y[i] - mean_y);
                Lxx += (data_x[i] - mean_x) * (data_x[i] - mean_x);
        }
       
        //计算回归系数
        *a=Lxy/Lxx;
        *b=mean_y-(*a)*mean_x;
}

void dsp_test(void)
{
        float a=0.,b=0.;
        LinearRegression(data_x,data_y,12,&a,&b);
        printf("%f        %f\r\n",a,b);
}

使用特权

评论回复
18
caigang13| | 2023-1-3 20:47 | 只看该作者
MCU还能玩神经网络计算?

使用特权

评论回复
19
zeshoufx|  楼主 | 2023-1-4 08:59 | 只看该作者
caigang13 发表于 2023-1-3 20:47
MCU还能玩神经网络计算?

可以的,,ARM官方提供的CMSIS-NN库,就是针对cortex-M 和cortex-A CPU的,,

使用特权

评论回复
20
cauhorse| | 2023-1-5 13:33 | 只看该作者
楼主玩得很全面,佩服

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

67

主题

1962

帖子

14

粉丝