micro_climate/tools/xcorr.c

330 lines
9.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "xcorr.h"
#include "usart.h"
//float32_t x_rfft_out[1024];
//float32_t y_rfft_out[1024];
//
//float32_t x_temp[1024];
//
//float32_t cmplx_result[1024];
arm_rfft_fast_instance_f32 s;
//q15_t x_rfft_out[1024];
//q15_t y_rfft_out[1024];
//
//q15_t x_temp[1024];
//
//q15_t cmplx_result[1024];
float32_t corrx_out[DATA_LEN];
float32_t x_buf[DATA_LEN];
float32_t y_buf[DATA_LEN];
float32_t x_fft_O_f32[DATA_LEN] = {0};
float32_t y_fft_O_f32[DATA_LEN]= {0};
float32_t cmplx_mul_result_f32[DATA_LEN]= {0};
float32_t max_val_f32;
int32_t max_val_index_f32;
//void fft_acc_corr_f32_test()
//{
// arm_copy_f32((float32_t*)x,x_buf,DATA_LEN);
// arm_copy_f32((float32_t*)y,y_buf,DATA_LEN);
//
// __HAL_TIM_SET_COUNTER(&htim16,0);
// // 启定时器
// __HAL_TIM_ENABLE(&htim16);
//
//
// arm_offset_f32(x_buf,-2048,x_buf,DATA_LEN);
// arm_offset_f32(y_buf,-2048,y_buf,DATA_LEN);
//
// arm_rfft_fast_init_f32(&s,DATA_LEN);
//
// arm_rfft_fast_f32(&s,x_buf,x_fft_O_f32,0);
// //arm_rfft_fast_init_f32(&s,DATA_LEN);
// arm_rfft_fast_f32(&s,y_buf,y_fft_O_f32,0);
//
// arm_cmplx_conj_f32(y_fft_O_f32,y_fft_O_f32,DATA_LEN);
//
// // __HAL_TIM_DISABLE(&htim7);
//
// //arm_cmplx_mult_cmplx_q15_user(x_fft_O,y_fft_O,cmplx_mul_result,DATA_LEN*2);
// arm_cmplx_mult_cmplx_f32(x_fft_O_f32,y_fft_O_f32,cmplx_mul_result_f32,DATA_LEN>>1);
// //arm_rfft_init_q15(&s,DATA_LEN,1,1);
//
// // s.pTwiddleAReal
// arm_rfft_fast_init_f32(&s,DATA_LEN);
// arm_rfft_fast_f32(&s,cmplx_mul_result_f32,corrx_out,1);
//
// arm_max_f32(corrx_out,DATA_LEN,&max_val_f32,&max_val_index_f32);
//
// // 关闭定时
// __HAL_TIM_DISABLE(&htim16);
//
//
//}
//void fft_acc_corr_q15_test()
//{
// arm_copy_f32((float32_t*)x,x_buf,DATA_LEN);
// arm_copy_f32((float32_t*)y,y_buf,DATA_LEN);
//
// __HAL_TIM_SET_COUNTER(&htim16,0);
// // 启定时器
// __HAL_TIM_ENABLE(&htim16);
//
//
// arm_offset_f32(x_buf,-2048,x_buf,DATA_LEN);
// arm_offset_f32(y_buf,-2048,y_buf,DATA_LEN);
//
// arm_rfft_fast_init_f32(&s,DATA_LEN);
//
// arm_rfft_fast_f32(&s,x_buf,x_fft_O_f32,0);
// //arm_rfft_fast_init_f32(&s,DATA_LEN);
// arm_rfft_fast_f32(&s,y_buf,y_fft_O_f32,0);
//
// arm_cmplx_conj_f32(y_fft_O_f32,y_fft_O_f32,DATA_LEN);
//
// // __HAL_TIM_DISABLE(&htim7);
//
// //arm_cmplx_mult_cmplx_q15_user(x_fft_O,y_fft_O,cmplx_mul_result,DATA_LEN*2);
// arm_cmplx_mult_cmplx_f32(x_fft_O_f32,y_fft_O_f32,cmplx_mul_result_f32,DATA_LEN>>1);
// //arm_rfft_init_q15(&s,DATA_LEN,1,1);
//
// // s.pTwiddleAReal
// arm_rfft_fast_init_f32(&s,DATA_LEN);
// arm_rfft_fast_f32(&s,cmplx_mul_result_f32,corrx_out,1);
//
// arm_max_f32(corrx_out,DATA_LEN,&max_val_f32,&max_val_index_f32);
//
// // 关闭定时
// __HAL_TIM_DISABLE(&htim16);
//}
q15_t dc_offset;
float cal_tof(q15_t* x,uint32_t len)
{
q15_t max_val;
float32_t echo_p = 0,echo_dt = 0;
uint32_t max_val_p;
uint32_t i=0,stop_position = 0;
// 求取平均值
arm_mean_q15(x,100,&dc_offset);
// 查找数组中的最大值和最大值所在的索引
arm_max_q15(x,len,&max_val,&max_val_p);
max_val = max_val - dc_offset ;
//uint16_t echo_position = 0;
// 最大值的0.18倍
uint16_t max_val_zero_1R5 = (max_val*15/100)+dc_offset;
// 最大值的0.45倍
uint16_t max_val_zero_4R5 = (max_val*45/100)+dc_offset;
// 最大值的0.8倍
uint16_t max_val_zero_8R0 = (max_val*80/100)+dc_offset;
//如果最大值位置大于200 则从最大值前200个位置开始寻找起始波形。
// 优化的地方,从最大值位置开始找到达波,可以最大限度排除偶然噪声干扰,
// 因为噪声在波形到达出 噪声不是很大
//优化性能如果不需要则从数组0位置开始寻找其实波形
if(max_val_p>=70)
{
i = max_val_p-70;
}else
{
i = 0;
}
// 在最大值前寻找起始波形
for( ; i < max_val_p ; i++)
{
// 建议判断顶点,但是容易遇到偶然数据异常 类似于 28 29 28 30 29 28这种情况
//if( x[i-1] < x[i] && x[i]> x[i+1] )
// 排除以上数据异常情况但是有可能就无法检测到30 这个顶点。
// 故需要检测下一个周期的顶点,然后再减去一个周期的时间。
if( x[i-2]<x[i-1] && x[i-1] <= x[i] && x[i]>=x[i+1] && x[i+1]>x[i+2])
{
// 减去偏置电压
//temp_val_zero = arr[i]-2048;
// 判断顶点是否在 15%-%45之间。
if(x[i] >= max_val_zero_1R5 && x[i] <= max_val_zero_4R5 )
{
// 如果找到 函数退出
echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]);
echo_p = (float)i+echo_dt;
return echo_p;
}
// 如果15% ~45%之间的数据未找到则找45-80%的顶点。
// 判断顶点是否在 45% -- 80% 之间
if(x[i] >= max_val_zero_4R5 && x[i] <= max_val_zero_8R0)
{
// 如果找到 函数推出
echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]);
// 换算成第二个顶点的位置。
echo_p = (float)i+echo_dt - 12.5;
return echo_p;
}
}
}
/*
// 2.5M/0.2k= 12.5 查找最大值前5个周期63个点并计算到达时间
if(max_val_p>=63)
{
stop_position = max_val_p-63;
}
else
{
stop_position = 0;
}
for(i = max_val_p-5 ; i >= stop_position ; i--)
{
if( x[i-2]<x[i-1] && x[i-1] <= x[i] && x[i]>=x[i+1] && x[i+1]>x[i+2])
{
// 减去偏置电压
//temp_val_zero = arr[i]-2048;
// 如果15% ~45%之间的数据未找到则找45-80%的顶点。
// 判断顶点是否在 45% -- 80% 之间
if(x[i] >= max_val_zero_4R5 && x[i] <= max_val_zero_8R0)
{
// 如果找到 函数推出
echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]);
// 换算成第二个顶点的位置。
echo_p = (float)i+echo_dt - 12.5;
return echo_p;
}
// 判断顶点是否在 15%-%45之间。
if(x[i] >= max_val_zero_1R5 && x[i] <= max_val_zero_4R5 )
{
// 如果找到 函数退出
echo_dt = (x[i-1]-x[i+1])/2.0/(x[i-1]-2*x[i]+x[i+1]);
echo_p = (float)i+echo_dt;
return echo_p;
}
}
} */
return 0;
}
float32_t cal_dtof(q15_t* x , q15_t* y , uint32_t len)
{
float a,b,c;
float w_val,x_val,y_val;
float tof;
arm_rfft_fast_init_f32(&s,len);
// 定点数转成float
arm_q15_to_float(x,x_buf,DATA_LEN);
// 定点数转成float
arm_q15_to_float(y,y_buf,DATA_LEN);
// 初始化 fft
arm_rfft_fast_init_f32(&s,DATA_LEN);
// fft 前一半和后一半是对称的,所以只求解了512组数据
arm_rfft_fast_f32(&s,x_buf,x_fft_O_f32,0);
// fft
arm_rfft_fast_f32(&s,y_buf,y_fft_O_f32,0);
// 复数取共轭
arm_cmplx_conj_f32(y_fft_O_f32,y_fft_O_f32,DATA_LEN>>1);
// fft的数据
// 时域卷积==频域相乘 1024个数据 复数只有512个
arm_cmplx_mult_cmplx_f32(x_fft_O_f32,y_fft_O_f32,cmplx_mul_result_f32,DATA_LEN>>1);
// ifft
arm_rfft_fast_f32(&s,cmplx_mul_result_f32,corrx_out,1);
//
arm_max_f32(corrx_out,DATA_LEN,&max_val_f32,&max_val_index_f32);
b =corrx_out[max_val_index_f32];
if(max_val_index_f32 == 0)
{
a =corrx_out[len-1];
c =corrx_out[max_val_index_f32+1];
}
else
if(max_val_index_f32 == len-1)
{
a =corrx_out[max_val_index_f32-1];
c =corrx_out[0];
}else
{
a =corrx_out[max_val_index_f32-1];
c =corrx_out[max_val_index_f32+1];
}
// sin 插值 寻找最大值
w_val = acosf((a+c)/2.0/b);
float sin_val = sinf(w_val);
y_val = atanf((a-c)/2.0/b/sin_val);
x_val = (0-y_val)/w_val;
tof = max_val_index_f32+x_val;
if(tof>len/2)
tof= tof-len;
return tof;
}
float xcorr_max_position_uint16_t(q15_t* xcorr_out,q15_t* x , q15_t* y , uint32_t len)
{
uint32_t i = 0; // y参数移动的次数
q15_t max_val=0;
int32_t max_p=0;
q15_t max_val_point[3];
float w_val,x_val,y_val;
__HAL_TIM_SET_COUNTER(&htim16,0);
// 启定时器
__HAL_TIM_ENABLE(&htim16);
arm_correlate_fast_q15(x,len,y,len,xcorr_out);
// 关闭定时
__HAL_TIM_DISABLE(&htim16);
// xcorr(xcorr_out,x,y,len);
for(i=0;i<len*2-1;i++)
{
if(xcorr_out[i]>max_val)
{
max_val = xcorr_out[i];
max_p = i;
}
}
// 曲线拟合 找到最大点 当作中间数据
max_val_point[1] =xcorr_out[max_p];
max_val_point[0] =xcorr_out[max_p-1];
max_val_point[2] =xcorr_out[max_p+1];
// sin 插值 寻找最大值
w_val = acosf((max_val_point[0]+max_val_point[2]-4096)*1.0/(max_val_point[1]-2048)/(max_val_point[1]-2048));
y_val = atanf((max_val_point[0]-max_val_point[2])/2.0/(max_val_point[1]-2048)/sinf(w_val));
x_val = (0-y_val)/w_val;
//return ((float)max_p+0.1-0.1);
return (((float)max_p)-x_val);
// return -((float)max_p);
}