同步操作将从 张恩寿/ARM CMSIS-DSP测试 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
ARM DSP基本就完了,包含了: 电机变换(克拉克变换、帕克变换)、卷积、 离散余弦变换、傅里叶变换、滤波、高斯朴素贝叶斯估计、 插值、矩阵运算、PID、支持向量机
软件架构说明
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]);
}
}
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]);
}
}
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]);
}
}
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]);
}
}
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);
}
}
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
}
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]);
}
}
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();
}
9.PID控制:PID控制在工业领域较为常用,尤其是自动化控制。PID初始化函数arm_pid_init_f32,PID控制函数为 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));
}
10。支持向量机分类器:支持向量机与贝叶斯分类器同属于机器学习领域,支持向量机分类器有线性和非线性, 对类A和类B进行标识,输入数据A和B,通过分类器计算结果,对输入数据进行分类,因为例程提供的是线性的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
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。