本系列文章为作者原创,未经作者书面同意,不得转载!
温湿度监控仪(温湿度表)在我们生活中很常见,尤其北方家庭,冬天比较干燥,一般都会在家里放一个温湿度表,如果湿度过低,会打开加湿器,能够防止过于干燥的环境给人带来的不适。温湿度表一般有以下两种,一种是电子的,一种是机械的:
今天我们的项目就是制作一个温湿度监控仪!
我们要制作的温湿度监控仪当然是电子式的,通过温湿度传感器获取环境温湿度数据,然后在一块液晶屏上实时显示出来。
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温湿度传感器
引脚说明:
- VCC:供电 3.5V-5.5V DC
- DATA:串行数据,单总线
- NC:空引脚(无需连线)
- GND:接地,电源负极
2.3.2 1602 LCD
1602字符型液晶,是一种专门用来显示字母、数字、符号等的点阵型液晶模块,能够同时显示16x02即32个字符。
它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。
1602 LCD分为两种:带背光和不带背光,带背光的要后一些,引脚多2个,为16个引脚,如下:
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通信,我们不在本文介绍。
本文主要介绍常用的四线法:
上图就是四线法的接线方法,应该很清晰了,注意V0与GND之间有一个调节液晶对比度的4K欧姆的电阻,也可以用一个滑动变阻器代替,这样调节对比度更加方便。
3 电路设计
3.1 电路图
根据我们的项目需求,设计电路图如下:
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连接上:
然后将UNO连接上电脑,上传程序:
呵呵,您做的是不是也成功了?
5 总结扩展
上面我们做的这个温湿度监控仪还是比较简陋的,摆在家里也不是很美观,您可以把它看成是一个产品的验证原型。
如果您想做一台能够放在家里使用的温湿度监控仪,当然也是可以的,您可以在上面的基础上增加一个亚克力的盒子,然后添加一个9V电池盒进行供电,再将上面的面包板换成一个小一些的,将布线稍微整理一下,然后就基本上是这个样子的(这个案例来自于链接,图片中的作品还增加了LED灯和蜂鸣器):
当然您也可以做得更漂亮一些,期待着您的作品!
如果您喜欢本文,您可以点击一下下面的喜欢按钮,您也可以关注我,谢谢您的支持!