gaoyang9992006 发表于 2020-10-24 14:02

我的硬件狂想作品-接触式电子体温计(NTC)

本帖最后由 gaoyang9992006 于 2021-11-1 09:33 编辑

       感谢贸泽电子提供这次活动赞助,让我体验到了村田制作所的这款NTC温度传感器,Murata Electronics MTHMR-N-0002A NTC热敏电阻评估板上板载了村田制作所的NXFT15XH103FA2B030NTC型热敏电阻,具有体积小,响应灵敏,精度高的特点,这得益于村田制作所多年的积累,以及提供了技术全面的技术手册。
这次活动参与的初衷是活动中提到了电子体温计,让我突然觉得这值得一试,以前生病测量体温用水银温度计,冰凉的难受,而非接触式的,又担心测的不准。这次看到了这么小的传感器(传感器只有芝麻粒那么大)觉得是时候寻找一个替代品了。
我参考部分可自动收回数据线与自动收回卷尺的想法,觉得这个传感器非常适合制作一款不用担心冰凉和水银破碎风险的电子体温计,同时还可以测量环境温度。
      再次感谢贸泽电子,之前我在贸泽电子下单买过好多次开发板与元件,发货及时,质量有保证,大的平台值得信赖。
测量提纲
第一步:查找资料,实现ADC测量
第二步:实现温度转换
第三步:实现体温计功能该方案的优点:该方案可以用于取代有危险的水银温度计,水银温度计冰凉,测量慢,由于特别冰凉,接触时候感觉很不舒适,升温较慢,测量周期长,该方案,利用该微型的温度传感器实现体温
的快速测量,体积较小,升温较快,响应灵敏。
-----------------------------------------------
第一步
在活动主页找到相关资料,关键内容如下所示,这是开发板的整体电路。

我们可以根据该图知道如何使用该开发板,输出为Vout=Vcc*(R/(R+Ref));

手册给出了计算公式


另外手册还提供了查表法

这里我利用新唐的ML51单片机进行ADC测量,该单片机具备12位的ADC外设。测量数值范围为0~0xFFF,也就是0到4095
由于这里是测量阻值大小,因此我们不考虑具体电压的读取,根据传感器开发板为传感器与一个6.2K标准电阻串联,因此
测量的结果R对应的ADC值应为4095*(R/(R+R0)),该值定义为ADCRESULT,则对应的R=((ADCRESULT*6.2)/(4095-ADCRESULT));单位KΩ
//***********************************************************************************************************
//File Function: ML51 series ADC software trigger on shot demo code
//***********************************************************************************************************
#include "ML51.h"
#include "math.h"
/******************************************************************************
The main C function.Program execution starts
here after stack initialization.
******************************************************************************/


void main ()
{
unsigned int ADCRESULT;
      float val;

/*
For UART0 P0.5 TXD output setting
* include gipo.c in Library for GPIO mode setting
* include uart.c in Library Setting for UART0
*/
    MFP_P31_UART0_TXD;                              // UART0 TXD use P0.5
    P31_QUASI_MODE;                                 // set P0.5as Quasi mode for UART0 trasnfer
    UART_Open(24000000,UART0_Timer3,115200);      // Open UART0 use timer1 as baudrate generate and baud rate = 115200
    ENABLE_UART0_PRINTF;
/*
ADCS to trig ADC convert
* include adc.c in Library for ADC initial setting
*/
    ADC_Open(ADC_SINGLE,1);                                        //Enable ADC_CH4
    ADC_ConvertTime(3,7);
//* find ADC result in ADC interrupt*/
                                          
    while(1)
    {
      set_ADCCON0_ADCS;                           // Software trig adc start
      while((ADCCON0|CLR_BIT7)==CLR_BIT7);         // wait ADCF = 1;
      ADCRESULT = (ADCRH<<4)+ADCRL;
      printf("\n ADC result = %d", ADCRESULT);
      Timer0_Delay(24000000,100,5000);
                        
                              val=((ADCRESULT*6.2)/(4095-ADCRESULT));
                              printf("\n val=%f K",val);
    }

}


代码如上所示。
例如测量结果为
ADC result = 2657
val=11.455770 K完成第一步,实现ADC测量,接下来根据公式实现温度读取

第二步:实现温度转换

