cityfuture 发表于 2013-10-27 13:32:59

电桥测ntc,ad读到的值如何转换为温度

电桥测ntc,ad读到的值如何转换为温度?
MF                             52        103                      H        3435                 F                    A
NTC热敏电阻        环氧系列        电阻值        阻值允差        B值              B值允差        B值类别
                                        10KΩ        ±5%              3435K        ±1%                B25/50
程序应该怎么写

gzhuli 发表于 2013-10-27 14:31:57

基本参数:
B = 3435
R0 = 10K
T0 = 273.15 + 25

预先计算好常数:
r∞ = R0 * e^(-B / T0)

测出NTC电阻值R,通过下式即可换算为温度T:
T = B / ln(R / r∞) - 273.15

如果要求精度较高,还要对T做多点曲线拟合校正。

cityfuture 发表于 2013-10-28 14:16:46

gzhuli 发表于 2013-10-27 14:31 static/image/common/back.gif
基本参数:
B = 3435
R0 = 10K


这个算法在单片机中是如何表达呢,有示例程序吗

amxx 发表于 2013-10-28 14:29:47

这是我在网上看到的,测试可以用
#define TEMP_B 3470.0            //热敏电阻的B值
#define TEMP_R 5000.0            //25度时的电阻值

float NTC_Cal_Temp(float R_Value)
{
        float x=0;
        float y=0;

        x = log((R_Value/TEMP_R));
y = 1/(x/TEMP_B+1/298.15);
y -= 273.15;

return y;
}

float NTC_Cal_R(uint32 ADC_Data)
{
float R_Value;
float Vr;

Vr = (ADC_Data / 4096.0) * 6.6;//得到电阻上的分压
R_Value = (4700.0 * Vr)/(5 - Vr);
return R_Value;

}

techbaby 发表于 2013-10-28 14:32:50

我都是查表的。

先在excel内算好电压对应的采样值(相隔1度),然后再做简单的线性计算。

techbaby 发表于 2013-10-28 14:34:36

/*
*******************************************************************************
*                           ntc对应采样电压值数组
*------------------------------------------------------------------------------
* 注释第一行:对应温度
*-------------------------------------------------------------------------------
* 测量温度范围定为-10℃-150℃(可能会有零点几的数据出入)
********************************************************************************
*/
static int16u code ntc_adc[] =
{      
        62454 ,   61415 ,60359 ,59286 ,58199 ,57098 ,55985 ,54862 ,
        53730 ,   52592 ,51448 ,50302 ,49153 ,48005 ,46858 ,45715 ,
        44576 ,   43444 ,42320 ,41205 ,40101 ,39009 ,37930 ,36865 ,
        35816 ,   34783 ,33767 ,32769 ,31790 ,30829 ,29889 ,28968 ,
        28068 ,   27189 ,26331 ,25494 ,24678 ,23883 ,23110 ,22358 ,
        21627 ,   20916 ,20226 ,19557 ,18908 ,18279 ,17669 ,17078 ,
        16506 ,   15952 ,15416 ,14898 ,14396 ,13912 ,13444 ,12991 ,
        12554 ,   12132 ,11724 ,11331 ,10951 ,10584 ,10230 ,   9889 ,
       9559 ,    9241 ,   8935 ,   8639 ,   8353 ,   8078 ,   7813 ,   7557 ,
       7310 ,    7072 ,   6842 ,   6620 ,   6407 ,   6201 ,   6002 ,   5810 ,
       5625 ,    5446 ,   5274 ,   5108 ,   4948 ,   4793 ,   4644 ,   4500 ,
       4361 ,    4227 ,   4098 ,   3973 ,   3852 ,   3735 ,   3623 ,   3514 ,
       3409 ,    3308 ,   3210 ,   3115 ,   3024 ,   2936 ,   2850 ,   2768 ,
       2688 ,    2611 ,   2536 ,   2464 ,   2394 ,   2327 ,   2262 ,   2198 ,
       2137 ,    2078 ,   2021 ,   1966 ,
};                                                                                       
#define NTC_ADC_ARRAY_NUM (sizeof(ntc_adc)/sizeof(int16u))
#define INDEX_MAX       NTC_ADC_ARRAY_NUM-2          /* 数组下标的最大可用取值,对应 80℃采样值下标 */
#define INDEX_MIN       2                            /* 数组下标的最小可用取值,对应-10℃采样值下标 */
#define TEMPER_REF      -15                     /* 温度基准点,即下标为0时对应的温度                    */
#define TEMPER_LAST   100                     /* 温度最后值,即数组最后一个对应的温度      */

