在测量仪器上经常会用到线性拟合,通过测量的标准仪器标定出几个点,写进mcu的flash里面,比如说采到adc的值500对应标准盐溶液浓度的10%,1000对应盐溶液浓度20%,如果测量得知中间的值都是线性的,那么adc采到的值750,就对应浓度15%。
线性拟合分为两种情况,一种是整个量程线性度都非常的好,那么只需计算出一个k值就好,然后其他的点根据公式就可以计算出来,二是整个量程线性度不好,需要分段计算k值,那么这就需要多段线性拟合。线性相关的程度可以通过Matalab的curvefiting工具来帮你自动计算出k值,然后看rms的大小表示出的相关度的大小,也就是线性拟合出来的误差。这个curvefiting的使用后面我电脑装上Matalab再在这里补充上,这个工具确实很重要的。
1、整个量程线性度都很好的情况。
以我之前做过的一个激光测距仪的温度补偿为例,首先以室温25℃测出的距离为标准,温度升高距离增加,温度降低距离减小,比如测得数据如下:
10℃ 900mm
15℃ 902mm
20℃ 904mm
25℃ 906mm
30℃ 908mm
35℃ 910mm
40℃ 912mm
从数据可以看出温度变化5℃时,距离也会增加或者减小2mm,也就是k=2/5=0.4,那么首先机器在室温标准距离时就需要记录标定时的温度t,然后补偿的时候,根据当时的温度与标定时的温度做差,例如当前温度是32℃,标准时的温度是25℃,那么相减就是7摄氏度,然后再乘以0.4,就是变化2.8mm,所以最终的距离就是906mm+2.8mm=908.8mm。实际中的k值计算可以直接通过Matalab的curvefitting工具自动计算出来的。
2、多段线性拟合
原理和多段拟合差不多,原因是从曲线看,不同量程段的线性度有差异的,下面我贴一下我的多选线性拟合的代码:
u16 Fitting_Curve(u32 Num)//多段线性拟合
{static u8 number;double Kr;double Br;u16 Result = 0;static u16 Result_Current = 0;u16 number_2[Numr] = {0, 100, 300, 500, 700, 900, 1200, 1400, 1500};for( number=1; number<Numr; number++){if(Num<Data_buff[number]){break;}} if(number >= Numr)number = Numr-1;Kr = (number_2[number] - number_2[number-1]);Kr = Kr/(Data_buff[number] - Data_buff[number-1]);Br = (number_2[number-1] - Kr * Data_buff[number-1]);_main_pro.salinity_double = Kr * Num + Br;Result = (u16)_main_pro.salinity_double;/* if((Result%10)<5)Result = Result/10;elseResult = Result/10 + 1;if((Result_Current - Result) * (Result_Current - Result) >= 4){Result_Current = Result;}else{Result = Result_Current;}*/return Result;
}