# 🕒 LED 点阵智能挂钟

一个基于 ESP32 + HUB75 64×64 全彩 LED 点阵屏 的智能挂钟。固件源自开源项目 jnthas/clockwise,我在其基础上完成了硬件适配、稳定性改造与自定义表盘开发,并额外写了一个 Flutter 手机 App,可以随时把手机相册里的图片推到时钟上显示。


✨ 功能特性

  • 64×64 全彩点阵显示:HUB75E 接口、1/32 扫描,开启双缓冲整帧切换,画面无闪烁撕裂
  • WiFi 配网:内置 WiFiManager + Improv 串口配网,首次上电自动开热点,用手机填写 WiFi 即可
  • NTP 自动校时:ezTime 支持时区与夏令时,12/24 小时制可切换,开机 2 秒内立即出画面,NTP 后台同步
  • Web 设置后台:浏览器访问设备 IP 就能改亮度、旋转、时区、RGB/BGR 通道交换,无需重新烧录
  • 内置 7 种表盘:cw-cf-0x01 ~ 0x07,含数字时钟、日历、天气、图片轮播等
  • 自定义表盘:自己写的 CustomClockface —— 中央显示图片,右下角用 picopixel 小字体显示时间
  • 手机传图:Flutter App 把图片二值化为 RGB565 通过 HTTP POST 写入 ESP32 的 LittleFS,掉电不丢失
  • 断网降级:检测到 WiFi 断开时自动隐藏时间数字,只保留图片,避免显示错误时间

🛠️ 硬件清单

组件型号 / 说明
主控ESP32-WROOM-32(DOIT DevKit v1 兼容板)
显示屏64×64 全彩 LED 点阵模块(HUB75E 接口,1/32 扫描,P3/P4 间距)
电源5V / 2A 起(全屏点亮电流很大,建议 4A 以上)
外壳3D 打印相框式外壳(可选)
连线16P 排线 + 杜邦线

📌 引脚接线

HUB75 信号ESP32 GPIO说明
R1 / G1 / B125 / 26 / 27上半屏 RGB 数据
R2 / G2 / B214 / 17 / 13下半屏 RGB 数据
A / B / C / D32 / 33 / 21 / 15行地址低 4 位
E181/32 扫描面板必需(HUB75E 特有)
CLK / LAT / OE16 / 4 / 22时钟 / 锁存 / 使能
⚠️ 踩坑记录:E 线原本接在 GPIO12
GPIO12 是 ESP32 的 strapping 引脚,上电瞬间其电平决定 flash 供电电压(VDD_SDIO 3.3V / 1.8V)。屏幕信号线把它拉高会导致电压配置错误,表现为随机崩溃、无法烧录。
本项目已把 E 改到 GPIO18。同理,OLED / 任何外设都不要用 GPIO12。

🖥️ 固件架构

依赖版本(关键,不要随意升级)

; firmware/platformio.ini
[env:esp32doit-devkit-v1]
platform = espressif32@5.3.0          ; ESP-IDF 4.4.x / Arduino 2.0.x
board = esp32doit-devkit-v1
framework = arduino
lib_deps =
    ESP32-HUB75-MatrixPanel-I2S-DMA@3.0.12
    adafruit/Adafruit GFX Library
    trod bot/ezTime
    Improv-WiFi-Library
    WiFiManager
    ArduinoJson
    PNGdec
⚠️ HUB75 驱动 3.0.12 与 Arduino 内核 3.x(ESP-IDF 5.x)不兼容,编译阶段就会报 I2S / DMA 相关错误,必须停留在 espressif32@5.3.0。

关键改造点

位置改造内容
displaySetup()自定义全套 GPIO 映射,double_buff 开启双缓冲,亮度上限钳到 2%(5/255)
setup()开机 delay(2000) 等电源浪涌过去,避免 I2S 初始化时电压塌陷崩溃
ImageStore新增基于 LittleFS 的图片存储模块,带版本号,上传后表盘自动重载
CustomClockface新增表盘:中央图片 + 右下角小字时间,断网隐藏时间
loop()不阻塞等待 NTP,先出画面再后台同步

图片传输协议(App ↔ 固件约定)

HTTP POST /
Body: [uint16 宽(大端)][uint16 高(大端)][宽×高 个 uint16 RGB565(大端)]
存储: LittleFS 的 /image.bin

📱 手机上传 App

led_uploader_app 是一个 Flutter 应用(led_uploader v1.0.0),功能很纯粹:

  1. 从相册选图或直接拍照
  2. 本地缩放到 64×64、按亮度阈值二值化、转成 RGB565 大端字节流
  3. HTTP POST 到 192.168.4.1:80(ESP32 热点默认地址),支持自定义 IP / 端口
  4. 上传成功后时钟立即刷新

依赖:image ^4.1.3、http ^1.1.0、image_picker ^1.0.5

🚀 使用流程

第一步:烧录固件

cd clockwise-main/firmware
pio run -t upload
pio device monitor       # 115200 波特率

第二步:配网

  1. 首次上电,屏幕显示配置提示,同时开出一热点 Clockwise-XXXX
  2. 手机连上这个热点,浏览器打开 192.168.4.1
  3. 选择家里的 WiFi、填密码、设时区,保存后设备自动重启接路由器

第三步:调设置

浏览器访问设备在局域网里的 IP,可以改:

  • Display Bright — 亮度(建议 2~8,越大电流越高)
  • Display Rotation — 旋转 0/90/180/270
  • Swap Blue/Green — 面板是 RBG 而非 RGB 时勾选
  • Time Zone / NTP Server — 时区与校时服务器
  • Clockface — 切换表盘

第四步:传图

  1. 手机装 LED时钟上传_v1.0.apk
  2. 手机连到 ESP32 所在网络
  3. 打开 App → 选图 → 填 ESP32 的 IP → 上传

📥 下载

文件说明大小
clockwise-led-clock-source-v1.0.zip完整源码(固件 + Flutter App,已剔除编译产物)5.3 MB
led-clock-uploader-v1.0.apk手机上传 App(Android)5.6 MB
全部下载归档:https://unfamili.work/downloads/

📂 源码结构

LED时钟/
├── clockwise-main/                 # ESP32 固件(clockwise 改造版)
│   ├── firmware/
│   │   ├── platformio.ini          # 版本锁定 + 接线注释
│   │   ├── src/
│   │   │   ├── main.cpp            # 引脚映射 / 双缓冲 / 主循环
│   │   │   ├── CustomClockface.*   # 自定义表盘(图片 + 小字时间)
│   │   │   ├── ImageStore.h        # LittleFS 图片存储
│   │   │   ├── BatteryMonitor.h
│   │   │   └── gfx/
│   │   ├── clockfaces/             # cw-cf-0x02 ~ 0x07 内置表盘
│   │   └── lib/                    # cw-cf-0x01 / cw-commons / cw-gfx-engine
│   ├── main/                       # ESP-IDF 入口 + Kconfig
│   └── README.md                   # 上游说明(硬件清单 / 刷机流程)
└── led_uploader_app/               # Flutter 手机上传 App
    ├── lib/main.dart               # 全部逻辑:选图 / 缩放 / RGB565 / POST
    └── pubspec.yaml

🔗 相关资源


本项目用于嵌入式与 DIY 硬件学习,固件基于开源项目二次开发,仅供技术交流。