Arduino 外设综合:温湿度传感器 DHT22 + OLED 显示
目标
使用 DHT22 采集温湿度,在 SSD1306 OLED 上实时显示,并实现按键切换显示模式。
硬件清单
| 元件 |
引脚 |
| Arduino Uno |
- |
| DHT22 温湿度传感器 |
DATA → D2 |
| SSD1306 OLED (128×64 I²C) |
SDA → A4, SCL → A5 |
| 按键 |
D3(内部上拉) |
完整代码
#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();
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;
}
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();
}
}
运行步骤
- 在 Arduino IDE 库管理器安装:
DHT sensor library、Adafruit SSD1306、Adafruit GFX
- 按硬件表接线
- 编译上传,打开串口监视器(9600 波特率)
- 按按键切换显示模式
预期输出
- OLED 实时显示温湿度(2 秒刷新)
- 串口同步输出读数
- 按键切换 4 种模式:双排紧凑 → 大字温度 → 大字湿度 → 循环
关键点
isnan() 检测 DHT22 读取失败(常见于刚上电)并优雅处理
- 显示刷新放在定时器中避免频繁重绘导致闪烁
- 按键用
INPUT_PULLUP 省外部上拉电阻
Arduino Hello World:LED 闪烁与串口输出
目标
掌握 Arduino 最基础的开发流程:编译 → 上传 → 观察 LED 闪烁和串口监视器输出。
完整代码
const int LED_PIN = LED_BUILTIN; // 板载 LED(大多数板子为 13)
unsigned long lastBlinkTime = 0;
const unsigned long BLINK_INTERVAL = 500; // 毫秒
int blinkCount = 0;
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
while (!Serial) {
delay(10);
}
Serial.println("=== Arduino Hello World ===");
Serial.println("板载 LED 开始闪烁,每 500ms 翻转一次");
Serial.print ("LED 引脚:");
Serial.println(LED_PIN);
}
void loop() {
unsigned long now = millis();
if (now - lastBlinkTime >= BLINK_INTERVAL) {
lastBlinkTime = now;
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
blinkCount++;
Serial.print("闪烁次数: ");
Serial.print(blinkCount);
Serial.print(" | LED 状态: ");
Serial.println(digitalRead(LED_PIN) ? "亮" : "灭");
}
}
运行步骤
- 用 USB 线连接 Arduino 到电脑
- 打开 Arduino IDE → 工具 → 开发板 → 选择你的板子(如 Arduino Uno)
- 工具 → 端口 → 选择对应 COM 端口
- 粘贴代码 → 点击 上传(→ 箭头)
- 打开 工具 → 串口监视器(Ctrl+Shift+M),波特率选 9600
预期输出
- 板载 LED 每 0.5 秒闪烁一次
- 串口监视器持续输出:
=== Arduino Hello World ===
板载 LED 开始闪烁,每 500ms 翻转一次
LED 引脚:13
闪烁次数: 1 | LED 状态: 亮
闪烁次数: 2 | LED 状态: 灭
闪烁次数: 3 | LED 状态: 亮
...
关键点
setup() 只执行一次,loop() 无限循环
millis() 实现非阻塞延时,优于 delay() 阻塞方案
LED_BUILTIN 是跨板通用宏,自动适配不同板子的板载 LED 引脚