💡 划重点

  • 本项目为办公桌场景打造一款成本 55 元以内的智能番茄钟工位站姿提醒设备。以 RP2040 为主控,结合 OLED 屏幕、震动电机与双按键,实现番茄工作法定时、久坐站姿提醒、按键交互与状态可视化,软硬件全部开源,适合个人 DIY 或小批量教学实践。核心指标:30 分钟工作 / 5 分钟休息循环、每 45 秒震动提示挺直脊柱、OLED 实时显示倒计时与姿态图标

需求洞察

目标用户

长期伏案办公的知识工作者、程序员、远程办公人群及大学生,他们普遍存在“久坐成疾”与“注意力碎片化”两大难题。

真实痛点

  1. 持续久坐超过 1 小时后,腰椎和颈肩压力剧增,身体不自觉前倾或驼背,却缺乏即时提醒。
  2. 番茄钟类手机 APP 容易分散注意力,通知频繁反而打断心流;纯软件方案无法感知真实坐姿。
  3. 市面智能升降桌或穿戴设备价格动辄数百元,个人工位改造门槛高。

为什么值得做

低成本硬件 + 确定性功能闭环,能把番茄钟的效率管理和站姿健康管理融为一体。震动电机直接贴附椅背或置于工位表面,形成物理级提醒,比屏幕弹窗更不易被忽略。RP2040 的 PIO 与双核对定时任务友好,方便后续扩展无线日志或桌面小仪表。55 元内完成所有物料,真正可实现“一人一机”。

方案设计

感知层

控制层

执行层

日志 / 联网层

物料清单

名称 数量 用途 估算单价(元) 小计(元)
树莓派 Pico(RP2040) 1 主控板 22.0 22.0
0.96 寸 OLED 128×64 SPI 1 状态显示 12.0 12.0
震动电机模块(微型扁平) 1 坐姿/站姿提醒 3.5 3.5
微动按键 2 启停、重置 0.5 1.0
直插电阻 10kΩ 2 按键上拉备用 0.1 0.2
NPN 三极管 S8050 1 震动电机驱动 0.3 0.3
1kΩ 电阻(基极限流) 1 匹配三极管 0.1 0.1
面包板 + 杜邦线套装 1 连线与固定 8.0 8.0
热缩管 / 泡棉胶 少量 绝缘与固定电机 1.0 1.0
USB‑micro 数据线 1 供电与日志 3.0 3.0
合计 51.1

接线与结构

严格遵循给定 GPIO 并微调 SPI 信号线。

OLED SPI:CS=13, DC=14, SCK=18, MOSI=19, RST=17(原计划未指定 SCLK/MOSI/RST,补充后可与大部分 SPI OLED 模块兼容)。选用 RP2040 的 SPI0 外设,SCK=18, MOSI=19 为默认映射,接线整洁且支持 DMA 刷新。

震动电机:控制脚 GPIO15,通过 S8050 驱动。

按键:KEY1=GPIO6(启停),KEY2=GPIO7(重置),内部上拉,短按触发。

结构上,Pico 固定于面包板一端,OLED 用杜邦线引出竖立在视野正前方;震动电机用泡棉胶粘在椅背或桌沿,导线从面包板走线。所有元器件不超过 100×80mm 面积,可装入 3D 打印外壳(外壳暂不计入 55 元成本,可后期自制)。

核心代码

基于 Arduino IDE + Earle Philhower 的 RP2040 核心 (Mbed OS 亦可),使用 Adafruit_SSD1306 库。下面给出可编译的骨架。


#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_CS   13
#define OLED_DC   14
#define OLED_RST  17
Adafruit_SSD1306 display(128, 64, &SPI;, OLED_DC, OLED_RST, OLED_CS);

#define VIBE_PIN  15
#define KEY1_PIN  6
#define KEY2_PIN  7

enum State { IDLE, WORK, REST, PAUSE } state = IDLE;
uint32_t timerSec = 0;
uint32_t lastVibe = 0;
bool postureFlag = false;
char statusStr[20];

void setup() {
  pinMode(VIBE_PIN, OUTPUT);
  Serial.begin(115200);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
}

void loop() {
  static uint32_t lastMs = millis();
  if (millis() - lastMs >= 1000) {
    lastMs = millis();
    if (state == WORK || state == REST) {
      timerSec++;
      if (state == WORK && timerSec >= 1800) { // 30 分
        state = REST; timerSec = 0;
      } else if (state == REST && timerSec >= 300) { // 5 分
        state = WORK; timerSec = 0;
      }
    }
    if (state == WORK && (millis() - lastVibe >= 45000)) { // 45 秒提醒
      digitalWrite(VIBE_PIN, LOW);
      lastVibe = millis();
      postureFlag = true;
    }
    // 显示更新
    display.clearDisplay();
    display.setCursor(0,0);
    const char* stateText = (state==WORK)?"工作":(state==REST)?"休息":"暂停";
    snprintf(statusStr, sizeof(statusStr), "%s %02d:%02d", stateText, timerSec/60, timerSec%60);
    display.print(statusStr);
    if (postureFlag) {
      display.setCursor(0,40);
      display.print("请挺直");
      postureFlag = false;
    }
    display.display();
    // 串口日志
    Serial.print("{\"status\":\"");
    Serial.print(stateText);
    Serial.print("\",\"remain\":");
    Serial.print((state==WORK?1800:300)-timerSec);
    Serial.print(",\"posture\":");
    Serial.print(postureFlag?"true":"false");
    Serial.println("}");
  }
  // 按键扫描
  if (!digitalRead(KEY1_PIN)) {
    delay(50); if(!digitalRead(KEY1_PIN)) {
      state = (state == WORK || state == REST) ? PAUSE : WORK;
      while(!digitalRead(KEY1_PIN));
    }
  }
  if (!digitalRead(KEY2_PIN)) {
    delay(50); if(!digitalRead(KEY2_PIN)) {
      state = IDLE; timerSec = 0;
      while(!digitalRead(KEY2_PIN));
    }
  }
}

编译环境:安装 RP2040 板包和 Adafruit SSD1306 库,选择“Raspberry Pi Pico”即可。

调试步骤

  1. 接线检查:用万用表短接测试各 VCC/GND 通路,确保 OLED 和振动模块供电无短路。
  2. OLED 驱动:先烧录 SPI 扫描示例,确认 SCK、MOSI、CS、DC、RST 对应正确,屏幕能点亮并打印“Hello”。
  3. 按键测试:在 IDE 串口监视器打印按键状态,确认短按不抖动,长按识别正常。
  4. 震动测试:编写单独代码让 GPIO15 以 PWM 驱动电机,确认强度和续流二极管保护。
  5. 定时器联调:修改宏将工作周期临时改为 30 秒、休息 5 秒,观察状态切换与震动逻辑。
  6. 整机运行:黏贴振动电机至工位边缘,坐姿下实际体验 45 秒提醒是否明显,根据反馈调整震动时长。
  7. 串口日志:打开串口绘图器或 Python 脚本记录 json,验证数据连续性。

设计图

番茄钟工位站姿提醒结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报