文章目录
- 1 前言
- 2 二分法查找
-
- 3 分段线性插值
- 4 RTD实例
1 前言
处理器通过RTD采集电路(芯片)精确获得当前RTD电阻值后,再结合RTD与温度线性关系表,换算出当前环境温度。阻值与温度换算,通常是对“阻值—温度”进行查表匹配获得。因为,RTD“阻值—温度”在整个变化范围内不一定是标准线性关系,只在某一温度区间呈现线性或者接近线性。因此,首先将“阻值—温度”划分为一定数量的区间,然后通过“二分法查找算法”查找测量的阻值处于某一区间,再通过“线性插值法”计算出实际温度值。
相关文章:
【RTD】铂电阻测温原理与具体方法
【RTD】AD7793三线式铂电阻PT100/PT1000应用
【RTD】AD7793四线式铂电阻PT100/PT1000应用
【RTD】AD7793两线式铂电阻PT100/PT1000应用
【RTD】AD7793驱动程序
【RTD】二分法查找和分段线性插值算法在RTD中应用
2 二分法查找
二分法查找,或者成为折半法查找,是一种用于有序数组中查找特定元素的查找算法。二分法查找比较易于理解,查找步骤大致分为:
【1】将待查找数组分为两部分
【2】待查找值与数组中间值比较,确保待查找值处于哪一半部分
【3】将该半部分重复【1】【2】步骤,直至查找到目标值或者查找结束为止
2.1 复杂度
【1】最坏情况查找最后一个元素(第一个元素),此时时间复杂度为T(n) = O(log2n)
【2】最理想情况首次查找中间元素即为目标值(奇数长度数组的正中间值,偶数长度数组的中间靠左的元素),此时时间复杂度为T(n) = O(1)
S(n)=logn
2.2 实现
二分法查找算法,可以使用递归和非递归方式实现;递归方式对于查找长度比较长的数组需要更大的栈空间。
int binary_search(int *buf, uint32_t index_bottom, uint32_t index_top, int s_value)
{
uint32_t index_mid = 0;
if (index_bottom > index_top)
{
return -1;
}
index_mid = index_bottom + (index_top-index_bottom)/2;
if (buf[index_mid] == s_value)
{
return index_mid;
}
else if(buf[mid] > s_value)
{
return binary_search(buf, index_bottom, index_mid-1, s_value);
}
else
{
return binary_search(buf, index_mid+1, index_top, s_value);
}
}
int binary_search(int *buf, uint32_t buf_size, int s_value)
{
uint32_t index_bottom = 0;
uint32_t index_top = buf_size-1;
uint32_t index_mid = buf_size/2 - 1;
while (index_top-index_bottom > 1)
{
if (s_value < buf[index_mid])
{
index_top=index_mid;
}
else if(s_value>buf[index_mid])
{
index_bottom=index_mid;
}
else
{
return index_mid;
}
index_mid=(index_bottom+index_top)/2;
}
return -1;
}
3 分段线性插值
分段线性插值法,将目标样本点区间划分为多个区间[x,x+1],分别在每个区间上作一次线性方程,计算x点的插值时,只需用到左右的两个坐标点,计算量与坐标点个数n无关。
假设某一区间两个节点为(x1,y1)和(x2,y2),则该区间上的一次线性方程可以这样表示:
F
1
=
x
−
x
2
x
1
−
x
2
f
(
x
1
)
+
x
−
x
1
x
2
−
x
1
f
(
x
2
)
F1 = \frac{x-x2} {x1-x2} f(x1)+\frac{x-x1} {x2-x1}f(x2)
F1=x1−x2x−x2f(x1)+x2−x1x−x1f(x2)
线性坐标图
以上图为例,利用方程式证明。
斜
率
:
k
=
(
y
2
−
y
1
)
(
x
2
−
x
1
)
斜率:k = \frac{(y2-y1)} {(x2-x1)}
斜率:k=(x2−x1)(y2−y1)
线
性
方
程
:
y
−
y
1
=
k
(
x
−
x
1
)
线性方程:y-y1 = k (x-x1)
线性方程:y−y1=k(x−x1)
y
=
(
y
2
−
y
1
)
(
x
−
x
1
)
(
x
2
−
x
1
)
+
y
1
y = \frac{(y2-y1)(x-x1)} {(x2-x1)}+y1
y=(x2−x1)(y2−y1)(x−x1)+y1
y
=
x
−
x
1
x
2
−
x
1
y
2
+
(
1
+
x
−
x
1
x
1
−
x
2
)
y
1
y = \frac{x-x1} {x2-x1}y2+(1+\frac{x-x1} {x1-x2})y1
y=x2−x1x−x1y2+(1+x1−x2x−x1)y1
y
=
x
−
x
2
x
1
−
x
2
y
1
+
x
−
x
1
x
2
−
x
1
y
2
y = \frac{x-x2} {x1-x2} y1+\frac{x-x1} {x2-x1}y2
y=x1−x2x−x2y1+x2−x1x−x1y2
很显然,如果测量的RTD阻值刚好处于某一区间内,则需要使用插值法计算出当前温度值。
4 RTD实例
以PT00、PT1000为例,分别生成一个【-70℃ ~ +110℃】、【温度步进为0.5℃】的表(数组)。X轴表示阻值,y轴表示温度值,根据线性插值法,温度计算公式表示为:
y
=
[
x
−
x
2
x
1
−
x
2
y
1
+
x
−
x
1
x
2
−
x
1
y
2
]
×
s
−
h
y = [\frac{x-x2} {x1-x2} y1+\frac{x-x1} {x2-x1}y2]\times {s}-h
y=[x1−x2x−x2y1+x2−x1x−x1y2]×s−h
其中:
斜率 s = 0.5
初值 h = 70
const float PT100_CODE[361] =
{
72.335, 72.535, 72.735, 72.935, 73.134, 73.334, 73.534, 73.734, 73.934, 74.133,
74.333, 74.533, 74.732, 74.932, 75.131, 75.331, 75.53, 75.73, 75.929, 76.129,
76.328, 76.527, 76.726, 76.926, 77.125, 77.324, 77.523, 77.722, 77.921, 78.12,
78.319, 78.518, 78.717, 78.915, 79.114, 79.313, 79.512, 79.71, 79.909, 80.108,
80.306, 80.505, 80.703, 80.902, 81.1, 81.299, 81.497, 81.695, 81.894, 82.092,
82.29, 82.488, 82.687, 82.885, 83.083, 83.281, 83.479, 83.677, 83.875, 84.073,
84.271, 84.469, 84.666, 84.864, 85.062, 85.26, 85.457, 85.655, 85.853, 86.05,
86.248, 86.445, 86.643, 86.84, 87.038, 87.235, 87.432, 87.63, 87.827, 88.024,
88.222, 88.419, 88.616, 88.813, 89.01, 89.207, 89.404, 89.601, 89.798, 89.995,
90.192, 90.389, 90.586, 90.783, 90.98, 91.177, 91.373, 91.57, 91.767, 91.963,
92.16, 92.356, 92.553, 92.75, 92.946, 93.143, 93.339, 93.535, 93.732, 93.928,
94.124, 94.321, 94.517, 94.713, 94.909, 95.106, 95.302, 95.498, 95.694, 95.89,
96.086, 96.282, 96.478, 96.674, 96.87, 97.066, 97.261, 97.457, 97.653, 97.849,
98.044, 98.24, 98.436, 98.631, 98.827, 99.023, 99.218, 99.414, 99.609, 99.805,
100, 100.195, 100.391, 100.586, 100.781, 100.977, 101.172, 101.367, 101.562, 101.758,
101.953, 102.148, 102.343, 102.538, 102.733, 102.928, 103.123, 103.318, 103.513, 103.708,
103.903, 104.097, 104.292, 104.487, 104.682, 104.876, 105.071, 105.266, 105.46, 105.655,
105.849, 106.044, 106.238, 106.433, 106.627, 106.822, 107.016, 107.211, 107.405, 107.599,
107.794, 107.988, 108.182, 108.376, 108.57, 108.764, 108.959, 109.153, 109.347, 109.541,
109.735, 109.929, 110.123, 110.316, 110.51, 110.704, 110.898, 111.092, 111.286, 111.479,
111.673, 111.867, 112.06, 112.254, 112.447, 112.641, 112.835, 113.028, 113.221, 113.415,
113.608, 113.802, 113.995, 114.188, 114.382, 114.575, 114.768, 114.961, 115.155, 115.348,
115.541, 115.734, 115.927, 116.12, 116.313, 116.506, 116.699, 116.892, 117.085, 117.278,
117.47, 117.663, 117.856, 118.049, 118.241, 118.434, 118.627, 118.819, 119.012, 119.205,
119.397, 119.59, 119.782, 119.975, 120.167, 120.359, 120.552, 120.744, 120.936, 121.129,
121.321, 121.513, 121.705, 121.898, 122.09, 122.282, 122.474, 122.666, 122.858, 123.05,
123.242, 123.434, 123.626, 123.818, 124.009, 124.201, 124.393, 124.585, 124.777, 124.968,
125.16, 125.352, 125.543, 125.735, 125.926, 126.118, 126.309, 126.501, 126.692, 126.884,
127.075, 127.649, 127.458, 127.649, 127.84, 128.032, 128.223, 128.414, 128.605, 128.796,
128.987, 129.178, 129.37, 129.561, 129.752, 129.942, 130.133, 130.324, 130.515, 130.706,
130.897, 131.088, 131.278, 131.469, 131.66, 131.85, 132.041, 132.232, 132.422, 132.613,
132.803, 132.994, 133.184, 133.375, 133.565, 133.755, 133.946, 134.136, 134.326, 134.517,
134.707, 134.897, 135.087, 135.277, 135.468, 135.658, 135.848, 136.038, 136.228, 136.418,
136.608, 136.798, 136.987, 137.177, 137.367, 137.557, 137.747, 137.936, 138.126, 138.316,
138.506, 138.695, 138.885, 139.074, 139.264, 139.453, 139.643, 139.832, 140.022, 140.211,
140.4, 140.59, 140.779, 140.968, 141.158, 141.347, 141.536, 141.725, 141.914, 142.103,
142.293,
};
const float PT1000_CODE[361] =
{
723.345, 725.346, 727.346, 729.345, 731.344, 733.343, 735.341, 737.339, 739.337, 741.334,
743.331, 745.327, 747.324, 749.319, 751.315, 753.309, 755.304, 757.298, 759.292, 761.285,
763.278, 765.271, 767.263, 769.255, 771.247, 773.238, 775.229, 777.219, 779.21, 781.199,
783.189, 785.178, 787.166, 789.155, 791.143, 793.13, 795.117, 797.104, 799.091, 801.077,
803.063, 805.048, 807.033, 809.018, 811.003, 812.987, 814.97, 816.954, 818.937, 820.919,
822.902, 824.884, 826.865, 828.847, 830.828, 832.808, 834.789, 836.769, 838.748, 840.728,
842.707, 844.685, 846.663, 848.641, 850.619, 852.596, 854.573, 856.55, 858.526, 860.502,
862.478, 864.453, 866.428, 868.403, 870.377, 872.351, 874.325, 876.298, 878.271, 880.244,
882.217, 884.189, 886.16, 888.132, 890.103, 892.074, 894.044, 896.015, 897.985, 899.954,
901.923, 903.892, 905.861, 907.829, 909.797, 911.765, 913.732, 915.7, 917.666, 919.633,
921.599, 923.565, 925.53, 927.496, 929.461, 931.425, 933.39, 935.354, 937.317, 939.281,
941.244, 943.207, 945.169, 947.132, 949.093, 951.055, 953.016, 954.977, 956.938, 958.899,
960.859, 962.819, 964.778, 966.737, 968.696, 970.655, 972.613, 974.572, 976.529, 978.487,
980.444, 982.401, 984.358, 986.314, 988.27, 990.226, 992.181, 994.136, 996.091, 998.046,
1000, 1001.954, 1003.908, 1005.861, 1007.814, 1009.767, 1011.72, 1013.672, 1015.624, 1017.576,
1019.527, 1021.478, 1023.429, 1025.38, 1027.33, 1029.28, 1031.229, 1033.179, 1035.128, 1037.077,
1039.025, 1040.973, 1042.921, 1044.869, 1046.816, 1048.764, 1050.71, 1052.657, 1054.603, 1056.549,
1058.495, 1060.44, 1062.385, 1064.33, 1066.274, 1068.218, 1070.162, 1072.106, 1074.049, 1075.992,
1077.935, 1079.877, 1081.82, 1083.762, 1085.703, 1087.644, 1089.585, 1091.526, 1093.467, 1095.407,
1097.347, 1099.286, 1101.225, 1103.164, 1105.103, 1107.042, 1108.98, 1110.917, 1112.855, 1114.792,
1116.729, 1118.666, 1120.602, 1122.538, 1124.474, 1126.41, 1128.345, 1130.28, 1132.215, 1134.149,
1136.083, 1138.017, 1139.95, 1141.884, 1143.817, 1145.749, 1147.681, 1149.614, 1151.545, 1153.477,
1155.408, 1157.339, 1159.27, 1161.2, 1163.13, 1165.06, 1166.989, 1168.918, 1170.847, 1172.776,
1174.704, 1176.632, 1178.56, 1180.487, 1182.414, 1184.341, 1186.268, 1188.194, 1190.12, 1192.046,
1193.971, 1195.896, 1197.821, 1199.746, 1201.67, 1203.594, 1205.518, 1207.441, 1209.364, 1211.287,
1213.21, 1215.132, 1217.054, 1218.975, 1220.897, 1222.818, 1224.739, 1226.659, 1228.579, 1230.499,
1232.419, 1234.338, 1236.257, 1238.176, 1240.095, 1242.013, 1243.931, 1245.848, 1247.766, 1249.683,
1251.6, 1253.516, 1255.432, 1257.348, 1259.264, 1261.179, 1263.094, 1265.009, 1266.923, 1268.837,
1270.751,
};
int8_t binary_search(const float *buf, uint32_t buf_size, float s_value, uint32_t *out_data)
{
uint32_t index_bottom = 0;
uint32_t index_top = buf_size-1;
uint32_t index_mid = buf_size/2 - 1;
while (index_top-index_bottom > 1)
{
if (s_value < buf[index_mid])
{
index_top=index_mid;
}
else if(s_value>buf[index_mid])
{
index_bottom=index_mid;
}
else
{
*out_data = index_mid;
return 0x00;
}
index_mid=(index_bottom+index_top)/2;
}
*out_data = index_bottom;
return 0x01;
}
float resi_temp_calc(const float *code, uint32_t size, float resi)
{
int8_t ret = 0;
uint32_t value = 0;
float temp = 0.0f;
float x1 = 0.0f;
float x2 = 0.0f;
float y1 = 0.0f;
float y2 = 0.0f;
ret = binary_search(&code[0], size, resi, &value);
if (0x00 == ret)
{
temp = value*0.5f-70;
}
else if(0x01 == ret)
{
x1 = code[value];
y1 = value;
x2 = code[value+1];
y2 = value+1;
temp = (y1*(resi-x2)/(x1-x2) + y2*(resi-x1)/(x2-x1))*0.5f - 70;
}
else
{
}
return temp;
}
#include <stdio.h>
#include <stdint.h>
int main(char argc, char **argv)
{
float temp0 = 0.0f;
float temp1 = 0.0f;
temp0 = resi_temp_calc(&PT100_CODE[0], sizeof(PT100_CODE)/sizeof(float), 102);
printf("PT100 temp=%.2fC\r\n", temp0);
temp1 = resi_temp_calc(&PT1000_CODE[0], sizeof(PT1000_CODE)/sizeof(float), 1001.954);
printf("PT1000 temp=%.2fC\r\n", temp1);
return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)