您好,欢迎访问深圳市深恒安科技有限公司官网!
VOC检测仪-甲醛检测仪-气体报警器-气体检测仪厂家-深恒安科技有限公司
联系我们
VOC检测仪-甲醛检测仪-气体报警器-气体检测仪厂家-深恒安科技有限公司
邮箱:Gaspanda@163.com
电话:18028784534
地址:深圳市宝安区新安街道文雅社区宝民一路203号
当前位置: 主页 > 检测仪知识百科

检测仪知识百科

温湿度探测 单片机很好玩8,温度太高就报警,制作一个智能室内温度湿度计
发布时间:2021-04-09 01:04浏览次数:

第二节和第三节介绍了如何使用C语言编程单片机,制作 LED 闪烁小灯,以及 LED “呼吸灯”。上一节介绍了利用 DHT11 温湿度传感器测量室内温度和湿度的方法,本节将把它们结合,制作一些更加“有意思”的小玩意儿。

温湿度报警器

温湿度传感器的很多实际应用的场景都是检测一个“阈值”——例如,如果环境温度在 40 摄氏度以下则一切正常,一旦环境温度超过 40 摄氏度,就会有报警信息,通常以“声光”的形式(铃声、警报灯等)给出。

参照实际应用,我们可以使用C语言编程单片机,用缓和的 LED “呼吸灯”表示正常温湿度情况。而一旦出现温度超过阈值的情况,则可以用急促的 LED 闪烁小灯表示。

先来看看上一节获取室内温湿度的单片机 C语言程序代码:

void main()
{
 char dat[5] = {0};
 int cks;
 init_uart(9600);
 set_timer0(10); // 10us
 prints("init...\r\n");
 delay_10us(50000);delay_10us(50000);
 delay_10us(50000);delay_10us(50000);
 prints("program start...\r\n");
 while(1){
 dht11_start();
 dht11_read_once(dat);
 cks = 0;
 cks += dat[0]; cks += dat[1];
 cks += dat[2]; cks += dat[3];
 if((char)cks == dat[4]){
 prints("RH: ");printn(dat[0]);prints(".");printn(dat[1]);prints(" ");
 prints("TM: ");printn(dat[2]);prints(".");printn(dat[3]);prints("\r\n");
 }else{
 prints("capture failed\r\n");
 }
 delay_10us(50000);delay_10us(50000);
 }
}

乍一看,要实现上面的设计好像很简单,只需要判断一下温度值,再决定使用哪一套 LED 小灯的控制程序(“呼吸灯”程序,或者“闪烁”程序)就可以了。

但是 DHT11 传感器需要的 delay_10us(50000); 语句会破坏 LED 小灯的控制程序,因为在这 500ms 期间,单片机处于等待状态,无法控制 LED 小灯闪烁或者“呼吸”。那么,没有办法解决这个问题吗?也不是,请看 LED 小灯“闪烁”的核心C语言程序:

while(1){
 P20 = 0;
 delay(10);
 P20 = 1;
 delay(10);
 }

以及 LED 的“呼吸灯”的核心C语言程序:

void twinkle_once(unsigned char darkTime)
{
 P20 = 0;
 delay(100-darkTime);
 P20 = 1;
 delay(darkTime);
}

仔细思考一下,应该能明白无论是 LED “闪烁”程序,还是“呼吸”程序,其实都依赖“延时”。那思路就有了,直接使用 LED 小灯的控制程序代替 delay_10us(50000); 不就可以了吗?的确如此,请继续往下看。

编写C语言程序,制作自己的警报器

先在上一节 C语言代码的基础上氨气报警器,实现更大尺度的 5ms 延时函数:

void delay_5ms(unsigned int n)
{
 while(n--)
 delay_10us(5);
}

耳温计和额温计_额温计和耳温计_温湿度探测

使用 delay_5m() 函数替换之前定义的“不精确”延时函数 delay() 函数甲烷报警器,这样我们就能知道较为精确的 LED 小灯的控制程序执行时间,也就能更加方便的替换 delay_10us(50000); 语句。

