对于线性变化的物理量可以根据简单的换算得出测量值与实际物理量的关系,但是实际大多数被检测物理量与转换后的数字量之间不是严格的线性关系。比如热敏电阻的阻值与温度,锂电池的电压与剩余电量,不可能按步进1ohm的阻值或者0.01v的电压建立很大一张对应表。一般情况下会标定有限个参考点,通过软件算法拟合去估算实际值。
已知(x0,y0)和(x1,y1),在这两个值之间插入节点,按线性函数g(x)=ax+b,计算得出
g(x)=y0+(y1-y0)*(x-x0)/( x1-x0)
插值节点x0与 x1的间距越小,则f(x)与g(x)之间的误差越小。以下面的数据为例说明。
- #define N 11
- //参考点
- int table[N][2]={
- {0, 2},
- {10, 12},
- {20, 21},
- {30, 29},
- {40, 36},
- {50, 42},
- {60, 47},
- {70, 51},
- {80, 54},
- {90, 56},
- {100, 57}
- };
-
- int conversion(int x)
- {
- int i;
- int y;
-
- if(x<table[0][0])
- {
- return table[0][1];
- }
-
- if(x>table[N-1][0])
- {
- return table[N-1][1];
- }
-
- for(i=0;i<N;i++)
- {
- if(x<=table[i][0])//数据排序,找到x前后的插值节点
- {
- //表示x介于table[i-1][0]~table[i][0]之间
- break;
- }
- }
-
- y=table[i-1][1]+(table[i][1]-table[i-1][1])*(x-table[i-1][0])/(table[i][0]-table[i-1][0]);
- return y;
- }
-
- int main(void)
- {
- printf("x=25,y=%d\r\n",conversion(25));
- printf("x=75,y=%d\r\n",conversion(75));
- return 0;
- }
-
运行后输出
x=25,y=25
x=75,y=52
将这两值插入原曲线图,效果如下,新加入的值基本与原曲线重合:
线性插值拟合,可以解决参考点有限的情况下估算对应关系,参考点越多,拟合得出的新值误差越小。