搜索
bottom↓
回复: 22

使用RC冲放电的温度计

[复制链接]

出0入0汤圆

发表于 2008-4-27 07:26:37 | 显示全部楼层 |阅读模式
______
IN)----|__100_|-------
             ______       |     | |
REF)----|__10K_|------------| |---(GND)
             ______       |     | |
RX)---------|__RT _|-------


(原文件名:测温.jpg)
使用夏普传真上拆的LCD的测试图;
这是主程序,不含RT转换函数和LCD显示,稍加修改就能用:
#include <avr/io.h> //MCU为ATmega48
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/sleep.h>

#include "lcd.h"
#include "lcdTimer.h"
#include "r2t.h"

#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

//电阻测试引脚
#define RESPOR PORTD
#define RESDDR DDRD
#define RESPIN PIND

#define INP 2
#define RXP 1
#define RFP 0

//开始计时
#define STARCT() TCCR1B = 0x01;        //1=不分频;2=8分频内部计数器
unsigned char buff[17];

#define TESTN        10        //测试平均数

int Vout;

ISR(SIG_OUTPUT_COMPARE0A)
{
        uint ms;
        ms++;
        if(ms > Vout)  LCD_write_char(15,'1');
        else  LCD_write_char(15,'0');
       
        if(ms > 5000) ms = 0;
                       
}
ISR(SIG_INTERRUPT0)
{
        //停止计数
        TCCR1B = 0;       
        EIMSK &=  ~_BV(INT0);                //禁用外部中断0
}
void resinit(void)
{
        ///////////////////////////////////////////
        /////////////电阻测试初始化////////////////
       
        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
       
        //定时器设置
        TCCR1A = 0x00;
        //TCCR1B = 0x02;        //8分频内部计数器
        TCCR1C = 0x00;
        //TIMSK1 |= _BV(TOIE1);        //开定时中断;
        TIFR1 |= _BV(TOV1);                //清定时中断;
       
        //输入中断设置
        EICRA = 0x2;                //外部中断0为引脚下降沿触发
        EIFR  |=  _BV(INT0);
        EIMSK |=  _BV(INT0);                //允许外部中断0
}
void testrf(void)
        //测试基准电阻
{
        ////////////////电阻时间测试//////////////////

        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        //放电
        RESDDR |= _BV(INP);
        RESPOR |= _BV(INP);
        Delay_10ms(50);
        RESDDR &= ~_BV(INP);
        RESPOR &= ~_BV(INP);
                       
        //清零
        TCNT1 = 0;
               
        //开外部中断
        EIMSK |= _BV(INT0);
        EIFR  |=  _BV(INT0);
        EIMSK |=  _BV(INT0);                //允许外部中断0
               
        //充电
        RESPOR &= ~_BV(RFP);
        RESDDR |= _BV(RFP);
       
        //开始计数
        STARCT();
               
        //等待转换结果
        while((RESPIN & _BV(INP)))
        {
                set_sleep_mode(0);
        }
}       
void testrx(void)
        //测试输入电阻
{
        ////////////////电阻时间测试//////////////////

        //端口设置为输入
        RESPOR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        RESDDR &= ~(_BV(RFP) | _BV(INP) | _BV(RXP));
        //放电
        RESDDR |= _BV(INP);
        RESPOR |= _BV(INP);
        Delay_10ms(50);
        RESDDR &= ~_BV(INP);
        RESPOR &= ~_BV(INP);
                       
        //清零
        TCNT1 = 0;
               
        //开外部中断
        EIMSK |= _BV(INT0);
        EIFR  |=  _BV(INT0);
        EIMSK |=  _BV(INT0);                //允许外部中断0
               
        //充电
        RESPOR &= ~_BV(RXP);
        RESDDR |= _BV(RXP);
       
        //开始计数
        STARCT();
               
        //等待转换结果
        while((RESPIN & _BV(INP))) set_sleep_mode(0);
}       
int main(void)
{
        timers_init();                //初始化系统定时器
    LCD_init();                 //初始化LCD1602
        write_command(0x01);  //清屏--对应清屏指令
        Delay_10ms(2);
        resinit();                        //初始化电阻测试
        sei();
       
        while(1)
        {
                float tmprf,tmprx,tmp;
                uint bufrf[TESTN],bufrx[TESTN],h,l;
                uchar i,tn;
               
                if(++tn >=TESTN) tn = 0;
                testrf();
                bufrf[tn] = TCNT1;
               
                testrx();
                bufrx[tn] = TCNT1;
               
               
                tmprf = 0;
                for(i=0;i<TESTN;i++)
                {
                        tmprf += bufrf;
                }
                tmprf /= TESTN;
               
                tmprx = 0;
                for(i=0;i<TESTN;i++)
                {
                        tmprx += bufrx;
                }
                tmprx /= TESTN;
                tmp = (tmprx * 10)/tmprf;
               
                h = r2t(tmp)/10;
                l = r2t(tmp)%10;
               
//                sprintf(buff,"R=%d,T=%d.%dC",(int)(tmp*10),h,l);
                sprintf(buff,"O=%d,T=%d.%d   ",Vout,h,l);
            LCD_write_string(0,buff);
               
//                Vout = pid(r2t(tmp),Vout,200);
//                if(Vout >=5000) Vout = 5000;
//                if(Vout <=0) Vout=0;
        }
}

