Loading...
低压
高压
未连接
-- 等待数据
坐垫舒适度 · 综合平衡、压力与稳定性评估
--
平衡度
--
压力水平
--
稳定性
左侧压力 --
右侧压力 --
实时压力曲线
左压力 右压力
--
近5分钟均值
--
近1小时均值
--
本次最高值
📷

上传坐垫场景照片
AI 将结合实时压力数据给出精准坐姿建议

--
当前左侧压力
--
当前右侧压力
--
左右平衡

🔧 硬件系统架构

FSR402 薄膜压力传感器
(左侧 · 长条型)
+
FSR402 薄膜压力传感器
(右侧 · 长条型)
│ 分压电路 → PA4 (ADC_IN4) / PA5 (ADC_IN5)
STM32F103C8T6 主控芯片
← 模拟输入
PA4 左压力 ADC
PA5 右压力 ADC
→ 数字输出
PA9 USART1_TX
CH340 串口
│ 交替行输出 (115200bps): 左值\r\n右值\r\n左值\r\n...
CH340 USB-TTL → 电脑 USB → 浏览器 Web Serial API → Flask 后端 + 3D 可视化

📸 硬件实物照片

📋 硬件模块详解

1. FSR402 薄膜压力传感器 (×2)

🔍 感知层

FSR402 是 Interlink Electronics 生产的力敏电阻传感器,感应区域约 12.7mm 直径。本系统使用两根长条型 FSR402,纵向放置于坐垫左右两侧。传感器与 10kΩ 电阻构成分压电路,连接 STM32 PA4(左)/PA5(右) ADC 通道。压力越大 → 电阻越小 → ADC 读数越低。闲置时 ADC≈4095,满载时 ADC 可降至数百。左右压力差 >15% 即触发姿势偏移提醒。

2. STM32F103C8T6 微控制器

🧠 控制层

ARM Cortex-M3 内核,72MHz 主频,64KB Flash。片上集成 2 路 12-bit ADC(PA4/PA5 扫描模式),每路采样后通过 USART1 (PA9 TX, 115200bps) 输出交替行文本(左值换行、右值换行)。固件使用 Keil MDK 开发,源码位于本地工程目录。

3. CH340 USB 转串口模块

🔌 通信层

CH340C USB 转 TTL 串口芯片,连接 STM32 PA9(TX)/PA10(RX),115200 bps。配合 Chrome 浏览器内置的 Web Serial API,无需安装任何驱动或软件,浏览器直接读取串口数据并驱动 3D 可视化面板。真正实现"插线即用"。

4. ST-LINK/V2 下载调试器

💻 编程工具

SWD 接口 (SWCLK/SWDIO/GND/3.3V) 连接 STM32,Keil MDK 一键编译下载。支持断点调试与变量监视。4 根杜邦线即可完成全部连接。

5. 0.96 寸 OLED 显示屏(可选)

📺 本地显示

SSD1306 驱动,128×64 分辨率,I2C 接口。本地实时显示左右压力原始值和平衡状态,无需电脑也能查看压力读数。

6. 面包板 & 连接线缆

🔧 结构件

MB-102 面包板、跳线、杜邦线(母对母)、飞线,用于搭建 FSR402 分压电路与 STM32 的传感器信号采集电路原型。无需焊接,方便快速迭代。

🔌 引脚接线表

STM32 引脚连接外设类型说明
PA4FSR402 左侧 (AO)ADC1_IN4左压力模拟采样,12-bit 分辨率
PA5FSR402 右侧 (AO)ADC1_IN5右压力模拟采样,12-bit 分辨率
PA9CH340 RXUSART1_TX串口发送交替压力值 (115200bps)
PA10CH340 TXUSART1_RX串口接收 (预留,当前未使用)
PA13ST-LINK SWDIOSWD程序下载 / 调试数据线
PA14ST-LINK SWCLKSWD程序下载 / 调试时钟线
3.3VFSR402 VCC (×2)电源传感器供电 3.3V
GNDFSR402 GND (×2)分压电路共地

⚙ 系统工作流程

STM32 上电复位
初始化 ADC1 (PA4/PA5 双通道扫描)
读 PA4 → 发 "值\r\n"
读 PA5 → 发 "值\r\n"
↓ 循环
CH340 串口 → USB → Chrome Web Serial API
3D 坐垫实时变形
舒适度评分更新
AI 场景分析

🧠 软件系统设计

状态机设计

🟢 初始化 (INIT)

ADC1 初始化 (12MHz/12bit)
USART1 初始化 (115200/8N1)
PA4/PA5 设为模拟输入
SysTick 1ms 定时器启动

🔵 采集 (ACQUIRING)

扫描模式读取 PA4→PA5
交替串口发送: 左值\r\n右值\r\n
循环间隔 ~10ms
≈50Hz 等效采样频率

🟡 故障 (ERROR)

ADC 超时无数据 → 发送 0\r\n0\r\n
串口断开 → 等待 CH340 重连
连续 3 秒无数据 → 看门狗复位

⏰ 时序控制

SysTick 毫秒定时器 — 主循环用 SysTick 中断产生 1ms 基准,HAL_GetTick() 提供毫秒级时间戳。ADC 双通道扫描 + 串口发送的完整周期约 10ms,等效 100Hz 采样率。浏览器端每收到一对 L/R 值立即更新 3D 模型和仪表盘。

📊 ADC 双通道扫描采样

