第七章:OLED温湿度显示系统
ESP32 + DHT11 + OLED(I2C 4线)温湿度显示系统
📝 项目概述
本教程将教你如何使用ESP32连接DHT11温湿度传感器和4线I2C OLED显示屏(通常为SSD1306驱动),实时显示环境温湿度数据。
📦 所需材料
- ESP32开发板
- DHT11温湿度传感器
- 0.96寸I2C OLED显示屏(SSD1306,4线接口)
- 面包板和杜邦线
🔌 硬件连接(4线I2C OLED)
OLED显示屏通常有4个引脚:
OLED引脚 | ESP32引脚 |
---|---|
VCC | 3.3V |
GND | GND |
SCL | GPIO22 |
SDA | GPIO21 |
DHT11连接方式:
- VCC → 3.3V
- DATA → GPIO4
- GND → GND
⚠️ 注意:部分OLED模块可能标注SCK/SDA而不是SCL/SDA,但连接方式相同。
💻 软件准备
- 安装必要的库:
- DHT sensor library(Adafruit)
- Adafruit SSD1306(OLED驱动)
- Adafruit GFX(图形库)
- Wire(I2C通信,通常已内置)
- 在Arduino IDE中安装库:
- 打开 工具 → 管理库,搜索并安装上述库。
🔑OLED显示屏关键细节
坐标系统:
-
OLED 的坐标原点
(0,0)
在 左上角(与数学坐标系不同) -
X 轴向右增加,Y 轴向下增加
-
示例(128x64像素的OLED):
(0,0) ---------------------> (127,0) | | | | v v (0,63) -------------------> (127,63)
U8G2库的使用
为了比较方便的显示中文,引入U8g2图形库,它多平台支持,内置矢量字体引擎
📌 Arduino完整代码
/** ESP32温湿度监测系统 - 优化版* 功能:* - 通过DHT11采集温湿度数据* - OLED显示实时数据(含中文)* - 串口输出监测结果* - 完善的错误处理机制* * 硬件配置:* - DHT11: GPIO4* - OLED: SCL=GPIO5, SDA=GPIO6 (I2C)* * 库依赖:* - U8g2 v2.32.x* - DHT sensor library v1.4.4*/#include <U8g2lib.h> // U8g2 OLED驱动库
#include <DHT.h> // DHT传感器库// ================= 硬件配置 =================
#define DHTPIN 4 // DHT11数据引脚
#define DHTTYPE DHT11 // 传感器类型// ================= 全局对象初始化 =================
DHT dht(DHTPIN, DHTTYPE); // 初始化DHT传感器// OLED配置(128x64分辨率,硬件I2C)
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, // 屏幕方向(0°)/* reset=*/ U8X8_PIN_NONE, // 无硬件复位/* clock=*/ 5, // SCL引脚(GPIO5)/* data=*/ 6 // SDA引脚(GPIO6)
);// ================= 自定义图标 =================
// 16x16像素的温度计图标(XBM格式)
static const unsigned char tempIcon[] PROGMEM = {0x00, 0x00, 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00,0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00,0x3E, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3E, 0x00,0x3E, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x00, 0x00
};// ================= 主程序 =================
void setup() {// 初始化串口通信Serial.begin(115200);Serial.println("\n系统启动中...");// 初始化DHT传感器dht.begin();// 初始化OLED显示if(!u8g2.begin()) {Serial.println("OLED初始化失败!");while(1); // 停止执行}// 配置OLED显示参数u8g2.enableUTF8Print(); // 启用UTF-8支持u8g2.setFont(u8g2_font_wqy16_t_gb2312); // 设置16点阵中文字体// 显示启动画面showSplashScreen();delay(1000); // 展示启动画面1秒
}void loop() {static unsigned long lastReadTime = 0;const unsigned long readInterval = 2000; // 采样间隔2秒// 定时读取传感器数据if(millis() - lastReadTime >= readInterval) {lastReadTime = millis();// 读取温湿度数据(带重试机制)float temperature = readTemperatureWithRetry(3);float humidity = readHumidityWithRetry(3);// 检查数据有效性if(!isnan(temperature) && !isnan(humidity)) {displayData(temperature, humidity); // 显示数据printToSerial(temperature, humidity); // 串口输出} else {showSensorError(); // 显示错误信息}}
}// ================= 功能函数 =================/*** 显示启动画面*/
void showSplashScreen() {u8g2.clearBuffer();// 绘制温度计图标(居中显示)u8g2.drawXBMP((128-16)/2, // x坐标居中10, // y坐标16, // 图标宽度16, // 图标高度tempIcon // 图标数据);// 显示启动文字(居中)const char* msg = "系统启动中...";u8g2.setCursor((128 - u8g2.getUTF8Width(msg))/2, 50);u8g2.print(msg);u8g2.sendBuffer();
}/*** 显示温湿度数据* @param temp 温度值(℃)* @param humi 湿度值(%)*/
void displayData(float temp, float humi) {u8g2.clearBuffer();// 1. 绘制界面边框u8g2.drawFrame(0, 0, 128, 64);// 2. 显示标题(居中)const char* title = "环境监测";u8g2.setCursor((128 - u8g2.getUTF8Width(title))/2, 18);u8g2.print(title);// 3. 显示温度数据u8g2.setCursor(20, 38);u8g2.print("温度: ");u8g2.print(temp, 1); // 显示1位小数u8g2.print(" °C");// 4. 显示湿度数据u8g2.setCursor(20, 58);u8g2.print("湿度: ");u8g2.print(humi, 1); // 显示1位小数u8g2.print(" %");u8g2.sendBuffer();
}/*** 带重试的温度读取* @param retries 重试次数* @return 温度值(℃)或NAN*/
float readTemperatureWithRetry(uint8_t retries) {float temp = NAN;while(retries-- > 0) {temp = dht.readTemperature();if(!isnan(temp)) break;delay(100);}return temp;
}/*** 带重试的湿度读取* @param retries 重试次数* @return 湿度值(%)或NAN*/
float readHumidityWithRetry(uint8_t retries) {float humi = NAN;while(retries-- > 0) {humi = dht.readHumidity();if(!isnan(humi)) break;delay(100);}return humi;
}/*** 串口输出数据*/
void printToSerial(float temp, float humi) {Serial.print("温度: ");Serial.print(temp, 1); // 1位小数Serial.print(" °C\t");Serial.print("湿度: ");Serial.print(humi, 1); // 1位小数Serial.println(" %");
}/*** 显示传感器错误信息*/
void showSensorError() {u8g2.clearBuffer();// 错误图标u8g2.setFont(u8g2_font_open_iconic_embedded_2x_t);u8g2.drawGlyph(54, 30, 66); // 警告符号// 错误信息u8g2.setFont(u8g2_font_wqy16_t_gb2312);const char* errMsg = "传感器错误!";u8g2.setCursor((128 - u8g2.getUTF8Width(errMsg))/2, 55);u8g2.print(errMsg);u8g2.sendBuffer();Serial.println("错误:无法读取DHT11数据!");
}
🔍 代码说明
- OLED初始化:
- 使用
Adafruit_SSD1306
库驱动OLED。 - 默认I2C地址是
0x3C
(部分可能是0x3D
)。 - 如果初始化失败,会在串口提示错误。
- 使用
- DHT11数据读取:
- 每2秒读取一次温湿度数据。
- 如果读取失败,会在串口提示。
- u8g2的使用:
display.clearDisplay()
清屏。display.setCursor(x, y)
设置文本位置。display.display()
更新屏幕内容。
🚀 运行效果
-
OLED屏幕显示:
-
串口监视器输出: