💡 划重点

  • 本方案面向每天依赖公交通勤的上班族,用 ESP32 搭配 ILI9341 彩色 TFT 屏,制作一个摆在桌面的公交到站播报器。设备平时处于深度休眠状态,早上按下唤醒键后,自动连接 WiFi 并通过 HTTP API 实时获取所选线路的预计到站时间,循环刷新显示剩余分钟数。全项目物料成本控制在 75 元以内,结构简单,无需焊接也能完成。

需求洞察

目标用户:每日固定时间出门、依赖 1‑2 条公交线路的上班族。

真实痛点:早晨时间紧张,频繁解锁手机查看公交到站容易打断出门节奏;手机通知容易被海量消息淹没,错过提醒;冬季或雨天,在手机地图上反复刷新体验极差。

为什么值得做:桌面播报器让信息“抬头即见”,减少手机依赖;ESP32 的深度休眠配合按键唤醒,几乎不耗电;75 元内的成本远低于商业智能屏,且完全可定制,适合极客和居家办公人群。

方案设计

整体采用四层架构:

通过 ESP32 内置 Wi-Fi 连接家庭路由器,使用 HTTP GET 请求公交实时到站 API(可申请高德或百度的公开接口,或自建简易转发服务)。JSON 数据包解析后提取目标线路、最近一辆车的距离站数或预计分钟数。

ESP32 主控作为核心。GPIO0 配置为 RTC 唤醒源,长按或短按唤醒深度休眠的芯片。唤醒后执行联网、拉取数据流程;若 30 秒内无新数据或用户未操作,自动再次进入深度休眠。GPIO 分配兼顾 SPI 屏与按键,避免干扰启动引脚。

ILI9341 2.8 寸彩色 TFT 屏显示:当前时间、线路名、剩余分钟数、车辆状态(“即将到站”、“还有 2 站”等)。颜色区分紧急程度,比如剩余<3 分钟显示红色背景。屏幕背光在休眠时关闭,唤醒后点亮。

每次成功获取数据后,将时间戳、线路、到站分钟数通过串口打印,也可通过板载 LED 闪烁指示网络状态。后期可扩展将日志上传到本地 NAS 或 HomeAssistant,形成出行记录。

物料清单

序号 物料名称 数量 用途 估算单价(元)
1 ESP32-WROOM-32 开发板 1 主控与 Wi-Fi 19
2 ILI9341 2.8寸 TFT 屏(SPI) 1 信息显示 28
3 轻触按键(6x6mm) 1 唤醒按钮 0.5
4 面包板 + 杜邦线 若干 连接电路 5
5 10KΩ 电阻 1 按键上拉 0.2
6 USB 供电线 1 供电 2
合计 54.7

*注:总成本远低于 75 元预算,可另配外壳或打印底座。*

接线与结构

遵循说明书中默认 GPIO,仅增加必用的上拉电阻。接线关系如下:

SCK → GPIO18

MOSI → GPIO23

CS → GPIO15

DC → GPIO2

RST → 可接 EN 或 3.3V(此处接 3.3V 保持不复位)

VCC → 3.3V

GND → GND

LED → 3.3V(可通过 GPIO 控制背光,但为简化暂接 3.3V)

一端接 GPIO0,另一端接 GND;同时 GPIO0 与 3.3V 之间接 10KΩ 上拉电阻,确保未按下时保持高电平。ESP32 的 RTC 唤醒管脚复用 GPIO0,唤醒后程序检测按键短按次数可设置不同线路选择。

微调理由:GPIO0 作为启动模式引脚,外部上拉不影响芯片上电,且自带内部弱上拉,增加外部 10K 仅增强抗干扰。如此接线可在深度休眠下仍识别按键下降沿唤醒。

核心代码

以下给出基于 Arduino 框架的骨架代码,依赖 TFT_eSPI 库和 ArduinoJson 解析库。示例中配置高德 API 格式,请自行替换 API Key 和线路参数。


#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI();

const char* ssid = "SSID";
const char* password = "PASS";
const char* apiUrl = "http://api.xxx.com/bus?line=102";

RTC_DATA_ATTR int bootCount = 0;
#define BUTTON_PIN 0

void setup() {
  Serial.begin(115200);
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.setTextColor(TFT_WHITE);
  
  WiFi.begin(ssid, password);
  int retry = 0;
  while (WiFi.status() != WL_CONNECTED && retry < 20) {
    delay(500);
    retry++;
  }
  
  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(apiUrl);
    int httpCode = http.GET();
    if (httpCode == 200) {
      String payload = http.getString();
      DynamicJsonDocument doc(1024);
      deserializeJson(doc, payload);
      int minutes = doc["data"]["arrival_min"];
      String line = doc["data"]["line_name"];
      
      tft.fillScreen(TFT_BLACK);
      tft.drawString("Line: " + line, 10, 40, 4);
      tft.drawString("In " + String(minutes) + " min", 10, 90, 4);
    }
    http.end();
  }
  delay(30000);  // 显示30秒
  esp_deep_sleep_start();
}

void loop() {
  // 未使用
}

*说明:* 程序从深度休眠唤醒后运行 setup(),网络失败则直接重进休眠,可通过串口检查状态。实际产品可加入按键消抖与线路切换逻辑,此处为简洁只展示单线路。

调试步骤

  1. 硬件检查:用万用表确认 3.3V、GND 无短路,TFT 背光亮起;按下按键时 GPIO0 电压由高变低。
  2. 固件烧录:在 Arduino IDE 中安装 ESP32 板包、TFT_eSPI 库、ArduinoJson 库。选择 ESP32 Dev Module,上传后打开串口监视器。
  3. Wi-Fi 连接:观察串口打印的 IP 地址,若持续连接失败,检查 SSID/密码,确认路由器 2.4GHz 频段开启。
  4. API 获取:先用浏览器或 curl 测试 API 链接,确保 JSON 返回格式与代码一致。若解析失败,调整 DynamicJsonDocument 容量。
  5. 显示校验:观察屏幕是否出现线路与时间文字。如果背光亮无内容,检查 SPI 引脚顺序,或调整 TFT_eSPI 的 User_Setup 文件匹配 GPIO。
  6. 休眠唤醒:断开 USB 后重新上电,等待 30 秒屏幕熄灭,按下按键设备应重新亮起并刷新数据。

设计图

公交到站桌面播报器结构flow
1
感知输入(Wi-Fi HTTP API、按键唤醒)
2
控制处理(ESP32 深度休眠与定时唤醒、JSON 解析)
3
执行反馈(ILI9341 彩色屏显示线路与剩余分钟、红灯预警)
4
数据上报(串口日志、可选 HomeAssistant 集成)