PA4 (ADC1_IN4) 和 PA5 (ADC1_IN5) 配置为扫描模式,一次触发自动转换两路。12 位分辨率 (0-4095)。FSR402 传感器与 10kΩ 电阻组成分压电路:压力↑ → 电阻↓ → 电压↓ → ADC↓。闲置时 ADC≈4095,满载可降至数百。连续采样 4 次取平均值,滤除电源纹波。

📡 串口通信协议

USART1 (PA9 TX, PA10 RX), 115200 bps, 8N1。协议极简:每行一个整数值 + \r\n,左右交替发送。接收端配对两个连续行 = 一组 L/R 帧。浏览器 Web Serial API 逐行解析,无需 JSON 封装,开销为零。

// 串口输出示例
2847
2910
2835
2924
2821
2938
// 浏览器配对: (2847,2910) (2835,2924) (2821,2938) ...

💻 核心代码模块

ADC 双通道扫描 + 均值滤波

u16 ADC_ReadChannel(u8 channel) {
    u32 sum = 0;
    for (int i = 0; i < 4; i++) {                    // 4次采样取均值
        ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5);
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);      // 启动转换
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // 等待完成
        sum += ADC_GetConversionValue(ADC1);          // 读12bit结果
    }
    return (u16)(sum / 4);
}

u16 ReadLeftPressure(void)  { return ADC_ReadChannel(ADC_Channel_4); }  // PA4
u16 ReadRightPressure(void) { return ADC_ReadChannel(ADC_Channel_5); }  // PA5

主循环 — 交替串口输出

int main(void) {
    System_Init();                                    // 时钟 72MHz
    ADC_Init();    UART1_Init(115200);              // 外设初始化

    u16 left, right;
    char buf[16];

    while (1) {
        left  = ReadLeftPressure();                   // PA4 ADC
        right = ReadRightPressure();                  // PA5 ADC

        // 串口交替发送: 左值\r\n右值\r\n
        sprintf(buf, "%d\r\n", left);
        UART1_SendString(buf);

        sprintf(buf, "%d\r\n", right);
        UART1_SendString(buf);

        delay_ms(10);                              // ~100Hz 采样率
    }
}

Web Serial API — 浏览器端配对接收

async function readSerialLoop() {
    const reader = port.readable.getReader();
    let buf = '', expected = 'L', curL = 0, curR = 0;

    while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        buf += new TextDecoder().decode(value);

        const lines = buf.split('\n');
        buf = lines.pop();                            // 保留不完整行

        for (const line of lines) {
            const v = parseInt(line.trim());
            if (isNaN(v)) continue;
            if (expected === 'L') { curL = v; expected = 'R'; }
            else { curR = v; expected = 'L'; onFrame(curL, curR); }
        }
    }
}

🛡 数据质量保障

🔢 ADC 多次采样均值

每个通道连续采样 4 次取平均值,消除电源纹波和随机噪声。等效采样率降为 ~25Hz,人坐姿变化频率 <5Hz,满足奈奎斯特采样定理。

🔄 串口自动重连

Web Serial API 检测到串口断开后,自动释放端口 (reader.cancel + port.close + port.forget),用户点击按钮即可重新连接,无需刷新页面。

📋 数据校验

parseInt 解析每行,NaN 值自动跳过。左右配对机制确保 L/R 数据严格对应,避免错位导致平衡度计算失真。

📱 手动输入降级

浏览器不支持 Web Serial API 时 (Firefox/Safari),可切到 AI 建议 Tab 直接上传坐姿照片,由千问 VL-Plus 根据图像判断舒适度。

⚡ 技术亮点

🌐 Web Serial API

浏览器原生串口通信,零驱动、零安装。替代传统 pyserial + EXE 方案,无需安装任何软件,Chrome 打开网页即用。

🎨 Three.js 3D 实时渲染

3D 坐垫模型实时热力映射 (蓝→绿→黄→红),压力越大颜色越暖、形变越大。OrbitControls 支持旋转/缩放观察。

🧠 千问 VL-Plus 多模态 AI

上传坐姿照片 + 实时压力数据,AI 综合分析场景类型、坐姿偏差、压力分布,给出精准到厘米的坐姿调整建议。

📊 三环舒适度模型

Balance (平衡) + Level (压力) + Stability (稳定) 三因子加权评分,20 帧滑动窗口计算稳定性变异系数。

🔐 API Key 服务端保护

千问 API Key 仅存于服务端 web_server.py,前端通过 POST /api/analyze 代理调用,密钥永不暴露。

📡 极简串口协议

每行一个整数 + 换行符,左右交替发送。零 JSON 开销,STM32 端仅需 sprintf + 串口发送,固件体积 <10KB。

📋 软件基础设置信息

IDEKeil MDK v5 (uVision V5.06)
编译器ARMCC V5.06 update 5 (build 528)
主控芯片STM32F103C8T6 (Cortex-M3, 64KB Flash, 20KB SRAM)
时钟HSE 8MHz → PLL 9x → 72MHz
标准库STM32F10x Standard Peripheral Library V3.5.0
C 语言标准C99 (--c99)
MicroLIB已启用 (精简 printf/math 库)
工程定义STM32F10X_MD, USE_STDPERIPH_DRIVER
启动文件startup_stm32f10x_md.s (中等密度)
编程器ST-LINK/V2 (SWD 接口)
开发语言Python 3.10+ (服务端), JavaScript ES6+ (前端), C99 (固件)
前端框架Three.js 0.160 (3D), Chart.js 4.4 (曲线), 原生 JS (无框架)
后端框架Flask 3.x + Pillow (图片压缩), 千问 VL-Plus API