本帖最后由 zeshoufx 于 2022-10-28 22:05 编辑
插值算法运用很广,在采集数据较少的情况下,可以利用插值算法补充数据源,
常用的插值包括最邻近插值、线性插值(单线性插值和双线性插值)、样条插值;
其中样条插值包括自然样条插值、抛物样条插值;arm官方提供的样条插值就包括
这两种插值算法。
插值测试程序
#include "dsp_test.h"
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)]; //内部计算缓冲数组
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]);
}
}
测试对比一下自然样条插值和抛物样条插值两种方法
arm dsp库常量定义太多,ro-data占用空间较大
将数据拷贝到表格,导入到matlab
AB为原始数据,大小为32
C为插值后的x,大小为128
D为抛物样条插值的结果,大小为128
E为自然样条插值的结果,大小为128
主函数
/*!
\file main.c
\brief led spark with systick, USART print and key example
\version 2014-12-26, V1.0.0, firmware for GD32F10x
\version 2017-06-20, V2.0.0, firmware for GD32F10x
\version 2018-07-31, V2.1.0, firmware for GD32F10x
\version 2020-09-30, V2.2.0, firmware for GD32F10x
*/
#include "bitband.h"
#include "led.h"
#include "systick.h"
#include "print.h"
#include "dsp_test.h"
u16 mem_infor[2]={0};
u32 uid[3]={0};
int main(void)
{
systick_set(96);
led_init();
print_config(9600);
get_mem_infor(&mem_infor[0],&mem_infor[1]);
printf("GD32F103VKT6 Flash Size=%dKB,Sram Size=%dKB...\r\n",mem_infor[1],mem_infor[0]);
get_uid(uid);
printf("GD32F103VKT6 UID=%d%d%d...\r\n",uid[0],uid[1],uid[2]);
printf("\r\n抛物样条插值测试.....\r\n");
interp_test(0);
printf("\r\n自然样条插值测试.....\r\n");
interp_test(1);
while(1)
{
led_on();
delay_ms(1000);
led_off();
delay_ms(1000);
}
}
MATLAB程序
x=data(1:32,1);
y=data(1:32,2);
x1=data(:,3);
y1=data(:,4);
y2=data(:,5);
subplot(311)
plot(x,y),title('原始数据'),xlabel('x'),ylabel('y'),grid;
subplot(312)
plot(x1,y1),title('抛物样条插值结果'),xlabel('x'),ylabel('y'),grid;
subplot(313)
plot(x1,y2),title('自然样条插值结果'),xlabel('x'),ylabel('y'),grid;
结果
专栏细文:
程序
演示视频:
【ARM单片机插值算法,对比抛物样条插值和自然样条插值】 https://www.bilibili.com/video/BV1Sm4y1F7jc/?share_source=copy_web&vd_source=7f0cb9c0f09b768583faf157910eb515
结论:
可以看出插值后,正弦曲线变得很平滑,两者插值在细节上
无明显的区别,,只是最后几个点和趋势上抛物样条插值变缓
自然样条插值保持跟原始数据一样
|