DHT22

元器件
传感器
库存 800

介绍

DHT22/AM2302 高精度温湿度传感器,数字信号输出,测温-4080°C±0.5°C,测湿0100%RH±2%RH,单总线协议。相比DHT11精度更高、量程更宽,适合工业级和户外环境监测。3.3-5.5V供电,采样周期≥2秒。

规格参数

参数
封装4脚单排直插
尺寸25.1mm x 15.1mm x 7.7mm
分辨率温度0.1°C / 湿度0.1% RH
供电电压3.3V-5.5V
测温精度±0.5°C
测温范围-40°C ~ +80°C
测湿精度±2% RH
测湿范围0% ~ 100% RH
通信协议单总线(One-Wire)
采样周期>=2秒

代码例程

DHT22/AM2302 高精度温湿度传感器代码例程.md
# Arduino 外设综合:温湿度传感器 DHT22 + OLED 显示

## 目标

使用 DHT22 采集温湿度,在 SSD1306 OLED 上实时显示,并实现按键切换显示模式。

## 硬件清单

| 元件 | 引脚 |
|------|------|
| Arduino Uno | - |
| DHT22 温湿度传感器 | DATA → D2 |
| SSD1306 OLED (128×64 I²C) | SDA → A4, SCL → A5 |
| 按键 | D3(内部上拉) |

## 完整代码

```cpp
/*
 * 温湿度监测仪 — DHT22 + SSD1306 OLED
 * 库依赖:DHT sensor library by Adafruit (>=1.4.4)
 *         Adafruit SSD1306 (>=2.5.7)
 *         Adafruit GFX Library (>=1.11.9)
 */

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

// ── 引脚定义 ──
#define DHTPIN      2
#define DHTTYPE     DHT22
#define BTN_PIN     3
#define OLED_ADDR   0x3C
#define SCREEN_W    128
#define SCREEN_H    64

// ── 对象 ──
DHT dht(DHTPIN, DHTTYPE);
Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire);

// ── 状态 ──
enum DisplayMode { MODE_NORMAL, MODE_LARGE_TEMP, MODE_LARGE_HUM, MODE_COUNT };
DisplayMode mode = MODE_NORMAL;

float temperature = 0.0;
float humidity = 0.0;
unsigned long lastRead = 0, lastBtnCheck = 0;
const unsigned long READ_INTERVAL = 2000;

// ── 初始化 ──
void setup() {
  Serial.begin(9600);
  pinMode(BTN_PIN, INPUT_PULLUP);

  dht.begin();

  // OLED 初始化
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println(F("SSD1306 初始化失败!"));
    while (1) delay(10);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 25);
  display.println(F("DHT22 Monitor"));
  display.display();
  delay(1500);
}

// ── 读取传感器 ──
bool readSensor() {
  float t = dht.readTemperature();
  float h = dht.readHumidity();

  if (isnan(t) || isnan(h)) {
    Serial.println(F("DHT22 读取失败!"));
    return false;
  }
  temperature = t;
  humidity = h;
  return true;
}

// ── 按键处理 ──
void checkButton() {
  static bool lastState = HIGH;
  bool now = digitalRead(BTN_PIN);

  if (lastState == HIGH && now == LOW) {  // 下降沿
    delay(30);  // 消抖
    if (digitalRead(BTN_PIN) == LOW) {
      mode = (DisplayMode)((mode + 1) % MODE_COUNT);
      Serial.print(F("切换模式: "));
      Serial.println(mode);
    }
  }
  lastState = now;
}

// ── OLED 渲染 ──
void renderDisplay() {
  display.clearDisplay();

  switch (mode) {
    case MODE_NORMAL:
      renderNormal();
      break;
    case MODE_LARGE_TEMP:
      renderLarge(0, "TEMPERATURE", temperature, "C");
      break;
    case MODE_LARGE_HUM:
      renderLarge(1, "HUMIDITY", humidity, "%");
      break;
  }

  display.display();
}

void renderNormal() {
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(F("--- DHT22 Monitor ---"));

  display.drawLine(0, 12, 128, 12, SSD1306_WHITE);

  display.setTextSize(2);
  display.setCursor(5, 20);
  display.print(temperature, 1);
  display.print((char)247);  // °
  display.print(F("C"));

  display.setTextSize(2);
  display.setCursor(5, 42);
  display.print(humidity, 1);
  display.print(F("%"));

  // 模式指示
  display.setTextSize(1);
  display.setCursor(100, 56);
  display.print(mode + 1);
  display.print(F("/"));
  display.print(MODE_COUNT);
}

void renderLarge(int icon, const char* title, float value, const char* unit) {
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print(title);

  // 大字号数值
  display.setTextSize(4);
  int x = (value < 10) ? 30 : (value < 100) ? 18 : 5;
  display.setCursor(x, 18);
  display.print(value, 1);

  display.setTextSize(2);
  display.setCursor(x + 60, 38);
  display.print(unit);

  display.setTextSize(1);
  display.setCursor(0, 56);
  display.print(F("按键切换 ["));
  display.print(mode + 1);
  display.print(F("/"));
  display.print(MODE_COUNT);
  display.print(F("]"));
}

// ── 主循环 ──
void loop() {
  unsigned long now = millis();

  // 定时读取传感器(非阻塞)
  if (now - lastRead >= READ_INTERVAL) {
    lastRead = now;
    if (readSensor()) {
      Serial.print(F("温度: "));
      Serial.print(temperature);
      Serial.print(F("°C  湿度: "));
      Serial.print(humidity);
      Serial.println(F("%"));
    }
    renderDisplay();
  }

  // 按键扫描
  if (now - lastBtnCheck >= 50) {
    lastBtnCheck = now;
    checkButton();
  }
}
```

## 运行步骤

1. 在 Arduino IDE **库管理器**安装:`DHT sensor library`、`Adafruit SSD1306`、`Adafruit GFX`
2. 按硬件表接线
3. 编译上传,打开串口监视器(9600 波特率)
4. 按按键切换显示模式

## 预期输出

- OLED 实时显示温湿度(2 秒刷新)
- 串口同步输出读数
- 按键切换 4 种模式:双排紧凑 → 大字温度 → 大字湿度 → 循环

## 关键点

- `isnan()` 检测 DHT22 读取失败(常见于刚上电)并优雅处理
- 显示刷新放在定时器中避免频繁重绘导致闪烁
- 按键用 `INPUT_PULLUP` 省外部上拉电阻

参考资料

暂无参考文献