现在写出“呼吸”1 秒的 LED “呼吸灯”C语言程序就不难了,请看:

void led_breath_1s()
{
 static int cnt = 0;
 static char dark_time = 0, dir = 1 ;
 while(1){
 twinkle_once(dark_time);
 if( 0==((cnt++)%4) ){
 if(dir)
 dark_time += 1;
 else
 dark_time -= 1;
 if(dark_time >= 100)
 dir = 0;
 if(dark_time <= 60)
 dir = 1;
 }
 if(cnt > 200){
 cnt = 0;
 break;
 }
 }
}

twinkle_once() 执行一次需要 5ms 的时间,cnt 计数到 200 次就恰好是 1 秒,另外,if( 0==((cnt++)%4) ) 语句仍然能够控制 LED 小灯的“呼吸”频率。其他部分的代码与之前介绍的就没什么不同了。

类似的,闪烁 1 秒的 LED “闪烁”C语言程序可以如下实现:

void led_twinkle_1s()
{
 char cnt = 5;
 while(cnt--){
 P21 = 1;
 delay_10us(10000);
 P21 = 0;
 delay_10us(10000);
 }
}

闪烁一次需要 200 ms 的时间,那么闪烁 5 次就是 1秒了。现在使用 led_breath_1s() 和 led_twinkle_1s() 函数替换delay_10us(50000); 语句就可以了。请看:

void main()
{
 char dat[5] = {0};
 int cks;
 init_uart(9600);
 set_timer0(10); // 10us
 prints("init...\r\n");
// delay_10us(50000);delay_10us(50000);
// delay_10us(50000);delay_10us(50000);
 led_breath_1s();
 led_breath_1s(); 
 prints("program start...\r\n");
 while(1){
 dht11_start();
 dht11_read_once(dat);
 cks = 0;
 cks += dat[0]; cks += dat[1];
 cks += dat[2]; cks += dat[3];
 if((char)cks == dat[4]){
 prints("RH: ");printn(dat[0]);prints(".");printn(dat[1]);prints(" ");
 prints("TM: ");printn(dat[2]);prints(".");printn(dat[3]);prints("\r\n");
 }else{
 prints("capture failed\r\n");
 }
 if(dat[2] > 15)
 led_twinkle_1s();
 else
 led_breath_1s();
 //delay_10us(50000);delay_10us(50000);
 }
}

初始化时,使用了 led_breath_1s(); 代替了 DHT11 传感器需要的延时,每次获取温湿度值的时候,则判断了温度值,如果温度大于 15 摄氏度,使用LED的“闪烁”程序代替延时 1秒,否则使用 LED 的“呼吸灯”程序代替。

现在编译C语言程序,烧写到单片机,可以得到如下结果:

一开始,DHT11 探测到的温度较低,所以LED指示灯是“呼吸”状态的温湿度探测,然后使用手捏住 DHT11,温度升高超过“阈值”后,LED 小灯就变成“闪烁”状态了。

还有问题吗?

上面的控制程序还不是很完美,相信细心的朋友应该看出来了,LED小灯处于“呼吸”状态时,总是会有一次闪烁。这是因为我们采集 DHT11 传回来的温湿度信息时,也有几十毫秒的延时,在这段时间内,单片机是无法控制 LED 小灯的温湿度探测,所以小灯会一直处于最近一次的亮暗状态,查看 led_twinkle_1s() 函数的C语言代码就知道,LED 小灯最后的状态是亮的状态,这就解释了我们遇到的问题。

这其实也是单片机编程的一个特点温湿度探测,若单片机内部没有运行操作系统,则编写并行的程序几乎是不可能的,所以串行的阻塞延时应该尽量避免,否则就会出现类似上面的问题。那么,上面这种问题不借助于操作系统也能解决吗?当然可以,借助于单片机的中断系统就很好解决,限于篇幅,以后再说了。

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

腾元达编辑,转载请注明出处

标签: 温湿度探测
请往下拉!