You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Arduino Uno的无RTC数字时钟开发:DHT11温湿度轮显需求

Arduino Uno 无RTC数字时钟+DHT11温湿度切换显示方案

嘿,这个实用的小项目挺有意思的!我给你整理了一套完整的实现方案,分硬件、代码、关键细节三部分,跟着做就能轻松搞定~

整体思路

因为不用RTC模块,我们用Arduino的millis()函数实现非阻塞式计时(避免delay()导致的程序卡顿);LCD1602第一行固定显示时间,第二行通过定时器控制,每2秒切换一次温度和湿度显示;DHT11负责读取温湿度数据,同时加入错误处理避免读取失败时的乱码。

硬件接线说明

推荐用I2C版本的LCD1602,接线更简洁:

  • LCD1602(I2C):
    • VCC → Arduino Uno 5V引脚
    • GND → Arduino Uno GND引脚
    • SDA → Arduino Uno A4引脚
    • SCL → Arduino Uno A5引脚
  • DHT11传感器:
    • VCC → Arduino Uno 5V引脚
    • GND → Arduino Uno GND引脚
    • DATA → Arduino Uno D2引脚(代码里可修改对应引脚)
    • 补充:如果你的DHT11模块没有自带上拉电阻,需要在DATA和VCC之间接一个10KΩ的电阻,保证信号稳定。

完整代码实现

先确保你已经在Arduino库管理器里安装了LiquidCrystal_I2C和DHT库:

#include <LiquidCrystal_I2C.h>
#include <DHT.h>

// 初始化I2C LCD(地址通常为0x27或0x3F,根据你的模块调整)
LiquidCrystal_I2C lcd(0x27, 16, 2);

// 初始化DHT11
#define DHTPIN 2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// 计时相关变量
unsigned long lastTimeUpdate = 0;
const long timeInterval = 1000; // 1秒更新一次时间
int seconds = 0;
int minutes = 0;
int hours = 12; // 初始时间,可自行修改

// 温湿度切换相关变量
unsigned long lastDisplaySwitch = 0;
const long displayInterval = 2000; // 2秒切换一次显示
bool showTemperature = true; // 当前显示状态:true=温度,false=湿度
float tempValue = 0.0;
float humiValue = 0.0;

void setup() {
  lcd.init();
  lcd.backlight(); // 打开LCD背光
  dht.begin();
  Serial.begin(9600); // 串口调试用,不需要可注释掉
}

void loop() {
  unsigned long currentMillis = millis();

  // --- 处理时间更新 ---
  if (currentMillis - lastTimeUpdate >= timeInterval) {
    lastTimeUpdate = currentMillis;
    seconds++;
    
    // 时间进位逻辑
    if (seconds >= 60) {
      seconds = 0;
      minutes++;
      if (minutes >= 60) {
        minutes = 0;
        hours++;
        if (hours >= 24) hours = 0;
      }
    }

    // 更新第一行时间显示(格式化补零)
    lcd.setCursor(0, 0);
    lcd.print("TIME:");
    if (hours < 10) lcd.print("0");
    lcd.print(hours);
    lcd.print(":");
    if (minutes < 10) lcd.print("0");
    lcd.print(minutes);
    lcd.print(":");
    if (seconds < 10) lcd.print("0");
    lcd.print(seconds);
  }

  // --- 处理温湿度切换与读取 ---
  if (currentMillis - lastDisplaySwitch >= displayInterval) {
    lastDisplaySwitch = currentMillis;
    
    // 切换前先清空第二行(用空格覆盖,避免残留字符)
    lcd.setCursor(0, 1);
    lcd.print("                "); // 16个空格刚好填满一行
    
    // 切换显示状态
    showTemperature = !showTemperature;

    // 读取温湿度数据
    humiValue = dht.readHumidity();
    tempValue = dht.readTemperature();

    // 检查读取是否成功
    if (isnan(humiValue) || isnan(tempValue)) {
      lcd.setCursor(0, 1);
      lcd.print("Sensor Error!");
      return;
    }
  }

  // --- 显示当前温湿度 ---
  lcd.setCursor(0, 1);
  if (showTemperature) {
    lcd.print("TEMP(℃):");
    lcd.print(tempValue, 2); // 显示两位小数
  } else {
    lcd.print("HUM(%):");
    lcd.print(humiValue, 2);
  }
}

关键细节说明

  1. 非阻塞计时的重要性:用millis()代替delay(),这样计时、温湿度读取、LCD切换可以同时进行,不会出现程序卡顿的情况。如果用delay(),切换温湿度时时间会停止走,体验很差。
  2. LCD清行技巧:不用lcd.clear()(会清空整个屏幕),而是用16个空格覆盖第二行,保证第一行的时间持续显示。
  3. DHT11错误处理:加入isnan()判断传感器读取是否成功,如果失败就显示错误信息,避免出现乱码。
  4. 初始时间设置:因为没有RTC,每次上电后时间从代码里的hours、minutes、seconds初始值开始,你可以根据需要修改这些值。
  5. LCD I2C地址排查:如果LCD不显示内容,可能是地址不对。可以用I2C扫描程序确认地址,然后修改代码里的LiquidCrystal_I2C lcd(0x27, 16, 2);中的地址(常见地址是0x27或0x3F)。

如果调试时遇到问题,可以打开串口监视器,看看温湿度的读取值是否正常,时间更新是否准确。祝你项目顺利!

内容的提问来源于stack exchange,提问作者user9081078

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:36:35