第九章 家庭数字温湿度监控仪(温湿度传感器DHT11+1602 LCD)(Arduino边做边学:从点亮Led到物联网)

本系列文章为作者原创,未经作者书面同意,不得转载!

温湿度监控仪(温湿度表)在我们生活中很常见,尤其北方家庭,冬天比较干燥,一般都会在家里放一个温湿度表,如果湿度过低,会打开加湿器,能够防止过于干燥的环境给人带来的不适。温湿度表一般有以下两种,一种是电子的,一种是机械的:


001.png
002.png

今天我们的项目就是制作一个温湿度监控仪!


我们要制作的温湿度监控仪当然是电子式的,通过温湿度传感器获取环境温湿度数据,然后在一块液晶屏上实时显示出来。

1 本章您将学到

在这个项目中,您将学到的:

  • 学会使用温湿度传感器
  • 学习使用1602液晶显示屏
  • 学习使用库文件和定义对象

2 工具和组件

2.1 工具列表

本项目不需要额外的工具。

2.2 元器件列表

元器件 型号 数量 备注
主控板 arduino Uno 1
温湿度传感器 DHT11 1
液晶屏 1602 LCD 1
电阻 4K欧姆 4
面包板 1
杜邦线 若个
数据线 Uno数据线 1

2.3 工具和元器件介绍

2.3 工具和元器件介绍

2.3.1 DHT11温湿度传感器

dht11.png

引脚说明:

  • VCC:供电 3.5V-5.5V DC
  • DATA:串行数据,单总线
  • NC:空引脚(无需连线)
  • GND:接地,电源负极

2.3.2 1602 LCD

1602.png

1602字符型液晶,是一种专门用来显示字母、数字、符号等的点阵型液晶模块,能够同时显示16x02即32个字符。

它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。

1602 LCD分为两种:带背光和不带背光,带背光的要后一些,引脚多2个,为16个引脚,如下:


1602_01.png

2.3.2.1 引脚说明

1602 LCD通常有14条引脚或16条引脚,14与16引脚的差别在于16条引脚多了背光电源线VCC(15脚)和地线GND(16脚),其它引脚与14脚的LCD完全一样,如下:

引脚 符号 功能说明
1 VSS 一般接地
2 VDD 接电源(+5V)
3 V0 液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)
4 RS RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器
5 R/W R/W为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作
6 E E(或EN)端为使能(enable)端,写操作时,下降沿使能;读操作时,E高电平有效
7 DB0 低4位三态、 双向数据总线 0位(最低位)
8 DB1 高4位三态、 双向数据总线 1位
9 DB2 高4位三态、 双向数据总线 2位
10 DB3 高4位三态、 双向数据总线 3位
11 DB4 高4位三态、 双向数据总线 4位
12 DB5 高4位三态、 双向数据总线 5位
13 DB6 高4位三态、 双向数据总线 6位
14 DB7 高4位三态、 双向数据总线 7位(busy flag)
15 BLA 背光电源正极
16 BLK 背光电源负极

2.3.2.2 与Arduino的连接

1602 LCD与Arduino的直接相连有两种接线方式:四线法和八线法。顾名思义,四线法就是只需要连接8个数据引脚中的四个即可,八线法则需要全部连接。

您也许会问,既然连接4个引脚即可,为什么还要费劲巴拉的连八个?八线法有什么用呢?当然有用,用处就是数据的传输速度会快一些,给你的感觉就是显示器刷新速度会快一些,当然这个速度差异我没有测试过,这个还要取决于您的肉眼是否是火眼金睛。

另外,1602 LCD与Arduino还有一种间接的连接方式,就是用一块I2C的转接板,这种方式Arduino需要的引脚更少,这部分涉及到Arduino的I2C通信,我们不在本文介绍。

本文主要介绍常用的四线法:


1602_02.png

上图就是四线法的接线方法,应该很清晰了,注意V0与GND之间有一个调节液晶对比度的4K欧姆的电阻,也可以用一个滑动变阻器代替,这样调节对比度更加方便。

3 电路设计

3.1 电路图

根据我们的项目需求,设计电路图如下:


0006.png

3.2 电路原理

这个电路图其实比较简单,就是将1602 LCD和DHT11跟UNO连接上,这两个模块的连线方法第二节已经详细介绍了,这里就不再赘述。

这个电路图唯一需要注意的是图中V0/VL引脚连接的电阻。

V0/VL引脚为液晶显示器对比度调整端口,推荐使用一个10K的电位器来调整对比度。在这个项目中,选择了4k电阻,在通过电脑USB给UNO供电的情况下,液晶显示对比度比较理想,不过在用12V电源供电的情况下,液晶显示对比度偏低,所以您在设计还需要注意,如果需要采用独立电源供电,需要对电阻进行重新选择。

4 程序设计

4.1 类库介绍

4.1.1 dht11.h库介绍

4.1.1.1 dht11.h库的下载

首先说明一下,Arduino上DHT11的库有好几个,使用起来大同小异,本项目中使用的是dht11.h(还有DHT.h,稍微有点不同),dht11.h的下载地址:github链接
下载下来后,在Arduino IDE中,点击项目->加载库->添加一个.zip库,选择下载好的dht11-master.zip文件即可。

4.1.1.1 dht11.h库的介绍

我们来看一下这个库的头文件,cpp文件这里就不过多介绍了,对于库,我们主要是弄明白怎么使用就OK。
我们还是先看代码:

// 
//    FILE: dht11.h
// VERSION: 0.4.1
// PURPOSE: DHT11 Temperature & Humidity Sensor library for Arduino
// LICENSE: GPL v3 (http://www.gnu.org/licenses/gpl.html)
//
// DATASHEET: http://www.micro4you.com/files/sensor/DHT11.pdf
//
//     URL: http://playground.arduino.cc/Main/DHT11Lib
//
// HISTORY:
// George Hadjikyriacou - Original version
// see dht.cpp file
// 

