1. 项目概述:当传统坐垫遇上STM32
去年冬天,我在连续加班一周后腰酸背痛得厉害,这才意识到自己每天在电脑前要坐10小时以上。市面上那些记忆棉坐垫虽然舒服,但既不能提醒我起来活动,也无法解决冬天坐垫冰凉、夏天闷热的问题。于是萌生了一个想法:用STM32做个会"思考"的智能坐垫。
这个坐垫的核心是一块STM32F103C8T6最小系统板,它就像坐垫的"大脑",通过分布在坐垫各处的传感器实时监测使用状态。压力传感器阵列能感知臀部压力分布,不仅知道你是否坐着,还能判断坐姿是否端正;SHT30温湿度传感器时刻监测坐垫微环境;当检测到久坐或环境不适时,系统会自动开启通风/加热,并通过语音提醒你该活动了。所有数据都能通过蓝牙同步到手机APP,上班族、学生党、程序员都能从中受益。
2. 硬件架构设计解析
2.1 主控芯片选型考量
选择STM32F103C8T6主要基于三点考量:首先是性价比,这款Cortex-M3内核的MCU价格不到20元,却拥有72MHz主频和20KB RAM,足够处理多传感器数据;其次是生态完善,标准库和HAL库资料丰富,方便快速开发;最后是外设丰富,自带多个ADC、定时器和USART接口,正好满足我们的需求。
实际开发中发现,使用CubeMX配置时要注意ADC采样周期设置。压力传感器信号需要较稳定的采样,建议将ADC时钟分频设为PCLK2/8,采样周期设为239.5周期。
2.2 传感器模块配置方案
2.2.1 压力检测方案对比
测试了三种压力检测方案:
- 方案一:薄膜压力传感器(FSR)
- 优点:厚度仅0.2mm,可嵌入坐垫
- 缺点:线性度差,需多点校准
- 方案二:应变片+惠斯通电桥
- 优点:测量精确
- 缺点:安装复杂
- 方案三:成品压力传感器模块
- 优点:即插即用
- 缺点:体积较大
最终选择方案一,在坐垫布置4个FSR传感器(前左、前右、后左、后右),通过分压电路接入STM32的4路ADC。当某区域压力值持续超过阈值(实测1.2V对应60kg体重)即判定为就坐状态。
2.2.2 环境监测模块选型
温湿度传感器对比了DHT11和SHT30:
- DHT11价格低但精度差(湿度±5%,温度±2℃)
- SHT30虽然贵3倍,但精度高(湿度±2%,温度±0.2℃),且支持I2C通信
选用SHT30后,发现其I2C时序要求严格,必须按照手册配置:
c复制// SHT30初始化代码示例
void SHT30_Init(void) {
uint8_t cmd[2] = {0x24, 0x00}; // 高精度测量命令
HAL_I2C_Master_Transmit(&hi2c1, 0x44<<1, cmd, 2, 100);
HAL_Delay(20); // 必须等待测量完成
}
2.3 执行机构设计细节
2.3.1 加热系统实现
采用12V/20W碳纤维加热膜,通过MOS管(IRLZ44N)控制通断。关键点是PWM频率设置:
c复制TIM3->PSC = 71; // 1MHz计数频率
TIM3->ARR = 999; // 1kHz PWM频率
实测发现低于500Hz会听到线圈噪音,高于5kHz则MOS管发热明显,1kHz是最佳平衡点。
2.3.2 通风系统优化
最初选用普通电脑风扇,但风量不足且噪音大(45dB)。改用涡轮风机(型号EFB0512HA)后,风量提升3倍,噪音降至32dB。需注意启动电流较大(1.2A),要在电源处并联4700μF电容。
3. 软件架构与核心算法
3.1 主程序状态机设计
系统采用事件驱动型状态机,核心代码如下:
c复制typedef enum {
IDLE_STATE,
SEATED_STATE,
WARNING_STATE,
ADJUSTING_STATE
} SystemState;
void System_Task(void) {
static uint32_t seatedTimer = 0;
switch(currentState) {
case IDLE_STATE:
if(IsUserSeated()) {
currentState = SEATED_STATE;
seatedTimer = HAL_GetTick();
}
break;
case SEATED_STATE:
if(!IsUserSeated()) {
currentState = IDLE_STATE;
} else if(HAL_GetTick() - seatedTimer > 30*60*1000) { // 30分钟
currentState = WARNING_STATE;
}
break;
// 其他状态处理...
}
}
3.2 坐姿识别算法
通过4路压力值计算重心坐标:
c复制typedef struct {
float x; // 前后方向(-1:完全靠后,1:完全靠前)
float y; // 左右方向(-1:完全靠左,1:完全靠右)
} CenterOfPressure;
CenterOfPressure CalculateCOP(void) {
float total = fl + fr + bl + br; // 四个传感器值
return (CenterOfPressure){
.x = ((fr+br)-(fl+bl))/total,
.y = ((fl+fr)-(bl+br))/total
};
}
当x<-0.6判定为"瘫坐",x>0.4为"前倾",y绝对值>0.7为"侧坐"。
3.3 环境调控策略
温湿度控制采用模糊逻辑:
- 温度<18℃:加热100%
- 18-22℃:加热50%
- >26℃:通风100%
- 湿度>65%:通风线性增加(每5%湿度增加20%风量)
4. 蓝牙通信协议设计
4.1 数据帧格式定义
使用自定义二进制协议提高传输效率:
code复制帧头(0xAA) | 长度(1B) | 命令字(1B) | 数据(NB) | 校验和(1B)
手机APP发送的控制命令示例:
code复制AA 03 01 64 68 // 设置加热强度100%
坐垫上传的传感器数据帧:
code复制AA 0D 02 01 17 3C 00 64 00 00 01 00 00 00 9A
// 解析:温度23℃,湿度60%,压力100,状态正常
4.2 数据同步机制
采用"手机主动查询+坐垫事件上报"混合模式:
- APP每5秒发送查询命令(0x03)
- 坐垫状态变化时立即上报(如久坐提醒)
- 增加2秒防抖处理,避免频繁上报
调试时发现HC-05模块的AT+UART必须设置为115200bps,8N1,否则会出现数据截断。
5. 电源管理与低功耗优化
5.1 供电方案选择
系统需要三种电压:
- 12V(加热/风机):由外部适配器提供
- 5V(传感器):通过LM2596降压获得
- 3.3V(MCU):AMS1117稳压
实测整机待机电流80mA,全功率运行时可达1.5A,建议使用≥2A的电源适配器。
5.2 低功耗策略
当检测到无人就坐超过5分钟时:
- 关闭所有执行机构
- 传感器采样率从10Hz降至1Hz
- OLED进入休眠模式
- 蓝牙保持连接但停止广播
通过上述措施,待机电流降至35mA,节能效果显著。
6. 结构设计与安装要点
6.1 坐垫层叠结构
从下到上共五层:
- 底层:1mm铝板(散热)
- 加热层:碳纤维膜
- 缓冲层:高密度海绵(开孔用于通风)
- 传感器层:FSR阵列
- 表面层:透气网布
6.2 走线注意事项
- 加热膜引线要用硅胶线(耐高温)
- 传感器线缆要走蛇形避免拉扯
- 所有线束用尼龙扎带固定
- 电路板用3M双面胶粘贴在铝板上散热
7. 常见问题排查指南
7.1 压力检测异常
现象:某个区域始终显示有压力
排查步骤:
- 检查FSR电阻(未受压时应>1MΩ)
- 测量分压电路输出电压(空载时应接近0V)
- 检查ADC引脚是否配置正确
7.2 蓝牙连接不稳定
现象:数据时有时无
解决方案:
- 在模块天线旁加焊22pF电容
- 修改AT+INQM=1,9,48(提高搜索强度)
- 避免将模块安装在金属部件附近
7.3 加热不均匀
可能原因及处理:
- 加热膜局部损坏:用万用表测量电阻(正常约50Ω)
- 散热不良:增加铝板面积或添加散热硅胶垫
- PWM驱动不足:检查MOS管栅极电压(应>8V)
8. 项目优化方向
经过三个月实际使用,发现几个待改进点:
- 增加惯性传感器(MPU6050)检测微动,避免误判短暂离座
- 改用硅胶加热片替代碳纤维膜,提升耐用性
- 开发iOS版本APP,使用BLE替代经典蓝牙
- 加入机器学习算法,个性化识别用户习惯
这个项目最让我惊喜的是,原本只是想做个小工具,结果办公室同事都抢着试用。有位腰椎不好的同事说,用了带坐姿提醒功能的坐垫后,疼痛确实减轻了。这也让我意识到,嵌入式开发不只是玩技术,更能实实在在地改善人们的生活质量。