温湿度监测站:实时环境数据采集
想要随时掌握家里或办公室的环境状况吗?今天我们就来打造一个基于ESP32的温湿度监测站!不仅能实时显示数据,还能通过Wi-Fi将数据上传到云端,让你随时随地都能查看环境状况。告别”感觉潮湿”,用数据说话!
1. 项目简介
温湿度监测站是一个非常实用的物联网项目,可以用于:
-
监控室内环境舒适度 -
保护对温湿度敏感的物品(如书籍、乐器、电子设备) -
农业大棚环境监控 -
实验室环境记录
本项目将使用DHT22传感器(也可以用DHT11)来采集温湿度数据,并通过OLED显示屏实时显示,同时通过Wi-Fi将数据上传到服务器。
2. 硬件准备
必需硬件
-
ESP32开发板 × 1 -
DHT22温湿度传感器 × 1(或DHT11,精度稍低但价格便宜) -
OLED显示屏(128×64,I2C接口) × 1 -
杜邦线若干 -
面包板 × 1 -
USB数据线 × 1
传感器引脚说明
-
DHT22: VCC(3.3V)、GND、DATA(GPIO14) -
OLED: VCC(3.3V)、GND、SCL(GPIO22)、SDA(GPIO21)
3. 软件依赖
在ESP-IDF项目中,我们需要以下组件:
-
driver/gpio.h– GPIO控制 -
driver/i2c.h– I2C通信(用于OLED) -
freertos/task.h– FreeRTOS任务管理 -
nvs_flash.h– NVS存储(可选,用于保存配置) -
第三方库: DHT sensor library、SSD1306 OLED library
4. 核心代码实现
4.1 项目结构
main/
├── main.c
├── dht_sensor.c
├── oled_display.c
├── wifi_manager.c
└── components/
├── dht/
└── ssd1306/
4.2 DHT22传感器驱动
// dht_sensor.h
#ifndef DHT_SENSOR_H
#define DHT_SENSOR_H
#include <stdint.h>
#include <stdbool.h>
typedefstruct {
float temperature;
float humidity;
bool valid;
} dht_data_t;
esp_err_tdht_init(gpio_num_t pin);
esp_err_tdht_read_data(gpio_num_t pin, dht_data_t *data);
#endif
// dht_sensor.c
#include "dht_sensor.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/task.h"
#define TAG "DHT"
staticvoiddht_delay_us(uint32_t us) {
uint32_t start = esp_timer_get_time();
while ((esp_timer_get_time() - start) < us) {
// 忙等待
}
}
esp_err_tdht_init(gpio_num_t pin) {
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << pin),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
return ESP_OK;
}
esp_err_tdht_read_data(gpio_num_t pin, dht_data_t *data) {
// 初始化为输出模式
gpio_set_direction(pin, GPIO_MODE_OUTPUT);
// 主机拉低至少18ms
gpio_set_level(pin, 0);
vTaskDelay(pdMS_TO_TICKS(20));
// 主机拉高20-40us
gpio_set_level(pin, 1);
dht_delay_us(30);
// 切换到输入模式,等待传感器响应
gpio_set_direction(pin, GPIO_MODE_INPUT);
// 等待传感器拉低80us
uint32_t timeout = 0;
while (gpio_get_level(pin) == 1 && timeout < 1000) {
dht_delay_us(1);
timeout++;
}
if (timeout >= 1000) return ESP_ERR_TIMEOUT;
// 等待传感器拉高80us
timeout = 0;
while (gpio_get_level(pin) == 0 && timeout < 1000) {
dht_delay_us(1);
timeout++;
}
if (timeout >= 1000) return ESP_ERR_TIMEOUT;
// 读取40位数据
uint8_t data_bytes[5] = {0};
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 8; j++) {
// 等待50us低电平
timeout = 0;
while (gpio_get_level(pin) == 0 && timeout < 100) {
dht_delay_us(1);
timeout++;
}
// 测量高电平持续时间
uint32_t high_time = 0;
while (gpio_get_level(pin) == 1 && high_time < 100) {
dht_delay_us(1);
high_time++;
}
// 高电平>30us表示1,否则表示0
if (high_time > 30) {
data_bytes[i] |= (1 << (7 - j));
}
}
}
// 校验和验证
if (data_bytes[4] != (data_bytes[0] + data_bytes[1] + data_bytes[2] + data_bytes[3])) {
ESP_LOGE(TAG, "Checksum error");
data->valid = false;
return ESP_ERR_INVALID_CRC;
}
// 解析数据(DHT22)
data->humidity = (data_bytes[0] * 256 + data_bytes[1]) / 10.0;
data->temperature = ((data_bytes[2] & 0x7F) * 256 + data_bytes[3]) / 10.0;
if (data_bytes[2] & 0x80) {
data->temperature = -data->temperature;
}
data->valid = true;
ESP_LOGI(TAG, "Temp: %.1f°C, Humidity: %.1f%%", data->temperature, data->humidity);
return ESP_OK;
}
4.3 OLED显示驱动
// oled_display.c
#include "ssd1306.h"
#include "font8x8_basic.h"
#include "esp_log.h"
#define TAG "OLED"
voidoled_display_init(void) {
i2c_master_init();
ssd1306_init();
ssd1306_fill_screen(0x00);
ssd1306_show_text("温湿度监测站", 0, 0, 1);
ssd1306_show_text("初始化...", 0, 2, 1);
ssd1306_display();
}
voidoled_display_update(float temperature, float humidity) {
char temp_str[32];
char hum_str[32];
sprintf(temp_str, "温度: %.1f°C", temperature);
sprintf(hum_str, "湿度: %.1f%%", humidity);
ssd1306_fill_screen(0x00);
ssd1306_show_text("温湿度监测站", 0, 0, 1);
ssd1306_show_text(temp_str, 0, 2, 1);
ssd1306_show_text(hum_str, 0, 4, 1);
ssd1306_show_text("www.esp32iot.com", 0, 7, 1);
ssd1306_display();
}
4.4 主程序
// main.c
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "wifi_manager.h"
#include "dht_sensor.h"
#include "oled_display.h"
#define DHT_PIN GPIO_NUM_14
staticconstchar *TAG = "main";
voidtemp_humidity_task(void *pvParameters) {
dht_data_t sensor_data;
while (1) {
if (dht_read_data(DHT_PIN, &sensor_data) == ESP_OK && sensor_data.valid) {
// 更新OLED显示
oled_display_update(sensor_data.temperature, sensor_data.humidity);
// 上传数据到服务器(这里简化为打印)
ESP_LOGI(TAG, "上传数据: Temp=%.1f°C, Hum=%.1f%%",
sensor_data.temperature, sensor_data.humidity);
// TODO: 实际项目中这里会调用HTTP/MQTT上传函数
} else {
ESP_LOGE(TAG, "传感器读取失败");
oled_display_init();
ssd1306_show_text("传感器错误!", 0, 2, 1);
ssd1306_display();
}
// 每2秒读取一次
vTaskDelay(pdMS_TO_TICKS(2000));
}
}
voidapp_main(void) {
// 初始化NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NEW_VERSION_ERROR) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 初始化Wi-Fi
wifi_manager_init();
// 初始化OLED
oled_display_init();
// 初始化DHT传感器
dht_init(DHT_PIN);
// 创建温湿度读取任务
xTaskCreate(temp_humidity_task, "temp_humidity_task", 4096, NULL, 5, NULL);
}
5. 功能扩展
5.1 数据上传到云端
可以将数据上传到以下平台:
-
Thingspeak: 简单易用的IoT平台 -
Blynk: 提供手机App控制界面 -
自建服务器: 使用Node-RED或Python Flask
5.2 报警功能
-
当温度超过阈值时发送通知 -
湿度过高时自动开启除湿器(需要继电器模块)
5.3 历史数据记录
-
使用SPIFFS文件系统保存历史数据 -
定期上传到云端进行长期存储
6. 调试与优化
常见问题
-
传感器读取失败: 检查接线是否正确,确保使用3.3V供电 -
OLED不显示: 确认I2C地址是否正确(通常是0x3C) -
Wi-Fi连接不稳定: 检查信号强度,考虑添加重连机制
性能优化
-
使用低功耗模式延长电池寿命 -
优化读取频率(根据实际需求调整) -
添加数据滤波算法减少噪声
7. 项目总结
通过这个温湿度监测站项目,你不仅学会了如何使用DHT22传感器和OLED显示屏,还掌握了ESP32的多任务处理、I2C通信和Wi-Fi联网等核心技能。这个项目可以作为很多更复杂IoT应用的基础,比如智能家居环境监控系统、农业大棚管理系统等。
下一步建议:尝试将这个项目升级为太阳能供电的户外监测站,或者添加更多传感器(如大气压、光照强度)来构建完整的环境监测系统!
*本文使用的硬件:ESP32S3-DevKitC、DHT22传感器、SSD1306 OLED显示屏。
来源:老才科技学习记录
原创:老才
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END














![表情[chi]-寻找资源网](http://www.seekresource.com/wp-content/themes/zibll/img/smilies/chi.gif)



暂无评论内容