出0入0汤圆

发表于 2008-4-27 07:47:28 | 显示全部楼层
以前在430上用过,是一个例程。

出0入46汤圆

发表于 2008-4-27 11:38:17 | 显示全部楼层
顶!

出0入0汤圆

发表于 2008-4-28 14:18:11 | 显示全部楼层
我也用过RC测温的,觉得还蛮精准的。

出0入0汤圆

发表于 2008-4-28 14:46:49 | 显示全部楼层
衡水的?
我是河北的

出0入0汤圆

 楼主| 发表于 2008-4-28 18:59:19 | 显示全部楼层
遇到老乡了!呵呵;
这一个在室温段可以接近0.2℃的精度,是一个产品的测试代码

出0入0汤圆

发表于 2008-4-29 12:57:01 | 显示全部楼层
430加pt1000可以作0.1度,我以前作暖气表时就是用的这种方法

出0入0汤圆

 楼主| 发表于 2008-4-30 07:07:26 | 显示全部楼层
有一些MCU本身有硬件的RC型AD,可以简化测试,我得这个程序使用的中断处理的,电阻较小的时候误差较大,在产品中已经修改了,是用IO直接驱动LCD的,在2。5-3。6V可以获得比较好的效果和精度,以前直接驱动LED时会有测量干扰比较大的情况,现在没有试过;
用NTC最大的特点是价格便宜,PT1000的精度很高稳定性也好,只是最便宜的也要十几,NTC国产的1%精度精度约0.3℃在20只对比时基本在0.2℃以下,采用进口的0.5%的NTC(要几元一只)接近精度0.1℃,当然工作于200℃以下还行如果到近300的时候几个小时之后就不准了,相比PT1000稳定性相差太多了,估计楼上的朋友用于暖气表时温度不会太高,可以考虑用NTC降低成本,在电线比较长的时候NTC也有较小的误差,PT的要达到精度需要考虑补偿了

出0入0汤圆

发表于 2008-4-30 10:44:16 | 显示全部楼层
请教下,对有 AD 的 AVR 来说,RC 振荡测温、RC 充放电测温和 AD 转换测温的优缺点是什么?

出0入0汤圆

 楼主| 发表于 2008-4-30 12:13:30 | 显示全部楼层
AVR的AD大多是10位的,注定了测试的分辨率,假设传感器是可以变换为线性输出的电压信号,那在-20+80℃的测温范围可以得到0.1的分辨率,如果再宽的话就不行了,至少需要想些办法;RC振荡型会对环境有较高的要求,尤其是精密的电容器,也就是温度系数了,再者他需要其他元件配合,廉价的555可以做到,只是精度很低,精度高的价格又高,有时不如直接用高分辨率的ADIC;RC冲放电是比较折中的方法,精度主要依靠基准电阻和定时器,速度会比较慢,对于较小的电阻会有较大的误差,主要来源是IO电阻,会和环境电源电压有关;还有就是电容的吸收误差了,通常CBB的小些

出0入0汤圆

发表于 2008-4-30 20:24:02 | 显示全部楼层
以前好像也玩过一下,一般家电用还是不错的....

出0入0汤圆

发表于 2009-10-30 11:42:44 | 显示全部楼层
记号

出0入0汤圆

发表于 2009-10-30 12:57:27 | 显示全部楼层
用傳感器做的,精度不好,為1攝氏度,有更精度更高的傳感器没?哪位大哥推薦下?

出0入0汤圆

发表于 2009-10-30 14:24:07 | 显示全部楼层
这照片拍的跟老录像带截图似的,,还有啊就是rx是做什么用的?(我想起来了是串口的接收端?)

出0入0汤圆

发表于 2009-10-30 14:40:09 | 显示全部楼层
rx应当就是待测电阻吧,热敏电阻。

出0入0汤圆

发表于 2013-7-24 22:12:20 | 显示全部楼层

出0入0汤圆

发表于 2013-8-2 13:03:27 | 显示全部楼层
请问可以用2个IO做吗?  用2个IO做时,也就造成不同的输入电阻,会不会影响结果?
我的实验会有影响,不知大家有没这样做过?

出0入0汤圆

发表于 2015-4-20 13:52:47 | 显示全部楼层
好帖子,收藏了

出0入0汤圆

发表于 2015-5-12 20:48:29 | 显示全部楼层
如果传感器断开了呢?有没有做处理?

出0入0汤圆

发表于 2016-2-26 12:26:06 | 显示全部楼层
楼主可以上传一下电路图吗,在下不胜感激。

出0入0汤圆

发表于 2017-12-27 18:18:45 | 显示全部楼层
记号。。。。。。

出0入0汤圆

发表于 2017-12-28 12:20:25 | 显示全部楼层
学习,谢谢!!!

出0入53汤圆

发表于 2022-7-11 15:55:26 | 显示全部楼层
没看懂 能否解释一下过程
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 -- 东莞阿莫电子网站 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2023-1-30 00:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表