💡 划重点
- 本项目基于 XIAO ESP32-S3 主控芯片,结合 MPU6050 六轴姿态传感器与振动反馈单元,打造一款可贴合于背部或肩颈区域的“矫正坐姿背带贴片”。系统通过实时检测人体躯干倾角与弯腰幅度,在识别到不良坐姿(如低头、驼背、侧倾)时触发振动马达,形成即时触觉提醒,引导使用者主动恢复正确坐姿。设备采用锂电池供电,整体硬件成本控制在 75 元以内,面向学生与
需求洞察
目标用户:长时间伏案学习的中学生、大学生,以及每日面对电脑工作超过六小时的办公室白领。
真实痛点:绝大多数人意识到“坐直”的重要性,但在专注状态下(写作业、写代码、处理文档)会无意识前倾或塌腰。传统矫正带属于物理束缚,佩戴不适且限制活动;智能坐垫仅能检测臀部压力,无法感知上半身姿态;手机摄像头监测则存在隐私与部署成本问题。真正需要的不是“强制纠正”,而是在错误姿势刚发生且可逆时,给予一个轻微的、不打断注意力的信号。
为什么值得做:颈椎病与腰椎间盘突出正呈现低龄化趋势,预防成本远低于治疗成本。一个不足 75 元的可穿戴小装置,能够在不打扰他人、不束缚动作的前提下,通过触觉神经通路建立“姿势-提醒”的条件反射循环,长期使用即可改善肌肉记忆。该方案体积小、功耗低、成本可控,具备 DIY 量产的可能性,也适合作为硬件编程教学的综合实践项目。
方案设计
系统整体分为四个逻辑层面:
- 感知层:采用 MPU6050 六轴传感器(三轴加速度 + 三轴陀螺仪),贴附于肩胛骨之间或背部脊柱位置。通过算法融合加速度与角速度数据,计算俯仰角(Pitch)与横滚角(Roll)。当 Pitch 角大于设定阈值(如 25-30°)且持续超过 2 秒,判定为“低头驼背”姿态;当 Roll 角偏移过大,判定为“侧斜”姿态。
- 控制层:XIAO ESP32-S3 内置 Xtensa LX7 双核处理器,主频 240MHz,足以运行姿态解算逻辑。软件设定防抖时间窗口(如 2 秒),避免打哈欠、伸懒腰等短暂动作引发误报。同时设置冷却时间(如 5 秒),防止连续震动造成麻木感。
- 执行层:采用扁平微型振动马达(直径 10mm,厚度 3mm),通过 GPIO 输出 PWM 信号驱动三极管(如 S8050)进行功率放大。根据姿态严重程度分级反馈:轻度前倾->单次短震(200ms);中度歪斜->双次中震(300ms 间隔 150ms);长时间塌腰->连续长震(500ms 停顿 200ms 循环三次)。
- 日志/联网层:XIAO ESP32-S3 具备 Wi-Fi 与 BLE 能力。预留蓝牙低功耗通道,可将每日不良坐姿次数、累计时长等统计数据发送至手机微信小程序或手机 APP。若无手机连接,则在板载 Flash 中存储最近七天的行为摘要,通过 USB 导出。
物料清单
| 序号 | 物料名称 | 规格/型号 | 数量 | 用途说明 | 估算单价(元) | 小计(元) |
|---|---|---|---|---|---|---|
| 1 | 主控开发板 | XIAO ESP32-S3 | 1 | 核心控制、姿态解算、无线通信 | 35.00 | 35.00 |
| 2 | 姿态传感器 | MPU6050 模块(GY-521) | 1 | 检测倾角与角速度 | 6.50 | 6.50 |
| 3 | 振动马达 | 扁平纽扣式振动电机 10mm | 1 | 触觉反馈输出 | 2.80 | 2.80 |
| 4 | 驱动三极管 | S8050 + 1kΩ 基极电阻 | 1套 | 放大 GPIO 驱动电流 | 0.50 | 0.50 |
| 5 | 锂电池 | 3.7V 400mAh 聚合物电池(带保护板) | 1 | 便携供电 | 9.00 | 9.00 |
| 6 | 充电管理 | TP4056 模块(Type-C 母座) | 1 | USB-C 充电、过充保护 | 2.50 | 2.50 |
| 7 | 升压稳压 | MT3608 升压模块(调至 5V) | 1 | 为 ESP32-S3 提供稳定 5V | 3.50 | 3.50 |
| 8 | 背带载体 | 弹性尼龙背带 + 魔术贴 | 1 | 贴合背部固定硬件 | 8.00 | 8.00 |
| 9 | 结构壳体 | 3D 打印 ABS 小盒(40x30x15mm) | 1 | 固定 PCB 与电池 | 5.00 | 5.00 |
| 10 | 辅助材料 | 杜邦线、热缩管、焊锡丝、双面胶 | 若干 | 连接与固定 | 2.00 | 2.00 |
| 11 | 电源开关 | SS12D00 滑动开关 | 1 | 总电源开关 | 0.60 | 0.60 |
| 合计 | 75.40 |
成本控制说明:上述合计 75.40 元,若在批量采购或使用国产替代传感器(如 QMI8658)时可微调至 75 元内。TP4056 模块自带 Type-C 母座,直接满足 USB-C 充电需求,无需额外焊接。
接线与结构
接线定义(按项目指定 GPIO) :
| 模块 | 引脚 | 连接到 XIAO ESP32-S3 | 备注 |
|---|---|---|---|
| MPU6050 | VCC | 3.3V | 模块供电 |
| MPU6050 | GND | GND | 共地 |
| MPU6050 | SDA | GPIO5 | I2C 数据线,使用内部上拉 |
| MPU6050 | SCL | GPIO6 | I2C 时钟线 |
| MPU6050 | AD0 | GND | 地址 0x68 |
| 振动马达驱动 | 基极电阻 | GPIO7 | 输出高电平触发震动 |
| TP4056 | OUT+ | 锂电池正极 / 升压模块 IN+ | 电池输出端 |
| TP4056 | OUT- | 锂电池负极 / 系统 GND |
微调说明:原方案默认 MPU6050 接 5/6 引脚,符合 ESP32-S3 任意 GPIO 均可配置为 I2C 的特性,故直接沿用。震动马达驱动电路需要 GPIO7 输出 3.3V 逻辑电平,经三极管放大后驱动马达(马达工作电压 3V,电流约 80mA),不可直接接 GPIO。
结构布局:
- 将 MPU6050 远离马达,避免马达振动噪声干扰传感器数据,中间用一块薄海绵隔离。
- 电池位于壳体最底层,PCB 板位于中层,XIAO ESP32-S3 与 MPU6050 用排针垂直插接。
- 背带主体采用弹性涤纶织带,宽度 5cm,硬件盒通过魔术贴固定在肩胛骨下缘偏上位置(约 T4-T6 椎骨高度)。
- 充电口朝上,侧面留滑动开关孔位。
核心代码
以下为适用于 XIAO ESP32-S3 的 Arduino 框架代码骨架,通过 PlatformIO 编译。代码实现了姿态读取、阈值判断与震动触发。
#include <Wire.h>
#include <MPU6050.h>
MPU6050 mpu;
const int VIB_PIN = 7; // 震动马达 GPIO7
const float PITCH_THRESHOLD = 25.0; // 俯仰角阈值,低头超过25°
const float ROLL_THRESHOLD = 15.0; // 横滚角阈值,侧倾超过15°
const unsigned long DURATION_MS = 2000; // 不良姿态持续2秒才触发
const unsigned long COOLDOWN_MS = 5000; // 两次提醒间隔5秒
unsigned long badPostureStart = 0;
unsigned long lastVibrateTime = 0;
bool badPostureActive = false;
void setup() {
pinMode(VIB_PIN, OUTPUT);
digitalWrite(VIB_PIN, LOW);
Wire.begin(5, 6); // GPIO5=SDA, GPIO6=SCL
mpu.initialize();
if (mpu.testConnection()) {
// 可以加一点状态指示
}
}
void loop() {
// 读取六轴原始数据
mpu.getMotion6(&ax;, &ay;, &az;, &gx;, &gy;, &gz;);
// 将加速度归一化并计算 Pitch 与 Roll(单位:度)
float accX = ax / 16384.0;
float accY = ay / 16384.0;
float accZ = az / 16384.0;
float pitch = atan2(accX, sqrt(accY * accY + accZ * accZ)) * 180.0 / PI;
float roll = atan2(accY, sqrt(accX * accX + accZ * accZ)) * 180.0 / PI;
// 姿态判断逻辑
bool isBadPosture = (pitch > PITCH_THRESHOLD) || (roll > ROLL_THRESHOLD) || (roll < -ROLL_THRESHOLD);
unsigned long now = millis();
if (isBadPosture) {
if (!badPostureActive) {
badPostureStart = now;
badPostureActive = true;
}
// 持续时间超过阈值且不在冷却期
if ((now - badPostureStart >= DURATION_MS) && (now - lastVibrateTime >= COOLDOWN_MS)) {
// 触发震动马达:连续两次 300ms 震动,间隔 150ms
digitalWrite(VIB_PIN, HIGH);
delay(300);
digitalWrite(VIB_PIN, LOW);
delay(150);
digitalWrite(VIB_PIN, HIGH);
delay(300);
digitalWrite(VIB_PIN, LOW);
lastVibrateTime = millis();
// 可以在此处记录日志或通过 BLE 发送数据
}
} else {
badPostureActive = false;
badPostureStart = 0;
}
delay(50); // 20Hz 采样率,足够感知慢速姿态变化
}
代码要点说明:
Wire.begin(5, 6)显式指定 SDA 与 SCL 引脚。- 使用
atan2直接计算倾角,无需额外库。 - 阈值与时间窗口均为常量,可通过宏定义调整。
- 若需上传数据,可在
lastVibrateTime更新处调用 BLE 蓝牙库(如BLEDevice)发送统计值。
调试步骤
- 基本通电测试:先不连接马达,仅给 XIAO 烧录空白程序,确认板载 LED 正常呼吸闪烁,TP4056 充电指示灯亮起,测量电池端输出电压约 3.7-4.2V。
- I2C 通信验证:使用 Arduino 的 I2C 扫描例程(
Wire库扫描 0x68 地址)确认 MPU6050 能被识别。若失败,检查 SDA/SCL 是否接反、上拉电阻是否缺失(GY-521 板载 10kΩ 上拉,通常无需外接)。
- 姿态数据可视化:连接串口监视器(波特率 115200),编写临时脚本每 100ms 打印一次
pitch与roll值。将板子平放读数应接近 0°,竖直立起读数约 90°,倾斜 30° 则读数应在 28-32° 之间(误差允许 2°)。
- 震动驱动确认:使用万用表二极管档测量 GPIO7 输出的高电平电压(应约 3.3V)。接好三极管电路后,短接 GPIO7 与 3.3V 引脚,马达应转动,若带偏心锤则有明显振动感。
- 阈值整定:将背带穿在身上,模拟正常坐姿(挺直)与伏案低头姿势,观察串口打印的 Pitch 值变化。若坐直时读数仍大于 10°,说明背带贴合位置或传感器方向有偏移,需微调安装角度,或者将目标阈值设为“坐直值 + 15°”作为动态基准。
- 整机佩戴测试:连续运行 30 分钟,记录是否出现误触发(如伸懒腰、扭头看旁边)。若误报频繁,增大
DURATION_MS至 3000ms 或提高阈值 5°。若该提醒时不提醒,适当降低阈值。
- 充电与续航测试:充满电后,连续运行 8 小时,观察电池电压下降曲线。若不足 6 小时,考虑优化睡眠模式(未触发姿态变化时进入 modem 休眠)。
- 信号完整性检查:在震动马达启动瞬间,用示波器(或逻辑分析仪)观察 MPU6050 的 SDA/SCL 线上是否有毛刺干扰。若存在,可在马达两端并联 100nF 电容并靠近马达放置。
设计图
流程说明:感知输入由 MPU6050 完成,数据通过 I2C(GPIO5/6)送入 XIAO ESP32-S3 主控;进行姿态解算与阈值判断后,控制层输出 PWM 信号至 GPIO7,经三极管放大驱动振动马达,实现执行反馈。同时,控制层可将不良姿态统计数据打包,通过蓝牙 BLE 对外广播,供手机端接收上报。整个流程循环运行,无外部干预。