【原创】RC充放电实现温度测量,前一段时间用过的,总结一下
首先检讨一下,用的cpu是本人很不喜欢的甚至讨厌的stc某一系列的,不为别的,就因为祖父祖母的,太扯淡了。言归正传。。
一提到温度测量,我们通常往往都会想到AD采样,但是在一些对测量精度要求不是很高的场合,
我们是不是可以换一种思路,抛弃AD,用其他的方式来实现呢,呵呵,正好接触到一个项目,所
以打算挑战一下,没错,就是RC充放电来实现温度测量。
先看一下基本的电路连接:
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626300HT8TBI.PNG
0 (原文件名:RC0.PNG)
图O:cpu拿出三个GPIO管脚,分别连接热敏电阻、100K高精电阻R1、泄流电阻R2,然后
通过一只电容器连接到GND。在这里电容器可以理解成一只小电池,而且还是一只可
充电电池。
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626301W17HD9.PNG
1 (原文件名:RC1.PNG)
图1:将RT设置成高阻太(输入),这样热敏电阻相当于断开(虚线),R1设置成输出,泄流电阻R2
设置成输出,如果cpu内部有上拉的话,最好打开,或者配置成强推挽,具体情况根据所选则的cpu而定。
这样R2给电容器充电,程序中一直检测R1管脚,直到R1管脚为高 while(R1 == 1);其实电容器被不一定被充满
电,只要满足R1管脚处的电平对于cpu来说是个高电平就足以。
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626302LAD5W7.PNG
2 (原文件名:RC2.PNG)
图2:保持RT继续高阻(断开),将R1设置成输出,输出0(低电平),R2设置成输入,此时电容通过100K
高精度电阻进行放电,程序中一直检测R2管脚,直到R2管脚为低电平 while(R2 == 0);记录时间T1,T1就是
电容器通过100k电阻放电所需要的时间。
图3:过程跟图一是一模一样的,给电容器充电(不一定充满),原因你懂的;
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626303I9IDGD.PNG
3 (原文件名:RC3.PNG)
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626304N0PM3O.PNG
4 (原文件名:RC4.PNG)
图4:将R1设置成高阻(断开),RT设置成输出,并且输出低电平,将R2设置成输出;此时电容器通过RT进行放电,程序中一直检测R2管脚,直到R2管脚为低电平 while(R2 == 0);记录时间T2,T2就是电容器通过100k电阻放电所需要的时间。
到此,我们就可以算出热敏电阻RT的阻值了:
http://cache.amobbs.com/bbs_upload782111/files_37/ourdev_626468STEK2Q.PNG
6 (原文件名:RC6.PNG)
001 /**
002 *青岛昊阳智能微控技术有限公司
003 *
004 * 温度采集
005 * 参考电阻为100 K
006 * @param
007 * unsigned char channel:采集哪个通道的温度
008 * NTP_OUTSIDE: 温控器外部温度探头
009 * NTP_INSIDE: 温控器内部探头
010 *@return
011 * ERROR_NTP_PARA_ERROR:参数错误
012 * ERROR_NTP_LOST_ERROR:温度探头丢失
013 * 非负:采集到的温度值
014 *
015 * @brief
016 * by kaka,2011,2,20
017 */
018
019
020 #define NTP_CHECK (1)
021 short ntp_100k_get_temperature(unsigned char channel){
022 double x, y, z;
023 unsigned long temperature_cnt_a, temperature_cnt_b;
024 unsigned char tmp;
025
026 if(channel == NTP_INSIDE){
027 SET_P2(7, IO_PORT_TRI_IN); //参考电阻 输入
028 SET_P2(6, IO_PORT_PULL_OUT); // 泄流电阻输出
029 SET_P4(4, IO_PORT_TRI_IN); // 热敏电阻输入
030
031 RFL0 = 0; //泄流电阻输出0
032 while(RE0); // 一直等到电容空
033
034 RFL0 = 1; //泄流电阻输出1
035 while(!RE0); // 一直等到电容满
036
037 SET_P2(7, IO_PORT_NO_PULL_IO); //参考电阻 输出
038 SET_P2(6, IO_PORT_TRI_IN); // 泄流电阻输入
039 SET_P4(4, IO_PORT_TRI_IN);// 热敏电阻输入
040
041 RE0 = 0; //参考电阻输出0, 给电容放电
042 temperature_cnt_a = 1;
043 while(RFL0){ // 等到电容电量放空
044 temperature_cnt_a ++;
045 if(temperature_cnt_a > NTP_MAX_COUNTER){
046 return ERROR_NTP_LOST_ERROR;
047 }
048 }
049
050 SET_P2(7, IO_PORT_TRI_IN); //参考电阻 输入
051 SET_P2(6, IO_PORT_PULL_OUT); // 泄流电阻输出
052 SET_P4(4, IO_PORT_TRI_IN); // 热敏电阻输入
053
054 RFL0 = 0; //泄流电阻输出0
055 while(RE0); // 一直等到电容空
056
057 RFL0 = 1; //泄流电阻输出1
058 while(!RE0); // 一直等到电容满
059
060 SET_P2(7, IO_PORT_TRI_IN); //参考电阻 输入
061 SET_P2(6, IO_PORT_TRI_IN); // 泄流电阻输入
062 SET_P4(4, IO_PORT_NO_PULL_IO);// 热敏电阻输出
063 RT0 = 0; //通过热敏电阻给电容充电
064 temperature_cnt_b = 1;
065 while(RFL0){
066 temperature_cnt_b ++;
067 if(temperature_cnt_b > NTP_MAX_COUNTER){
068 return ERROR_NTP_LOST_ERROR;
069 }
070 }
071 }else if(channel == NTP_OUTSIDE){
072 SET_P2(4, IO_PORT_TRI_IN); //参考电阻 输入
073 SET_P2(3, IO_PORT_PULL_OUT); // 泄流电阻输出
074 SET_P2(5, IO_PORT_TRI_IN); // 热敏电阻输入
075
076 RFL1 = 1; //泄流电阻输出1
077 while(!RE1); // 一直等到电容放满
078
079 SET_P2(4, IO_PORT_NO_PULL_IO); //参考电阻 输出
080 SET_P2(3, IO_PORT_TRI_IN); // 泄流电阻输入
081 SET_P2(5, IO_PORT_TRI_IN);// 热敏电阻输入
082
083 RE1 = 0; //参考电阻输出0, 给电容放电
084 temperature_cnt_a = 1;
085 while((RFL1)){ // 等到电容电量充满
086 temperature_cnt_a ++;
087 if(temperature_cnt_a > NTP_MAX_COUNTER){
088 return ERROR_NTP_LOST_ERROR;
089 }
090 }
091 SET_P2(4, IO_PORT_TRI_IN); //参考电阻 输入
092 SET_P2(3, IO_PORT_PULL_OUT); // 泄流电阻输出
093 SET_P2(5, IO_PORT_TRI_IN); // 热敏电阻输入
094
095 RFL1 = 1; //泄流电阻输出1
096 while(!RE1); // 一直等到电容满
097
098 SET_P2(4, IO_PORT_TRI_IN); //参考电阻 输入
099 SET_P2(3, IO_PORT_TRI_IN); // 泄流电阻输入
100 SET_P2(5, IO_PORT_NO_PULL_IO);// 热敏电阻输出
101 RT1 = 0; //通过热敏电阻给电容放电
102 temperature_cnt_b = 1;
103 while(RFL1){
104 temperature_cnt_b ++;
105 if(temperature_cnt_b > NTP_MAX_COUNTER){
106 return ERROR_NTP_LOST_ERROR;
107 }
108 }
109 }else{
110 return ERROR_NTP_PARA_ERROR;
111 }
112
113 x = 0;
114 y = temperature_cnt_a;
115 z = temperature_cnt_b*100000;
116 x = z / y;//热敏电阻除以参考电阻
117 tmp = ntp_100k_conversion(x);
118
119 return tmp;
120 } mark 不错 标记一下 MARK 楼主流程图做得不错 很不错,这样非常方便,而且体积小,不需要电桥和调理电路,一般精度的测量足够了。感谢楼主分享。 mark 这个用555是不是会好点,有人说STC的输入触发器有问题(仅是听说),如果接比较器的话就不用校准了 mark mark 很形象.我也用过,但是对于热敏电阻的标准值,一直没环境测量,所以变得很被动了. cool 图很给力 图片很不错 有矛盾的地方,看了晕。 根据顶楼的公式 RT*T2 = R1*T1,R1*T1 是一个固定值,当 RT 变大的时候放电时间会变长,因此 T2 变大,RT*T2 也会变大,这个公式有问题? 记号!! 文章里有几处输入和输出写反了,望楼主编辑一下方便阅读 :) 想问一下,图怎么画的 强~ mark 好东西,支持 mark mark 回复【18楼】wajlh
-----------------------------------------------------------------------
图就是用visio画的 回复【15楼】atommann
-----------------------------------------------------------------------
呵呵,搞错了,谢谢提醒。。 标记 想问下楼主,定时器如何取值比较合适呢·!
如果一直在主程序中跑,中断后,会影响电容放电时间计数吗? 这个要用STC12系例来做吧? mark 图不错! 不错啊,喜欢! 图蛮给力的,不过这个方法哪里看见过。。。 楼主是通过电容放电的时间来测的,好像大家一般都是测电容充电时间的,先充电再测放电时间,这过程中会不会因为电容自漏电造成误差?
我也试验过,也通过读取16位定时器的值来验证,不过我是程序菜鸟,目前只会汇编,不会处理16进制的乘除法,特别是要求精度的情况下还要有余数,所以我只是看看定时器的值判断一下而已,通过串口把定时器的值发回电脑串口软件,读回的定时值很稳定,偶尔偏差一个值,用手捏着传感器读数就变了好多,, "002 *青岛昊阳智能微控技术有限公司 "
it is incredibly complicated.
you can code it much simpler. mark 回复【34楼】millwood0
-----------------------------------------------------------------------
Yes, I think “hanyo” better。。 这个真的很不错,以前做过和这个一样的,检测气敏电阻阻值的,用AVR做的,也是这个原理。
图画得很到位。 STC做不到的。 不错,标记一下 标记一下,以后用的到 记录时间T2,T2就是电容器通过100k电阻放电所需要的时间。
应该是"记录时间T2,T2就是电容器通过RT电阻放电所需要的时间。" 哇哦,虽然不是啥新东西。。。不过那几个图画得很好。赞~
【34楼】 millwood0 说的对,代码太过复杂了。
而且,对于有三态IO的单片机来说,两个IO就够了,一个Rt,一个电容,足矣。
说到底都是AD转换。只是形式不同而已。
话说不带AD的单片机也多数都带个比较器,用它做更好。 回复【15楼】atommann
根据顶楼的公式 rt*t2 = r1*t1,r1*t1 是一个固定值,当 rt 变大的时候放电时间会变长,因此 t2 变大,rt*t2 也会变大,这个公式有问题?
-----------------------------------------------------------------------
RT/T2 = R1/T1, 你弄反了. 两个IO精度会下降的. 必须用同一个IINPUT检测"高",用同一个INPUT检测"低",否则精度很差. 回复【43楼】gwdong
回复【15楼】atommann
根据顶楼的公式 rt*t2 = r1*t1,r1*t1 是一个固定值,当 rt 变大的时候放电时间会变长,因此 t2 变大,rt*t2 也会变大,这个公式有问题?
-----------------------------------------------------------------------
rt/t2 = r1/t1, 你弄反了.
-----------------------------------------------------------------------
gwdong,你没有读懂我的话,我说“根据顶楼的公式 rt*t2 = r1*t1”,这个公式就是顶楼最初的公式,我质疑的就是这个公式有问题。楼主现在的公式是重新修改过的了。 回复【43楼】gwdong
回复【15楼】<span highlight="search">atommann</span>
根据顶楼的公式 rt*t2 = r1*t1,r1*t1 是一个固定值,当 rt 变大的时候放电时间会变长,因此 t2 变大,rt*t2 也会变大,这个公式有问题?
-----------------------------------------------------------------------
rt/t2 = r1/t1, 你弄反了.
-----------------------------------------------------------------------
你看一下楼主在 25 楼的回复。 MARK!! NTC这个鬼东西用在工业上可靠性很难保证. mark 顶顶 没有这个必要吧 图片很给力 顶一下, mark 好东西,做个记号先。 图很喜欢,哈哈~~ 简易的AD转换,这样算比较经济的了 图做的真好{:victory:} 有空试试 留个记号…呵呵…以后回去看 谢谢分享,学习了 mark……
顶一个… 收藏了,分析的很仔细! mark ~ RC的充放电不是不可以,只是RC是非线性的DD,所以温度需要你重新标定的,还有就是RC的充放电太依赖于RC的稳定性,这个问题你想吧 标记一下 图画得很不错呀 好东西........................ longquan 发表于 2011-3-29 07:58
这个用555是不是会好点,有人说STC的输入触发器有问题(仅是听说),如果接比较器的话就不用校准了 ...
555请楼上的晒晒原理图 请问lz 用这种方法那HR202湿敏电阻改如何测量呢 感觉不错,学习下! 楼主,啥也不说,就是吊,就是任性 为什么电容充电不需要充满也可以啊 markmarkmarkmark 好东西,收藏一下 楼主的图通俗易懂.顶
页:
[1]