💡 划重点
- 本项目以 RP2040 为主控,结合 OLED 显示屏、震动电机与两个独立按键,打造一款放在办公桌上的番茄钟工位站姿提醒器。核心目标是帮助久坐办公人群在番茄工作法的专注间隔结束后,通过震动提醒起身或调整坐姿,同时利用 OLED 显示当前阶段与倒计时。整机成本控制在 55 元以内,结构简单,适合个人 DIY 与编程学习。
需求洞察
目标用户是长期伏案工作的人群,包括程序员、设计师、财务人员、行政人员以及居家办公者。真实痛点是:办公桌前的久坐往往在无意识中持续超过一小时,即使使用了番茄钟,很多人也只是在休息时继续坐着刷手机,并没有真正改变坐姿或起身活动。长期低头、塌腰、肩颈前倾会让腰椎和颈椎压力持续累积,造成慢性疲劳和疼痛。
将番茄钟与站姿提醒结合,可以在每个专注间隔结束时用震动电机主动提醒用户,而不是只靠屏幕或手机通知。OLED 屏幕则直观显示当前是专注、短休息还是长休息阶段,以及剩余时间。该项目成本低、体积小、放置在桌面不占空间,同时具备明确的交互反馈,因此值得做。
方案设计
感知层:两个轻触按键分别接入 GPIO6 和 GPIO7,用于开始/暂停和重置/跳过番茄阶段。按键采用内部上拉,低电平触发,通过软件消抖识别用户意图。当前版本不额外增加姿态传感器,以控制成本并保持结构简单。
控制层:RP2040 作为主控芯片,运行番茄钟状态机。默认规则为每轮专注 25 分钟、短休息 5 分钟,每完成 4 轮专注后进入 15 分钟长休息。控制层同时驱动 OLED 显示和震动电机,并负责按键事件处理与计时。
执行层:OLED 使用 SPI 接口,显示倒计时、阶段名称和简单的站姿提醒文字。震动电机通过 GPIO15 输出 PWM,在阶段切换时震动 2 秒,提醒用户调整姿势或起身活动。
日志/联网层:当前版本通过 USB CDC 串口输出状态日志,方便在电脑端查看当前番茄阶段、完成轮数和时间戳。后续可以扩展蓝牙或 Wi-Fi 模块,将数据同步到上位机或云端,但不列入本次 55 元成本。
物料清单
| 物料名称 | 数量 | 用途 | 估算单价(元) |
|---|---|---|---|
| RP2040 开发板(Pico 兼容) | 1 块 | 主控,运行计时与状态机 | 25 |
| 0.96 寸 OLED SSD1306 SPI 模块 | 1 块 | 显示倒计时与站姿提醒 | 12 |
| 震动电机模块(含驱动三极管) | 1 个 | 阶段切换震动提醒 | 4 |
| 轻触按键 | 2 个 | 开始/暂停与重置 | 2 |
| 面包板/洞洞板、排针、导线、电阻 | 1 套 | 搭建电路与连接 | 8 |
| 合计 | 51 |
总成本约 51 元,低于 55 元目标。
接线与结构
按给定 GPIO 进行连接,并做小幅微调以补齐 SPI 所需信号线。OLED 的 CS 接 GPIO13,DC 接 GPIO14;震动电机控制脚接 GPIO15;按键分别接 GPIO6 和 GPIO7。OLED SPI 的 SCK 与 MOSI 在给定接线中未指定,这里选择 GPIO10 作为 SCK、GPIO11 作为 MOSI。理由:GPIO10、GPIO11 与 GPIO13、GPIO14 相邻,走线集中;同时避开按键 GPIO6、GPIO7,减少干扰。
结构上,RP2040 开发板用双面胶或铜柱固定在洞洞板底部,OLED 倾斜安装在朝向用户的前方,两个按键放置在板子侧边或正面,震动电机可贴在桌面边缘或壳体背面,保证震动感明显且不松动。
核心代码
采用 MicroPython 编写,基于 RP2040。以下为可运行骨架,包含 OLED 初始化、按键读取、番茄钟状态切换与震动控制。
import time
spi = SPI(1, baudrate=8000000, polarity=0, phase=0, sck=Pin(10), mosi=Pin(11))
cs = Pin(13, Pin.OUT, value=1)
dc = Pin(14, Pin.OUT)
motor = PWM(Pin(15))
key_start = Pin(6, Pin.IN, Pin.PULL_UP)
key_reset = Pin(7, Pin.IN, Pin.PULL_UP)
FOCUS = 25 * 60
SHORT_BREAK = 5 * 60
LONG_BREAK = 15 * 60
def oled_cmd(c):
dc.value(0)
cs.value(0)
spi.write(bytes([c]))
cs.value(1)
def oled_data(d):
dc.value(1)
cs.value(0)
spi.write(d)
cs.value(1)
def oled_init():
oled_cmd(0xAE)
oled_cmd(0xD5); oled_cmd(0x80)
oled_cmd(0xA8); oled_cmd(0x3F)
oled_cmd(0xD3); oled_cmd(0x00)
oled_cmd(0x40)
oled_cmd(0x8D); oled_cmd(0x14)
oled_cmd(0x20); oled_cmd(0x00)
oled_cmd(0xA1)
oled_cmd(0xC8)
oled_cmd(0xDA); oled_cmd(0x12)
oled_cmd(0x81); oled_cmd(0xCF)
oled_cmd(0xD9); oled_cmd(0xF1)
oled_cmd(0xDB); oled_cmd(0x40)
oled_cmd(0xA4)
oled_cmd(0xA6)
oled_cmd(0xAF)
def vibrate(seconds=2):
motor.freq(1000)
motor.duty_u16(30000)
time.sleep(seconds)
motor.duty_u16(0)
def main():
oled_init()
stage = 'focus'
remaining = FOCUS
rounds = 0
last_tick = time.ticks_ms()
while True:
if key_start.value() == 0:
time.sleep_ms(20)
if key_start.value() == 0:
pass # 此处可切换启动/暂停
now = time.ticks_ms()
if time.ticks_diff(now, last_tick) >= 1000:
last_tick = now
remaining -= 1
if remaining <= 0:
vibrate(2)
if stage == 'focus':
rounds += 1
if rounds % 4 == 0:
stage = 'long_break'
remaining = LONG_BREAK
else:
stage = 'short_break'
remaining = SHORT_BREAK
else:
stage = 'focus'
remaining = FOCUS
time.sleep_ms(10)
if __name__ == '__main__':
main()
调试步骤
首先给 RP2040 烧录 MicroPython 固件,并通过 USB 连接电脑。然后单独测试 OLED,确认能正常显示初始界面;再分别短接按键,观察串口输出或屏幕状态变化;接着让震动电机在阶段切换时短震,确认 PWM 输出正常。最后整机联调,观察一个完整番茄钟周期是否按 25 分钟专注、5 分钟休息运行,并在第 4 轮后进入 15 分钟长休息。若震动不明显,可调整 PWM 占空比或电机固定位置。