根据手册提供的公式:R=R0 exp B(1/T - 1/T0);
其中R是待测电阻,R0是某个温度T0 K下的已知电阻,B是温度传感器常数
通过以上公式反推T = temp=1/((1/T0)+(log(RT/R0)/B));
代入数据测试,例如T0=25摄氏度时候R0=10K欧姆,主意以上代入实际计算时候要使用绝对温度,单位开尔文
经过测试上述公式可以完成验算,即,正确。
根据手册该型号的B常数在25到50度之间采用3380,25到80之间采用3428,25到85之间采用3434,25到100摄氏度之间采用3455.
为了方便,本项目采用3455计算。
程序如下
//***********************************************************************************************************
//File Function: ML51 series ADC software trigger on shot demo code
//***********************************************************************************************************
#include "ML51.h"
#include "math.h"
/******************************************************************************
The main C function.Program execution starts
here after stack initialization.
******************************************************************************/


void main ()
{
unsigned int ADCRESULT;
      float val;
      float temp;
      const float K=273.15;
      const float R0=10000.0;
      const float B=3455.0;
      float T0=25.0+K;
      unsigned int RT;
      unsigned int x;      
      
/*
For UART0 P0.5 TXD output setting
* include gipo.c in Library for GPIO mode setting
* include uart.c in Library Setting for UART0
*/
    MFP_P31_UART0_TXD;                              // UART0 TXD use P0.5
    P31_QUASI_MODE;                                 // set P0.5as Quasi mode for UART0 trasnfer
    UART_Open(24000000,UART0_Timer3,115200);      // Open UART0 use timer1 as baudrate generate and baud rate = 115200
    ENABLE_UART0_PRINTF;
/*
ADCS to trig ADC convert
* include adc.c in Library for ADC initial setting
*/
    ADC_Open(ADC_SINGLE,1);                                        //Enable ADC_CH4
    ADC_ConvertTime(3,7);
//* find ADC result in ADC interrupt*/
                                          
    while(1)
    {
      set_ADCCON0_ADCS;                           // Software trig adc start
      while((ADCCON0|CLR_BIT7)==CLR_BIT7);         // wait ADCF = 1;
      ADCRESULT = (ADCRH<<4)+ADCRL;
      printf("\n ADC result = %d", ADCRESULT);
      Timer0_Delay(24000000,100,5000);
                        
                              val=((ADCRESULT*6.2)/(4095-ADCRESULT));
                              printf("\n val=%f K",val);
                              x=(val*1000.0);
                              printf("\n x=%d ",x);                        
                              RT=x;
                              temp=1/((1/T0)+(log(RT/R0)/B));
                              printf("\n temp=%.2f",temp-K);




gaoyang9992006 发表于 2020-10-24 14:26

本帖最后由 gaoyang9992006 于 2020-10-24 14:29 编辑


在串口助手打印出测量结果,完全正确。
用手加热,温度立马升高,该温度传感器由于体积特别小,跟个大头针一样,加热和散热速度非常快,可以很快的响应环境温度变化。

测试电路连接图。效果非常好。

gaoyang9992006 发表于 2020-10-24 14:32

先占楼,后面一步一步实现样机,接下来就是增加测量体温的逻辑:每个测量周期内将会记录最高温度,这个思路和水银体温计是原理一样的,只不过把危险的水印换成了这个电子的传感器。当温度升高时候,保持最大记录,直到下一个测量周期被触发,重新记录新的最大值。

gaoyang9992006 发表于 2020-10-24 15:44

本帖最后由 gaoyang9992006 于 2020-10-24 18:36 编辑


这是测量嘎子窝体温的结果36.62
人体的正常体温是36.3~37.2℃。


通过Excel绘制出手册给的查表值。
通过6阶曲线拟合


不过这是通过温度求R值的,我们是测量温度,所以需要知道通过R值求温度的拟合公式
交换坐标轴后,发现拟合的很不好,算了,还是用推荐的公式。之后再研究如何利用这些给定的点校准。

gaoyang9992006 发表于 2020-10-25 00:28

本帖最后由 gaoyang9992006 于 2020-10-26 09:44 编辑

优化一下源代码
//***********************************************************************************************************
//File Function: ML51 series ADC software trigger on shot demo code
//***********************************************************************************************************
#include "ML51.h"
#include "math.h"
/******************************************************************************
The main C function.Program execution starts
here after stack initialization.
******************************************************************************/

#define K 273.15
#define T0 (25.0+K)
#define R0 10000.0
#define B 3455.0      

void main ()
{
unsigned int ADCRESULT;
      float Rval;
      float temp;

/*
For UART0 P0.5 TXD output setting
* include gipo.c in Library for GPIO mode setting
* include uart.c in Library Setting for UART0
*/
    MFP_P31_UART0_TXD;                              // UART0 TXD use P0.5
    P31_QUASI_MODE;                                 // set P0.5as Quasi mode for UART0 trasnfer
    UART_Open(24000000,UART0_Timer3,115200);      // Open UART0 use timer1 as baudrate generate and baud rate = 115200
    ENABLE_UART0_PRINTF;
/*
ADCS to trig ADC convert
* include adc.c in Library for ADC initial setting
*/
    ADC_Open(ADC_SINGLE,1);                                        //Enable ADC_CH4
    ADC_ConvertTime(3,7);
//* find ADC result in ADC interrupt*/
                                          
    while(1)
    {
      set_ADCCON0_ADCS;                           // Software trig adc start
      while((ADCCON0|CLR_BIT7)==CLR_BIT7);         // wait ADCF = 1;
      ADCRESULT = (ADCRH<<4)+ADCRL;
      printf("\n ADC result = %d", ADCRESULT);
      Timer0_Delay(24000000,100,5000);
                        
         Rval=1000*((ADCRESULT*6.2)/(4095-ADCRESULT));
         printf("\n Rval=%d Ohm",(unsigned int)Rval);
         temp=1/((1/T0)+(log(Rval/R0)/B));
         printf("\n temp=%.2f",temp-K);
         printf("\n----------------");                                       
    }

}

gaoyang9992006 发表于 2020-10-27 16:39

本帖最后由 gaoyang9992006 于 2020-11-17 17:36 编辑


这是该作品的原理图,很简单,只需要一个超低功耗单片机,1片3V纽扣电池或者3.7V锂电池,一个数码管显示屏,1个按钮,一个电阻,1个NTC电阻。
而设计的产品外观如下所示

采用自动收线设计,传感器探头为一条较细的导线连接,可以收入设备内部,拉出线缆后,可以有约一米长,按下收回按键,线缆自动收回盒子内部。
线缆可以采用类似耳机线缆那种线缆制作,韧性强,柔软。
还可以设置若干LED灯,超出正常体温显示红色,正常体温范围内显示绿色。

将串口打印改成OLED屏幕显示






gaoyang9992006 发表于 2020-10-27 23:41

https://www.bilibili.com/video/BV1Tr4y1w7vz/
视频放到B站了。

hjl2832 发表于 2020-10-28 09:03

不错不错

598330983 发表于 2020-10-28 09:17

老高研究的透彻,多谢分享。

gaoyang9992006 发表于 2020-11-5 20:35

再次更新该贴,将电阻转换成温度的函数单独摘出来,作为一个独立的头文件,方便移植到其他平台调用。

NTC.h

#define K 273.15
#define T0 (25.0+K)
#define R0 10000.0
#define B 3455.0       

/*
电阻值换算到温度
adc_val:NTC当前的阻抗值,单位欧姆
返回值:摄氏度
*/

float Res_to_Tem(float adc_val)
{
        float temp;
        temp=1/((1/T0)+(log(adc_val/R0)/B));
        return temp-K;
}

gaochy1126 发表于 2020-11-13 09:30

gaoyang9992006 发表于 2020-11-5 20:35
再次更新该贴,将电阻转换成温度的函数单独摘出来,作为一个独立的头文件,方便移植到其他平台调用。

NTC. ...

这个有阻抗偏移吗?楼主是怎么进行矫正的?内部有矫正的寄存器吗?

gaoyang9992006 发表于 2020-11-13 09:55

gaochy1126 发表于 2020-11-13 09:30
这个有阻抗偏移吗?楼主是怎么进行矫正的?内部有矫正的寄存器吗?

不需要,单片机ADC内部一般都有输入缓冲器。

qbwww 发表于 2020-11-13 10:14

围观大佬

734774645 发表于 2022-5-23 15:14

学习学习。

streetkid 发表于 2022-5-23 15:41

干的漂亮
页: [1]
查看完整版本: 我的硬件狂想作品-接触式电子体温计(NTC)