💡 划重点
- 主控:ESP32,利用 Wi‑Fi 定时请求公交实时 API,低功耗待机。
- 屏幕:ILI9341 TFT,显示线路、剩余站数、预计到达时间。
- 唤醒:按键轻触点亮屏幕,超时自动息屏。
- 目标:上班族出门前快速确认公交位置,告别反复刷手机。
- 成本:整机 75 元以内,单件焊接即可完成。
需求洞察
目标用户
住在公交站点附近、每天固定时段通勤的上班族。用户需在出门前判断需要加快脚步还是可以慢走,避免错过刚走的那班车或长时间在站台等候。
真实痛点
手机查询公交信息需要解锁、打开 App、找到收藏线路、加载数据,步骤繁琐;冬天不愿掏手机,雨天操作不便;长时间亮屏耗电,频繁查询造成心理慌乱。用户真正需要的是一个摆在桌面或玄关、一瞥即知的固定设备。
为什么值得做
硬件成本极低,功能聚焦,只解决一件事:告诉用户下一班车何时到。相比手机查询,物理按键唤醒+大字体显示体验更好,也更接近传统闹钟或温湿度计的位置。对于非智能家居用户,这仍是增量市场,可 DIY 满足个性化需求。
方案设计
感知层
- 按键:轻触开关接 GPIO0,用于唤醒 MCU 和点亮屏幕。
- RTC 时钟:利用 ESP32 内部 RTC,在深度睡眠时计时,定时唤醒拉取 API。
- 无外部传感器:所有交通数据来自云端公交 API。
控制层
- 主控:ESP32‑WROOM‑32 模组,双核 240 MHz,内置 Wi‑Fi,支持 deep sleep 低功耗。
- 工作逻辑:
1. 上电后连接 Wi‑Fi,获取 NTP 时间。
2. 进入 light sleep 或 deep sleep,按设定的间隔(例如 60 秒)自动唤醒获取公交数据。
3. 按键唤醒时点亮屏幕并立即请求一次最新数据,显示 30 秒后自动息屏。
4. 若电池供电则更多使用 deep sleep,仅在唤醒时联网。
执行层
- 显示:2.4 寸 ILI9341 SPI TFT,分辨率 240×320。大字显示线路名、当前距站点站数、预计到站分钟。
- LED(可选):板载 LED 用于状态指示或网络连接提示。
- 蜂鸣器或振动马达(可选):预留 GPIO 可在车辆到达预警时发出声音,本方案暂不纳入成本,以字符颜色变化提示紧急性。
日志/联网层
- HTTP API:通过 ESP32 HTTPClient 定时 GET 城市公交实时数据接口(需注册开发者 key)。解析 JSON,提取目标线路的车辆列表、距离最近站点的进站站数或时间。
- Wi‑Fi 管理:通过 WiFiManager 库实现首次配网或自动重连。
- 数据上报(可选):将每次查询结果通过 MQTT 上传至 Home Assistant 或私有服务器,用于长期统计,本方案不强制。
物料清单
| 序号 | 物料名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|---|
| 1 | ESP32‑WROOM‑32 开发板 | 1 | 主控与联网 | 18 |
| 2 | 2.4″ ILI9341 SPI TFT 模块 | 1 | 显示公交信息 | 28 |
| 3 | 轻触按键 | 1 | 唤醒屏幕 | 0.5 |
| 4 | 10 kΩ 电阻 | 1 | 按键上拉 | 0.1 |
| 5 | 面包板 + 跳线 | 1 | 原型验证 | 5 |
| 6 | Micro‑USB 线 | 1 | 供电与烧录 | 3 |
| 7 | 3D 打印外壳或瓦楞纸壳 | 1 | 桌面摆放 | 5 (自打印估算) |
| 8 | 排针排母 | 若干 | 连接 | 2 |
| 合计 | 71.6 |
*成本控制在 75 元内,若使用自带 USB 供电的 ESP32 开发板,可省略额外电源模块。*
接线与结构
接线方案(基于 ESP32 开发板)
| ESP32 引脚 | 信号 | 连接至 |
|---|---|---|
| 3.3V | 电源正 | TFT VCC |
| GND | 电源地 | TFT GND, 按键另端 |
| GPIO18 | SCK | TFT SCK |
| GPIO23 | MOSI | TFT MOSI |
| GPIO15 | CS | TFT CS |
| GPIO2 | DC | TFT DC |
| GPIO0 | 按键输入 | 按键一脚 |
按键接线:轻触按键一脚接 GPIO0,另一脚接 GND;GPIO0 内部已通过 10 kΩ 上拉至 3.3V(多数开发板),若开发板未自带,需外部加 10 kΩ 上拉电阻,故清单中添加电阻一项。
理由:使用 GPIO0 作为唤醒源,ESP32 在 deep sleep 时可由 GPIO0 低电平唤醒,且不与其他 SPI 功能冲突。SPI 引脚沿用标准 VSPI 默认映射,保证 ILI9341 库的直接兼容。
结构建议:将 ESP32 与 TFT 堆叠或平置在壳体内,按键从前面板露出。屏幕用透明亚克力保护。USB 线从后方引出供电,方便摆在玄关柜。
核心代码
以下给出 MicroPython 骨架(ESP32 更适合快速原型,支持轻量级 sleep)。实际开发需根据公交 API 格式调整 JSON 解析。
import ili9341
import network
import urequests as requests
import time
import ntptime
# 硬件初始化
spi = SPI(2, baudrate=40000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
cs = Pin(15, Pin.OUT)
dc = Pin(2, Pin.OUT)
display = ili9341.ILI9341(spi, cs=cs, dc=dc)
button = Pin(0, Pin.IN, Pin.PULL_UP)
WIFI_SSID = 'your_ssid'
WIFI_PASS = 'your_password'
API_URL = 'http://your-bus-api.com/line?stopId=123'
def connect_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
for _ in range(20):
if wlan.isconnected():
break
time.sleep(0.5)
return wlan.isconnected()
def sync_time():
try:
ntptime.settime()
except:
pass
def fetch_bus_data():
try:
r = requests.get(API_URL, timeout=5)
data = r.json()
# 解析示例:目标线路最近的车辆预计到站分钟
eta_min = data.get('nextBusMinutes', 99)
return eta_min
except:
return -1
def show_info(minutes):
display.fill(0)
if minutes >= 0:
msg = f'Next: {minutes} min'
else:
msg = 'No data'
# 紧急提示变红
if 0 < minutes <= 2:
display.text('HURRY UP!', 20, 200, ili9341.color565(255,0,0))
def try_display():
if not button.value(): # 按键按下为低电平
if connect_wifi():
sync_time()
eta = fetch_bus_data()
show_info(eta)
time.sleep(30) # 显示30秒
display.fill(0)
else:
time.sleep(5)
display.fill(0)
def main():
# 检查唤醒原因,button 唤醒或定时器唤醒
import esp32
wake_reason = esp32.wake_reason()
if wake_reason == esp32.EXT0_WAKE: # GPIO0电平唤醒
try_display()
else: # 首次上电或定时器唤醒
if connect_wifi():
sync_time()
eta = fetch_bus_data()
show_info(eta)
time.sleep(30)
display.fill(0)
# 配置deep sleep,120秒后定时器唤醒,同时设置GPIO0为唤醒源
esp32.wake_on_ext0(pin=Pin(0), level=esp32.WAKEUP_ANY_LOW)
esp32.wake_on_timer(120000)
deepsleep()
main()
*该骨架实现按键唤醒显示、定时自动获取数据后睡眠的逻辑,可直接烧录到 ESP32。*
调试步骤
- 分步上电测试:仅连接 TFT,运行示例代码确保屏幕正常显示色块和文字。
- Wi‑Fi 联网:单独测试网络连接,打印获取到的 IP。
- API 对接:在 REPL 中手动调用 API 并打印 JSON,确认数据字段与显示内容匹配。
- 按键检测:短按按键,观察屏幕是否如期亮起与熄灭。
- 低功耗验证:进入 deep sleep 后测量电流,确保 USB 供电或移动电源可长时间运行。
- 整机联调:将所有功能整合,放在卧室模拟出门场景,检查数据更新频率与显示准确性。