说明¶
概述¶
架构1使用环形缓冲区实现 Producer-Consumer 模式,用于实时传感器数据采集和处理。该架构针对中等采样频率(0.1 - 1000 Hz,推荐:100 Hz - 1 kHz)设计,提供简单、易于理解的实现模式。
架构原理¶
Producer-Consumer 模式¶
该架构使用经典的 Producer-Consumer 模式,包含以下组件:
- Producer 任务(高优先级):以固定间隔读取传感器数据并写入环形缓冲区
- Consumer 任务(中等优先级):定期从环形缓冲区读取并处理数据
- 环形缓冲区:基于 PSRAM 的缓冲区,允许在满时覆盖旧数据(FIFO 覆盖)
- 互斥锁同步:保护 Producer 和 Consumer 任务之间的缓冲区访问
关键设计决策¶
- 环形缓冲区而非队列:使用环形缓冲区以提高内存效率和更简单的实现
- FIFO 覆盖:当缓冲区满时,覆盖最旧的数据(Producer 不跟踪数据丢失,但 Consumer 可以检测覆盖)
- 周期性 Consumer 处理:Consumer 每 50ms 处理一次缓冲区,读取最多 10 个最新样本
- 任务通知:ESP 定时器回调通过
xTaskNotify通知 Producer 任务,避免阻塞定时器回调
实现细节¶
基于定时器的采样¶
- ESP 定时器:创建周期定时器,周期 =
1,000,000 / sampling_frequency_hz微秒 - 定时器回调:在定时器上下文中执行,通过
xTaskNotify通知 Producer 任务 - 立即首次采样:在启动周期定时器之前执行一次采样
Producer 任务¶
优先级:10(高优先级,用于及时采集)
功能:
- 通过
xTaskNotifyWait等待定时器通知 - 读取传感器数据(加速度和温度)
- 准备带时间戳的样本结构
- 在互斥锁保护下写入环形缓冲区
- 更新采集统计
缓冲区写入逻辑:
- 以 10ms 超时获取互斥锁
- 写入当前写指针位置
- 推进写指针(环形)
- 如果缓冲区满(写指针追上读指针),推进读指针(FIFO 覆盖)
- 更新覆盖计数用于监控
Consumer 任务¶
优先级:8(中等优先级,低于 Producer 以确保采集优先级)
功能:
- 等待处理间隔(50ms)
- 获取互斥锁以读取缓冲区快照
- 从读指针读取最多 10 个最新样本
- 推进读指针
- 处理样本(特征提取、检测等)
- 更新处理统计
- 输出结果(串口、MQTT、LCD)
处理逻辑:
- 计算可用样本(读指针和写指针之间的距离)
- 读取最多
CONSUMER_PROCESS_SAMPLE_COUNT(10)个样本 - 处理环形缓冲区环绕
- 如果样本不足,用零填充
环形缓冲区¶
大小:512 样本(可通过 CIRCULAR_BUFFER_SIZE 配置)
内存:从 PSRAM 分配以支持大缓冲区
同步:互斥锁保护的访问
行为:
- 满时 FIFO 覆盖
- 读指针随 Consumer 读取而推进
- 写指针随 Producer 写入而推进
- 跟踪覆盖计数用于监控

图:环形缓冲区操作示意图,显示 Producer 写入和 Consumer 读取,以及 FIFO 覆盖行为
加速度检测¶
启用后,Consumer 任务对处理的样本执行加速度检测:
条件:
|x| > 0.5g OR |y| > 0.5g OR |z| < 0.5g
LCD 反馈:
- 满足条件时显示红色
- 否则显示白色
- 颜色保持:0.3 秒
- 最小更新间隔:100ms(避免 SPI 总线冲突)
数据流¶
ESP 定时器 → 定时器回调 → xTaskNotify → Producer 任务
↓
读取传感器(SPI)
↓
环形缓冲区(互斥锁)
↓
Consumer 任务(50ms 间隔)
↓
处理样本
↓
┌───────────────────┴───────────────────┐
↓ ↓ ↓
串口 MQTT LCD
配置¶
默认配置¶
#define RT_PC_QUEUE_SIZE_DEFAULT 50
#define RT_PC_PRODUCER_PRIORITY 10
#define RT_PC_CONSUMER_PRIORITY 8
#define RT_PC_PRODUCER_STACK_SIZE 4096
#define RT_PC_CONSUMER_STACK_SIZE 8192
#define CIRCULAR_BUFFER_SIZE 512
#define CONSUMER_PROCESS_INTERVAL_MS 50
#define CONSUMER_PROCESS_SAMPLE_COUNT 10
配置参数¶
- 采样频率:0.1 - 1000 Hz(初始化时验证)
- 队列大小:用于配置结构兼容性(环形缓冲区模式下不使用)
- 环形缓冲区大小:512 样本(编译时固定)
- Consumer 处理间隔:50ms(编译时固定)
- Consumer 处理样本数:10 样本(编译时固定)
功能特性¶
优势¶
- 实现简单:易于理解的 Producer-Consumer 模式
- 采集与处理解耦:Producer 和 Consumer 独立运行
- 内存高效:具有覆盖能力的环形缓冲区
- 低开销:最小同步开销
- 适用于中等频率:针对 100 Hz - 1 kHz 范围优化
限制¶
- 缓冲区可能成为瓶颈:如果 Consumer 无法跟上,数据可能被覆盖
- 固定处理间隔:Consumer 以固定 50ms 间隔处理
- 仅限于最新样本:每个周期仅处理最后 10 个样本
- 无 DMA 支持:使用标准 SPI 传输(CPU 绑定)
性能特征¶
适用频率范围¶
- 有效范围:0.1 - 1000 Hz(初始化时验证)
- 推荐:100 Hz - 1 kHz
- 最大:最高 1 kHz(验证限制)
- 最小:0.1 Hz(实际限制)
资源使用¶
- 内存:环形缓冲区(512 样本 × 32 字节 = 16 KB,来自 PSRAM)
- CPU:中等使用(Producer 和 Consumer 任务)
- 同步:单个互斥锁用于缓冲区访问
使用注意事项¶
- 初始化顺序:必须在
arch_pc_set_sensor_handle()之前调用arch_pc_init() - 传感器句柄:启动前必须设置
- 缓冲区监控:监控统计中的
overwrite_count以检测 Consumer 是否落后 - 处理延迟:Consumer 每 50ms 处理一次,因此处理延迟最多为 50ms
- 样本计数:Consumer 每个周期处理最多 10 个样本以实现实时响应
错误处理¶
- 互斥锁超时:如果无法在 10ms 内获取互斥锁,Producer 丢弃样本
- 缓冲区未初始化:如果缓冲区未就绪,丢弃样本
- 传感器读取失败:记录日志但不停止处理
- 任务创建失败:返回错误,清理资源
线程安全¶
- 互斥锁保护:所有缓冲区访问由互斥锁保护
- 任务隔离:Producer 和 Consumer 任务正确隔离
- 统计:在互斥锁保护的部分内原子更新