|
注:下面是我在C#写的一个查表类,思路是:
1、用工具软件(如EXCE)或自已画一个(以前我是这样子做的)温度/输入电压曲线表。然后对曲线进行线性化(可以在纸上用手画,也可以用EXCE跟据相应的数据自动生成,并且EXCE能对曲线自动进行线性化)。
2、写代码
所用到的数据结构:
先建立两个一维数组,分别对应温度- double linesT[14] ; 输入电压 - double linesV[14]。
注意:这两个数组有着一一对应的关系,也就是 linesT[3] 对应linesV[3] 的值;为什么数组的大小为15呢,是因为我选用的热电阻的 温/压曲线(是由温/阻曲线变换而来)线性化成14段直线。
然后建立一个用于判断查表的值所在那个区间的 结构体
public struct CompareResult
{
public SearchResult search_result;
public int Position; // 找到 输入 “数”在数组中的序号。
}
和用于表示查找结果的 enum
public enum SearchResult { Less_Than_linesV0, Equation, Less_Than_linesVi, ComeUpTo_limesV14 };
主要代码:
// 用一个for 循环来遍历 linesV数组,找到输入电压Vi所在 温/压曲线的区间,然后把反映 Vi 的位置的数据存放在 一个 CompareResult 结构体中。
//然后用一个电压转换温度的方法把电压转为温度值。
全部的类代码如下;已经过验证,可以精确到0.1度.由于选用的热电阻的范围是0至100度 和 在10位A/D下只有 698.368的分辨率.所以ADC的每个计数点有大约“0.14c”的分辨率. 减去其它的影响,实际可以达 0.2c 的分辨率.
using System;
namespace ROC
{
public enum SearchResult { Less_Than_linesV0, Equation, Less_Than_linesVi, ComeUpTo_limesV14 }; //
public struct CompareResult
{
public SearchResult search_result;
public int Position; // 找到 输入 “数”在数组中的序号。
}
/// <summary>
/// NTC10K 的摘要说明。
/// 4.27V - 0c ; 0.86V - 100c
/// MCU/AD为10位AD,所以AD的分辨率为2的10次方 = 1024;范围 = 0V(0) - 5V(1024)
/// 如下公式可计算出用该MCU和该热电阻测试温度的分辨率 = (4.27V - 0.86V)/5V * 1024 = 698.368
/// 这意味着在ADC的每个计数点有大约“0.14c”的分辨率。 // (|0 - 100|) / 698.368
///
/// </summary>
public class NTC10K
{
double[] linesV;
double[] linesT;
public NTC10K()
{
//
// TODO: 在此处添加构造函数逻辑
//
linesV = new double[15]{ 0.86d ,1.00d ,1.15d ,1.33d ,1.57d ,1.81d ,2.06d ,2.34d ,2.64d ,2.93d ,3.23d ,3.56d ,3.83d ,4.07d ,4.27d };
linesT = new double[15]{ 100d ,93d ,86d ,79d ,71d ,64d ,57d ,50d ,43d ,36d ,29d ,21d ,14d ,7d ,0d };
}
/// <summary>
/// 返回值 = -1 表示没找到 ; = i(0 至 14), 表示 i < 输入的数 <= V[i+1]
/// </summary>
/// <param name="Vi"></param>
/// <returns></returns>
void Search_LinesV(double Vi,ref CompareResult cr)
{
for(int i=0;i<15;i++)
{
if ( Vi < linesV)
{
if (i == 0)
{
cr.search_result = SearchResult.Less_Than_linesV0;
break;
}
else
{
cr.search_result = SearchResult.Less_Than_linesVi;
cr.Position = i;
break;
}
}
else if (Vi == linesV)
{
cr.search_result = ROC.SearchResult.Equation;
cr.Position = i;
break;
}
else if (Vi > linesV)
{
if (i == 14)
{
cr.search_result = ROC.SearchResult.ComeUpTo_limesV14;
break;
}
}
}
}
public double Convert_V_To_T(double Vi)
{
double T = -1;
CompareResult cr = new CompareResult();
Search_LinesV(Vi,ref cr);
switch(cr.search_result)
{
case ROC.SearchResult.Less_Than_linesV0:
T = linesT[0];
break;
case ROC.SearchResult.Equation:
T = linesT[cr.Position];
break;
case ROC.SearchResult.Less_Than_linesVi:
int i = cr.Position;
T = linesT[i-1] + (linesT - linesT[i-1]) * (Vi - linesV[i-1])/(linesV - linesV[i-1]) ;
break;
case ROC.SearchResult.ComeUpTo_limesV14:
T = linesT[14];
break;
}
return T;
}
/// <summary>
/// 热水压力
/// </summary>
/// <param name="V"></param>
/// <returns></returns>
public double Convert_V_To_KPa_HotWater(double V)
{
return 0;
}
/// <summary>
/// 燃气压力
/// </summary>
/// <param name="V"></param>
/// <returns></returns>
public double Convert_V_To_KPa_GasFired(double V)
{
return 0;
}
}
} |
|