30、告别“感觉潮湿”:ESP32让环境数据一目了然

30、告别“感觉潮湿”:ESP32让环境数据一目了然

温湿度监测站:实时环境数据采集

想要随时掌握家里或办公室的环境状况吗?今天我们就来打造一个基于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)

图片[1]-30、告别“感觉潮湿”:ESP32让环境数据一目了然-寻找资源网

3. 软件依赖

在ESP-IDF项目中,我们需要以下组件:

  • driver/gpio.h – GPIO控制
  • driver/i2c.h – I2C通信(用于OLED)
  • freertos/task.h – FreeRTOS任务管理
  • nvs_flash.h – NVS存储(可选,用于保存配置)
  • 第三方库:DHT sensor librarySSD1306 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. 调试与优化

常见问题

  1. 传感器读取失败: 检查接线是否正确,确保使用3.3V供电
  2. OLED不显示: 确认I2C地址是否正确(通常是0x3C)
  3. Wi-Fi连接不稳定: 检查信号强度,考虑添加重连机制

性能优化

  • 使用低功耗模式延长电池寿命
  • 优化读取频率(根据实际需求调整)
  • 添加数据滤波算法减少噪声

7. 项目总结

通过这个温湿度监测站项目,你不仅学会了如何使用DHT22传感器和OLED显示屏,还掌握了ESP32的多任务处理、I2C通信和Wi-Fi联网等核心技能。这个项目可以作为很多更复杂IoT应用的基础,比如智能家居环境监控系统、农业大棚管理系统等。

下一步建议:尝试将这个项目升级为太阳能供电的户外监测站,或者添加更多传感器(如大气压、光照强度)来构建完整的环境监测系统!

*本文使用的硬件:ESP32S3-DevKitC、DHT22传感器、SSD1306 OLED显示屏。

来源:老才科技学习记录

原创:老才

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
相关推荐
评论 抢沙发

请登录后发表评论

    暂无评论内容