Arduino 实时天气时钟:OLED 显示时间、日期与温度
核心硬件清单
- Arduino Uno ×1
- DS3231 RTC 模块 ×1 - 高精度(±2ppm, 0-40°C),带备用电池(CR2032)
- SSD1306 OLED 显示屏 (128×64) ×1 - SPI 接口(本项目),也支持 I2C
- LM35 温度传感器 ×1 - 模拟输出,10mV/°C,量程 -55~150°C
- 面包板、跳线 若干
电路连接详解
OLED (SPI 模式)
| OLED 引脚 | Arduino 引脚 | 功能 |
|---|---|---|
| CS | D10 | 片选 |
| DC | D9 | 数据/命令 |
| RES | D8 | 复位 |
| D1 (MOSI) | D11 | 数据 |
| D0 (SCK) | D13 | 时钟 |
| VCC | 5V | 供电(模块自带 3.3V LDO) |
| GND | GND | 共地 |
DS3231 (I2C 模式)
| DS3231 引脚 | Arduino 引脚 |
|---|---|
| SDA | A4 |
| SCL | A5 |
| VCC | 5V |
| GND | GND |
LM35
- VCC → 5V
- OUT → A0
- GND → GND
软件库依赖
DS3231.h- jarzebski/Arduino-DS3231(库管理器可装)Adafruit_SSD1306.h+Adafruit_GFX.h- 官方库
完整固件代码(已修正语法、添加注释)
#include <Wire.h>
#include <DS3231.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ===== OLED SPI 引脚 =====
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_DC 9
#define OLED_CS 10
#define OLED_RESET 8
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
// ===== 传感器与 RTC =====
DS3231 rtc(Wire); // 使用 Wire (A4/A5)
const int sensorPin = A0;
float temperature;
void setup() {
pinMode(sensorPin, INPUT);
rtc.begin();
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
display.setTextColor(WHITE);
// 首次运行取消注释设置时间
// rtc.setDOW(WEDNESDAY);
// rtc.setTime(19, 2, 0); // 24小时制
// rtc.setDate(7, 12, 2017); // 日,月,年
// 启动画面
display.setTextSize(2);
display.setCursor(0, 0);
display.println(" Weather");
display.setCursor(0, 17);
display.println(" Clock ");
display.display();
delay(5000);
}
void loop() {
// 读取 LM35 温度
int raw = analogRead(sensorPin);
temperature = raw * 500.0 / 1024.0; // 5V/1024 * 100 = 500/1024 ≈ 0.488 mV/LSB → °C
// 刷新显示
display.clearDisplay();
// 时间 (大字体)
display.setTextSize(2);
display.setCursor(20, 0);
display.print(rtc.getTimeStr()); // "HH:MM:SS"
// 日期 + 星期 (小字体)
display.setTextSize(1);
display.setCursor(0, 15);
display.print(rtc.getDateStr()); // "DD/MM/YYYY"
display.setCursor(70, 15);
display.print(rtc.getDOWStr()); // "MON" 等
// 温度
display.setCursor(20, 25);
display.print("Temp: ");
display.print(temperature, 1); // 1位小数
display.print(" C");
display.display();
delay(1000);
}
关键技术细节
温度计算公式推导
LM35 输出 10mV/°C,Arduino 10-bit ADC 参考 5V:
Voltage = raw * 5.0 / 1024.0 (V)
Temp(°C) = Voltage / 0.01 = raw * 500.0 / 1024.0
代码中 500/1023 为近似,建议用 500.0/1024.0 提升精度。
DS3231 优势
- 内置温补晶振 (TCXO),年漂 < ±1 分钟
- 掉电走时靠纽扣电池,无需联网校时
- 提供可编程闹钟、方波输出、温度寄存器
OLED 显示优化
clearDisplay()每帧清屏防止残影- 分字号显示:时间大号醒目,日期/温度小号紧凑
- 坐标手动排版,适配 128×64 分辨率
常见问题与调试
| 现象 | 原因 | 对策 |
|---|---|---|
| OLED 不亮/花屏 | SPI 接线错误、供电不足、库版本不匹配 | 核对引脚、外接 5V 供电、更新 Adafruit_SSD1306 库 |
| 时间不准/重置后归零 | DS3231 备用电池耗尽、未首次设置时间 | 更换 CR2032、上传带设置时间的代码运行一次再注释 |
| 温度读数偏高 | LM35 自热、面包板接触电阻、ADC 参考电压偏差 | 传感器离 MCU 远一点、用 3.3V 基准+分压、或改用 DS18B20 |
| 中文/星期乱码 | 库默认英文星期缩写 | 手动映射:const char* dow[]={"SUN","MON",...}; |
进阶扩展功能
- 多传感器融合:加入 BME280(温湿度气压)、BH1750(光照)、MH-Z19(CO2)
- 网络校时:换用 ESP32/ESP8266,NTP 自动同步,弃用 DS3231
- 图形化 UI:绘制温度趋势曲线、湿度条形图、天气图标(需更大 Flash)
- 低功耗待机:OLED 关屏 + MCU 睡眠 + RTC 闹钟唤醒,按键/运动唤醒显示
- 外壳设计:3D 打印桌面座、壁挂盒,集成旋钮编码器调整时区/显示模式
教学价值总结
本项目集成了 RTC 实时时钟、模拟传感器读取、SPI/OLED 图形显示、字符串格式化 等核心嵌入式技能,代码量精简(<100 行),硬件成本低(~¥60),是「万年历/环境监测」类入门项目的标准范式。通过替换传感器与显示模块,可快速衍生智能家居面板、工业现场仪表、车载行车电脑等应用。
制造工艺
- Satellite CCRMA 套件:构建传感器驱动的音频效果器
- 复古 Numitron 管时钟:Arduino Nano 驱动,低温可靠省电
- 自制 Arduino 伊斯兰祷告时间实时时钟
- 用 Arduino UNO 和 OLED 显示屏制作经典 Pong 游戏:分步教程
- 精准文字时钟:分钟级文字显示时间
- 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
- Arduino Due 驱动 3.2″ TFT 实现温度监测与实时时钟
- 用 Arduino UNO 制作柏林时钟 – DIY LED 矩阵时钟
- 基于 Arduino Mega 与 Nextion 显示屏的交互式气象站
- TM1637 数码管时钟:Arduino Nano 实现时间设定与闹钟
- BME280 环境数据实时显示于 Nextion 触摸屏——Visuino 图形化开发
- 用 DS1302 RTC 和 Arduino UNO 制作可靠闹钟