#ifndef dht11_h
#define dht11_h

#if defined(ARDUINO) && (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif

#define DHT11LIB_VERSION "0.4.1"

#define DHTLIB_OK               0
#define DHTLIB_ERROR_CHECKSUM   -1
#define DHTLIB_ERROR_TIMEOUT    -2

class dht11
{
public:
    int read(int pin);
    int humidity;
    int temperature;
};
#endif
//
// END OF FILE
//

其实这个头文件非常简单(这也是为什么我采用这个库的原因,简单易学):

  • 申明了一个类:dht11
  • 申明了一个方法:read(int pin),读取传感器数据
  • 声明了两个变量:humidity和temperature,分别是湿度值和温度值

注意:dht11.h这个库温湿度数据都采用的整型变量,对于精度要求高的项目不适合,而且只能支持dht11型温湿度传感器,如果项目采用的是dht22传感器或者要求更高精度数据,可以使用dht.h这个库。

结合后面的主程序,对于这个库的使用,我想您一看就明白了!

4.1.2 LiquidCrystal.h库介绍

4.1.2.1 LiquidCrystal.h库的下载

LiquidCrystal库是Arduino IDE自带的,一般无需安装,如果您的IDE版本过低或者没有找到这个库,可以在Arduino IDE中, 项目->加载库->管理库中搜索LiquidCrystal,然后点击安装即可。

4.1.2.1 LiquidCrystal.h库的介绍

我们还是看看它的头文件吧:

#ifndef LiquidCrystal_h
#define LiquidCrystal_h

#include <inttypes.h>
#include "Print.h"

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

class LiquidCrystal : public Print {
public:
  LiquidCrystal(uint8_t rs, uint8_t enable,
        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
        uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
        uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
  LiquidCrystal(uint8_t rs, uint8_t enable,
        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
        uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
        uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
    
  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);

  void clear();
  void home();

  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void scrollDisplayLeft();
  void scrollDisplayRight();
  void leftToRight();
  void rightToLeft();
  void autoscroll();
  void noAutoscroll();

  void setRowOffsets(int row1, int row2, int row3, int row4);
  void createChar(uint8_t, uint8_t[]);
  void setCursor(uint8_t, uint8_t); 
  virtual size_t write(uint8_t);
  void command(uint8_t);
  
  using Print::write;
private:
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t);
  void write8bits(uint8_t);
  void pulseEnable();

  uint8_t _rs_pin; // LOW: command.  HIGH: character.
  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
  uint8_t _enable_pin; // activated by a HIGH pulse.
  uint8_t _data_pins[8];

  uint8_t _displayfunction;
  uint8_t _displaycontrol;
  uint8_t _displaymode;

  uint8_t _initialized;

  uint8_t _numlines;
  uint8_t _row_offsets[4];
};

#endif

这个头文件比上面那个dht11.h要丰富多了,它声明的方法很多,限于篇幅我不一一介绍,这部分类容会放在附录中详细介绍,本文主要介绍一下我们在主程序中将要用到的两个方法以及其构造方法:

  • LiquidCrystal():构造方法,用于声明1602 LCD对象时对其引脚连接进行初始化,我们看到这个函数能够根据不同的参数(接线方式)进行重载
  • setCursor():设定液晶的光标位置,即开始显示字符的位置
  • print():输出字符串到LCD

4.2 主程序设计

/*
 *名称:环境温湿度监控仪
 *功能:
 *作者:YXK
 *时间:2018.6.4 
 */
 
#include <LiquidCrystal.h>
#include <dht11.h>
#define DHT11PIN 4;  //定义温湿度传感器DHT11的引脚连接
LiquidCrystal myLcd(12,11,10,9,8,7,6); //声明一个1602 LCD对象
dht11 myDHT;   //声明一个DHT11对象

int temp = 0;  //初始化温度变量
int humi = 0;  //初始化湿度变量

void setup(){
  myLcd.begin(16,2);
}

void loop(){
  myDHT.read(DHT11PIN);               //读取传感器数据
  temp = myDHT.temperature;    //将读取的温度数据赋值给temp变量
  humi = myDHT.humidity;       //将读取的湿度数据赋值给humi变量
    
  myLcd.setCursor(0, 0);    //将1602 LCD光标移动到第一行第一列
  myLcd.print(String("TEMP: ") + String(String(temp) + String(" C")));  //显示温度
  myLcd.setCursor(0, 1);    //将1602 LCD光标移动到第二行第一列
  myLcd.print(String("HUMI: ") + String(String(humi) + String(" %")));  //显示湿度

  delay(60000);   //延迟1分钟,即每分钟更新一次
}

这个程序就不再解释了,我想程序中的注释已经非常清楚了!

4 安装调试

下面我们根据电路图将两个模块跟UNO连接上:

003.jpg

然后将UNO连接上电脑,上传程序:


002.jpg

呵呵,您做的是不是也成功了?

5 总结扩展

上面我们做的这个温湿度监控仪还是比较简陋的,摆在家里也不是很美观,您可以把它看成是一个产品的验证原型。

如果您想做一台能够放在家里使用的温湿度监控仪,当然也是可以的,您可以在上面的基础上增加一个亚克力的盒子,然后添加一个9V电池盒进行供电,再将上面的面包板换成一个小一些的,将布线稍微整理一下,然后就基本上是这个样子的(这个案例来自于链接,图片中的作品还增加了LED灯和蜂鸣器):

005.png

当然您也可以做得更漂亮一些,期待着您的作品!

如果您喜欢本文,您可以点击一下下面的喜欢按钮,您也可以关注我,谢谢您的支持!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容