曲线拟合在单片机中的应用
滤波算法:在matlab中采用了三种滤波方法:1、滑动平均滤波 2、中值滤波 3、卡尔曼滤波
ADC处理的办法:去掉最大最小求平均,中值滤波(可以过滤尖峰脉冲。目的在于我们对于滤波后的数据更感兴趣。滤波后的数据保留的原图像的变化趋势,同时去除了尖峰脉冲对分析造成的影响。重点是冒泡排序取中值)
中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点,对脉冲噪声有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。这些优良特性是线性滤波方法所不具有的。此外,中值滤波的算法比较简单,也易于用硬件实现。所以,中值滤波方法一经提出后,便在数字信号处理领得到重要的应用
unsigned char GetMedianNum(int * bArray, int iFilterLen) { int i,j;// 循环变量 unsigned char bTemp; // 用冒泡法对数组进行排序 for (j = 0; j < iFilterLen - 1; j ++) { for (i = 0; i < iFilterLen - j - 1; i ++) { if (bArray[i] > bArray[i + 1]) { // 互换 bTemp = bArray[i]; bArray[i] = bArray[i + 1]; bArray[i + 1] = bTemp; } } } // 计算中值 if ((iFilterLen & 1) > 0) { // 数组有奇数个元素,返回中间一个元素 bTemp = bArray[(iFilterLen + 1) / 2]; } else { // 数组有偶数个元素,返回中间两个元素平均值 bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2; } return bTemp; }
#define size 6000//数组大小 #define N 12//滑动平均滤波计算平均值时所取的点数 /*上面两句在使用下面这个函数的时候加到程序的开头*/ void Smooth(float data[]) { Sum1=0; for(int j=0;j<size;j++) { if(j<N/2) { for(int k=0;k<N;k++) { Sum1+=data[j+k]; } data[j]=Sum1/N; } else if(j<size -N/2) { for(int k=0;k<N/2;k++) { Sum1+=(data[j+k]+data[j-k]); } data[j]=Sum1/N; } else { for(int k=0;k<size-j;k++) { Sum1+=data[j+k]; } for(int k=0;k<(N-size+j);k++) { Sum1+=data[j-k]; } data[j]=Sum1/N; } Sum1=0; } }
关于用excel进行数据直线拟合时不可忽视的小数点设置问题:
根据上述数据用excel拟合后得到的右边公式,用10进制表示就是y = 0.000004x - 1.7525,但你会发现如果将第二组数值带进在计算误差非常大 0.000004*1306247.897 -1.7525 =3.47249,误差达到(3.47249-4)/4=13%,那问题出现在那里呢?
如果右击直线公式,选择设置趋势线标签,在右侧设置数字,位数为8,则得到一些新公式,重新带入计算,误差就小很多了
0.00000441*1306247.897 -1.75251642 =4.0080368,误差(4.0080368-4)/4=0.2%,所以曲线拟合的时候如果x与Y的数量级差距非常大的时候,拟合出来的公式如果不设置小数点位数就会出现很大的误差,此时需要对直线公式设置系数的小数点位数(要足够大比如可以大于等于与X或Y中位数较大的那个的位数一致)就不会出现这个误差问题