/*
*******************************************************************************
* 函数名称: search_data()
* 输 入: search_value查找基准值
* 输 出:
* 作 者:
* 日 期: 2010.08.11
* 功能描述: 二分查找adc采样值
*------------------------------------------------------------------------------
*注   意:
*    1.    返回值为查找表格中第一个小于查找值(search_value)的下标;
*    2.    查找值(search_value)大于查找表格中最大值时,返回1
*          查找值(search_value)小于查找表格中最小值时,返回查找表格数量,即最大下标+1
*******************************************************************************
*/
static int16u search_data(int16u search_value)
{
   register int16umax = NTC_ADC_ARRAY_NUM - 1;
   register int16umin = 1;
   register int16umid;

   while(min <= max)
   {
       mid = (max + min) / 2;

       if(search_value > ntc_adc)
       {
         max = mid - 1;
       }
       else
       {
         min = mid + 1;
       }
   }

   return min;
}

/*
*******************************************************************************
* 函数名称: temper_calc()
* 输 入: index       数组下标
*         adc0_valuead滤波后的采样值
* 输 出: ntc温度测量值
* 作 者:
* 日 期: 2010.10.26
* 功能描述: 温度计算(分段线性插值算法)
*******************************************************************************
*/
static int16s temper_calc(int16u index, int16u adc0_value)
{
        if (index > INDEX_MAX || index < INDEX_MIN)
        {
                return TEMPER_ERROR;        //返回错误采样温度
        }
//   else if (index < INDEX_MIN)
//   {
//         return -150;      //返回-15.0℃
//   }
        else
        {
       /*************************************************
      === 直线近似计算 ===
      y1 = kx1+b       x <-> adc_value
      y2 = kx2+b       y <-> temper
      yn = kxn+b
            y2 - y1   yn - y1
      k= --------- = ---------
            x2 - x1   xn - x1
            (y2 - y1)*(xn - x1)
      yn = --------------------- + y1
                  (x2 - x1)
      *************************************************/

       int16s temper;
                                       
       temper= 10*(ntc_adc - adc0_value);   //放大10倍,temper放大10倍
       temper /= (ntc_adc - ntc_adc);//(xn - x1)
       temper += 10*(index + TEMPER_REF - 1);
      
       return temper;            
        }      
}

/*
*******************************************************************************
* 函数名称: adc0_battery_temper_calc()
* 输 入: adc0_sample_num            ad采样次数
*         adc0_sample_sum                ad采样总和
* 输 出:
* 作 者:
* 日 期: 2011.11.23
* 功能描述: 输出220V电压计算
*******************************************************************************
*/
void adc0_battery_temper_calc(int16u adc_value)
{                     
        register int16s temper;            // 温度值
        register int16u index;               // 查表下标值

        index= search_data(adc_value);                     // 取温度数组下标
        temper = temper_calc(index, adc_value);              // 温度计算

        battery_sample.battery_temper = temper;
}

gzhuli 发表于 2013-10-28 16:53:45

cityfuture 发表于 2013-10-28 14:16 static/image/common/back.gif
这个算法在单片机中是如何表达呢,有示例程序吗

4L的算法和我的公式是等效的,对于单片机来说鸭梨最大的就是log()和浮点除法运算,至于变通办法就只能自己发挥了。

NEWT 发表于 2013-10-29 17:23:06

拟合,分段线性或者用公式都可以

lmt50211 发表于 2013-10-27 13:33:00

本帖最后由 lmt50211 于 2013-10-31 13:57 编辑

uchar code table_temp[]=//定义温度数据表
{
42, 44, 45, 47, 49, 51, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 79,
81, 83, 85, 87, 90, 92, 94, 96, 99,101,103,106,108,110,112,115,117,119,122,124,
126,129,131,133,135,138,140,142,144,146,148,150,151,155,157,159,161,163,165,167,
169,171,173,174,176,178,180,182,183,185,187,188,190,191,193,194,196,197,199,200,
201,203,204,205,206,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223
};
//====================================================================
//===          温度转换函数          ===//
void temp_process(void)
{
        uchar i;
                r_temp_adc=adc_conver();      //ADC转换
        if(r_temp_adc>=223)            //开路判断
        {
                r_temp_room=100;
        }
        else if(r_temp_adc<=42)          //短路判断
        {
                r_temp_room=0;       
                }
        else
        {               
                     while(r_temp_adc>=table_temp)//比较采集AD值和表格温度点值,以判断出温度
                {
                        i++;       
                }       
                r_temp_room=i;            //查表计算温度值
        }       
}
这个方法精度比较低,表格也会比较大,但用于精度要求不高的地方还是很有优势的。

zxd08 发表于 2013-10-31 15:19:09

我觉得查表法最简单的了,把数值放到数组里对比一下就可以的了
页: [1]
查看完整版本: 电桥测ntc,ad读到的值如何转换为温度