4. 设备端数据采集与预处理
可穿戴设备与手机或网关之间的数据链路,本质上是一条“受限资源下的可靠传输链”。设备端 MCU 的 RAM 通常只有几十到几百 KB,Flash 也只有几百 KB 到几 MB,而传感器每秒可能产生数十到数百个采样点。如果采集、清洗、缓存、上传四个环节没有协同设计,就会出现丢包、重复上传、电量骤降或数据空洞。本节围绕这条链路,讲清楚采样策略怎么定、清洗在哪里做、缓存怎么组织、断点续传靠什么状态字段实现。
采样策略:先定频率,再定触发方式
采样频率不是越高越好。以 PPG 心率为例,25 Hz 通常足以提取心率,50 Hz 可支持部分 HRV 分析,而 100 Hz 以上主要服务于波形级研究。工程上常用“按需分级”策略:静息时用低频,运动状态用高频。判断运动状态可以借助设备自带的加速度计模组,当三轴合加速度方差超过阈值时切换到高频档。
触发方式上,连续采样适合心率、体温等慢变量;事件触发适合跌倒检测、异常心律等突发场景。下面是一段典型的采样配置示例,采用“基础频率 + 运动升频”的策略:
{
"sensor": "ppg",
"base_rate_hz": 25,
"active_rate_hz": 50,
"motion_threshold_g": 0.35,
"batch_size": 50,
"flush_interval_ms": 2000
}
其中 batch_size 表示攒够 50 个采样点打包一次,flush_interval_ms 表示即使没攒满,2 秒也必须落盘或上传,避免数据长时间停留在易失内存中。
数据清洗:在设备端做“减法”
设备端清洗的目标不是做复杂算法,而是用最小算力去掉明显无效的数据,减少后续传输和云端处理压力。常见处理包括三类:
- 范围过滤:心率超出 30~220 bpm、血氧超出 70%~100% 的读数直接标记为无效。
- 突变抑制:相邻两点差值超过物理可能变化率时,判定为运动伪影或接触不良,暂存待确认。
- 缺失标记:传感器未佩戴或信号质量差时,不伪造数值,而是写入质量位
quality=0。
清洗后的数据应保留原始值和质量标记,而不是直接丢弃。这样云端仍可回溯,也便于后续算法重新评估。一个常见的记录结构如下:
typedef struct {
uint32_t ts_ms; // 采样时间戳
int16_t raw_value; // 原始读数
uint8_t quality; // 0=无效 1=可用 2=优
uint8_t seq; // 批内序号
} sample_t;
本地缓存:环形缓冲 + 分段落盘
设备端缓存要解决两个矛盾:写入速度要快,掉电不能丢。推荐做法是“RAM 环形缓冲 + Flash 分段存储”。RAM 中维护一个固定长度的环形队列,采集任务只负责写入;一个低优先级任务负责把队列中已满的批次搬运到 Flash 的段中。每段大小固定,例如 4 KB,写满后切换到下一段。
Flash 写入必须考虑擦除寿命。以每天写入 200 KB 计算,1 MB 的预留区可支撑约 5000 次擦写循环,配合磨损均衡,足以覆盖数月使用。缓存区还需要一个“水位”机制:当占用超过 80% 时,主动降低采样频率或优先上传,防止溢出。
断点续传:靠序号和确认位对齐
断点续传的核心是让接收端能判断“我收到了哪些、还缺哪些”。最简洁的方案是给每个批次分配单调递增的 batch_id,接收端定期回传已确认的最大连续 ID。设备端只需保存三个关键状态:
next_batch_id:下一个待发送批次号;acked_batch_id:已被云端确认的最大连续批次号;pending_list:已发送但未确认的批次号列表。
重连后,设备从 acked_batch_id + 1 开始重发,云端按 batch_id 去重。这样即使中途断网、重启,也不会丢数据或产生重复记录。下面这张图展示了从采集到续传的完整数据流与状态关系:
参数协同与验证要点
四个环节的参数必须一起调。例如 batch_size 太小会导致上传次数过多、功耗上升;太大则断网时丢失风险增加。一个可参考的起点是:采样 25 Hz、batch 50 点、flush 2 秒、Flash 预留 1 MB、水位阈值 80%。验证时重点观察三件事:断网 10 分钟后重连,云端记录是否连续无缺口;设备重启后 next_batch_id 是否从正确位置继续;连续运行 24 小时后缓存占用是否稳定在阈值以下。若出现缺口,优先检查 acked_batch_id 的持久化时机——它必须在收到云端确认并写入 Flash 之后才能更新,否则重启后会误判已确认范围。