用 Serial Studio 实时可视化脉搏传感器(PPG):Arduino 滤波采集 + Quick Plot 绘图实战
2026/9/18 17:45:20 网站建设 项目流程

用 Serial Studio 实时可视化脉搏传感器(PPG):Arduino 滤波采集 + Quick Plot 绘图实战

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

本篇技术指南以开源遥测仪表板 Serial Studio 仓库中的 PulseSensor 示例 为核心,完整讲解如何用 Arduino 读取光电容积脉搏波(PPG)信号、在板端完成低通滤波与滑动平均去噪,再通过串口以 115200 波特率把滤波后的数据送入 Serial Studio 的 Quick Plot 模式实时绘图,并将数据导出为可回放、可离线分析的 CSV 文件。读完本文,你将掌握一套从传感器硬件接线、嵌入式滤波代码到桌面端零配置可视化与数据导出的完整实战链路。

项目概览与 PPG 信号背景

本示例的目标非常明确:用 Arduino 读取心率脉搏传感器的原始模拟信号,经过两级数字滤波后通过串口发送,让 Serial Studio 以类似 Arduino IDE Serial Plotter 的方式实时画出心跳波形,同时无需创建任何项目文件即可把数据存成 CSV 供离线分析。

这里采集的脉搏信号在生物医学上被称为光电容积脉搏波(Photoplethysmogram, PPG)。其原理是:传感器用一个发光二极管(LED)照射皮肤,再用光敏三极管测量被反射或透射的光量。心脏每搏动一次,皮肤微小血管中的血容量就会变化,对光的吸收量随之改变,最终形成一个以每次心跳为峰值的周期性波形。

PPG 传感器正是脉搏血氧仪的核心部件,用于估算心率和血氧饱和度,同时还能提供呼吸模式与血流状态等信息。需要特别说明的是,PPG 波形的具体形态会随传感器佩戴部位而变化——不同位置的组织构成和血管结构不同,信号特征也就不同。这一点在后续观察波形、调整滤波参数时值得留意。

硬件接线

示例对硬件的要求非常低,任何输出模拟信号的脉搏传感器模块都可以使用,代码固定使用 Arduino 的A0模拟引脚。

连接方式:将脉搏传感器的信号输出引脚(Signal)接到 Arduino 的 A0;再将传感器的 VCC 与 GND 分别接到 Arduino 的 5V 与 GND。

接线完成后即可烧录 PulseSensor.ino,无需其他外部库,全部逻辑由原生 Arduino API 实现。

Arduino 端:两级滤波与串口输出

PulseSensor.ino 是整个数据链路的源头,其处理流程分为三步:原始采样 → 低通滤波 → 滑动平均 → 串口打印。下面结合源码逐段解读。

参数与缓冲定义

#define SENSOR_PIN A0 // 脉搏传感器接模拟引脚 A0 #define BUFFER_SIZE 10 // 滑动平均缓冲区大小 float lowPassFiltered = 0.0; // 低通滤波后的信号 float filteredSignal = 0.0; // 最终平滑后的信号 float previousLowPass = 0.0; // 低通滤波的上一次输出,用于递推计算 float buffer[BUFFER_SIZE]; // 环形缓冲区,保存最近的滤波值 int bufferIndex = 0; // 环形缓冲区的当前写入位置 float bufferSum = 0.0; // 缓冲区内所有值的累加和,用于快速求平均 const float lowPassAlpha = 0.1; // 低通滤波系数

两个可调参数是理解整个滤波链路的关键:

  • lowPassAlpha(默认 0.1):一阶低通滤波的系数,取值范围为 0~1。值越小,对高频噪声的抑制越强,但信号响应越迟缓;值越大,波形跟随越快,但去噪效果变弱。示例默认 0.1,是针对 PPG 信号较为稳妥的起点,下文"故障排查"会说明如何调整。
  • BUFFER_SIZE(默认 10):滑动平均窗口的大小,即最终输出是最近 10 个低通滤波值的算术平均,窗口越大波形越平滑,但峰值(心跳)也会被削得更钝。

setup():串口初始化与缓冲区清零

void setup() { Serial.begin(115200); // 与 Serial Studio 匹配的波特率 for (int i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0.0; // 启动时清空滑动平均缓冲 }

串口以115200 波特率初始化,这个速率必须与 Serial Studio 侧保持一致,否则将看不到任何数据。将缓冲区预先清零,可避免上电瞬间的平均值被未初始化的随机值污染。

loop():采样、两级滤波、输出

void loop() { // 1. 读取 A0 上的原始模拟量(0~1023) sensorValue = analogRead(SENSOR_PIN); // 2. 一阶低通滤波:新值 = α·原始值 + (1-α)·上一次滤波值 lowPassFiltered = (lowPassAlpha * sensorValue) + ((1.0 - lowPassAlpha) * previousLowPass); previousLowPass = lowPassFiltered; // 3. 滑动平均:从和中移除最旧值,写入新值,再加入累加和 bufferSum -= buffer[bufferIndex]; buffer[bufferIndex] = lowPassFiltered; bufferSum += buffer[bufferIndex]; bufferIndex = (bufferIndex + 1) % BUFFER_SIZE; // 环形推进 // 4. 最终输出 = 窗口内平均值 filteredSignal = bufferSum / BUFFER_SIZE; // 5. 以一行文本的形式发送,供 Serial Studio 逐行解析 Serial.println(filteredSignal); // 6. 延时 5ms,粗略控制采样率(约 200 Hz) delay(5); }

值得注意的工程细节:

  • 低通滤波采用递推式一阶 IIR 结构y[n] = α·x[n] + (1−α)·y[n−1],只需保存上一次输出previousLowPass,内存开销极小,非常适合资源受限的 Arduino。
  • 滑动平均使用环形缓冲区 + 累加和的增量更新:每轮只做一次"减最旧、加最新"的 O(1) 操作,而非重新遍历求和,代码简洁且高效。
  • 串口输出用println打印单个浮点数:Serial Studio 的 Quick Plot 正是按行读取这种逗号分隔/换行分隔的数值流来实时绘图(见下文原理分析)。
  • 采样节奏由delay(5)控制:主循环以约 200 Hz 的速率采样、滤波并输出,对人体的脉搏频带(约 0.5~4 Hz)而言绰绰有余。

Serial Studio 侧:Quick Plot 零配置可视化

Arduino 端就绪后,Serial Studio 的配置几乎为零,这是 Quick Plot 模式的核心价值——不需要创建任何.ssproj项目文件即可绘图与导出。

操作步骤:

  1. 安装 Serial Studio:从项目官网下载并安装桌面版应用。
  2. 连接设备:将 Arduino 通过 USB 接入电脑,启动 Serial Studio,在设备/连接设置中选择正确的串口,并将波特率设为 115200以匹配固件。
  3. 启用 Quick Plot:在 Setup 面板的FRAME PARSING区域选择Quick Plot (Comma Separated Values)模式。该模式会把接收到的每一行中的所有数值逐个绘制成通道曲线,行为与 Arduino IDE 的 Serial Plotter 一致,但功能更强(支持缩放、暂停、多通道)。
  4. CSV 导出:即使没有创建任何项目,Serial Studio 也能把接收到的数据导出为带时间戳的、可回放的 CSV 文件,非常适合离线分析或分享给他人。

完成上述设置后,选中正确的串口并保持 115200 波特率,滤波后的脉搏波形就会在绘图窗口中实时滚动;数据可以随时从 Serial Studio 直接保存,用于离线分析。

Quick Plot 的底层原理(源码佐证)

Quick Plot 并非一个简单的"画曲线"开关,而是 Serial Studio 数据管线中的一等公民。仓库源码清晰地展示了它的实现方式:

  • 专用的帧构建器:QuickPlotBuilder 负责把每一行 CSV 数值动态组装成一个合成数据帧。从源码看,它会为每个数值自动生成一个数据集:无表头时按Channel 1Channel 2……依次命名(dataset.title = tr("Channel %1").arg(idx));当检测到多列数值时,还会额外创建一个Multi-Plot分组用于多曲线叠加显示,每个数据集都标记为可绘图(datasets[i].plt = true)。这就是为什么单通道脉搏信号会显示在Channel 1绘图窗中。
  • 逐行 CSV 解析:FrameBuilder.cpp 中的parseQuickPlotFrame()负责把串口数据按行拆分(splitQuickPlotChannels),再逐列转换为数值。特别的是,它会探测首行是否全部为非数字——如果收到一行全是文本,就将其识别为通道表头(m_quickPlot.setHeaders(channels)),后续数值行便以该表头命名通道。这意味着你甚至可以在固件里先发送一行"pulse"之类的标题,让绘图通道获得语义化名称。
  • 模式枚举与 CLI 支持:Quick Plot 是 Serial Studio 的顶层操作模式之一(见 SerialStudio.h 中的OperationMode枚举),并且命令行工具支持通过--quick-plot参数直接以该模式启动(见 CLI.cpp 中的相关逻辑),便于脚本化、自动化场景直接进入 Quick Plot 工作流。

理解这些实现细节,能帮助你在面对"为什么叫 Channel 1""为什么多列数据自动分成多条曲线"等问题时心中有数。

查看滤波后的脉搏数据

链路全部打通后的效果(参见 README 截图 与上方界面图):

  • 在 Serial Studio 中选择正确的串口,波特率保持 115200;
  • 绘图窗口以约 200 Hz 的刷新速率实时绘制平滑后的脉搏波形,每个心跳对应一个清晰的峰值;
  • 点击保存即可将带时间戳的数据从 Serial Studio 直接导出,供后续离线分析(如统计心率、观察波峰间距)。

若在串口侧临时想验证数据,也可以先用 Arduino IDE 的串口监视器观察原始输出是否在持续打印数值,再回到 Serial Studio 中连接。

故障排查与参数调优

  • Quick Plot 中无数据:首先检查脉搏传感器接线是否正确(Signal → A0,VCC → 5V,GND → GND);其次确认 Serial Studio 中选择的串口号与电脑识别到的一致,且波特率严格为 115200。也可先用 Arduino IDE 串口监视器验证固件是否在输出数据。
  • 波形噪声明显:如果绘图中的信号抖动剧烈、心跳峰值不清晰,说明低通滤波对高频噪声的抑制不足。可适当调小lowPassAlpha(例如从 0.1 降到 0.05),增强平滑效果;反之,如果波形过于迟钝、峰值被削平,说明滤波过重,可适当调大该系数。调整后重新烧录固件即可。
  • 波形出现毛刺/跳变:检查传感器与皮肤的贴合是否稳定,佩戴位置松动会造成基线漂移;同时在允许范围内增大BUFFER_SIZE可进一步抑制瞬时毛刺,但会引入更大的相位延迟。
  • 采样率相关delay(5)把输出限制在约 200 Hz,若后续想对接更高频的信号处理或缩小波形的滞后感,可在保持波特率不变的前提下减小延时,但需注意 115200 波特率下的串口吞吐上限。

延伸:从 Quick Plot 到完整项目

本示例展示的是零配置的 Quick Plot 工作流,特别适合快速验证传感器与算法。如果后续需要更专业的展示(例如同时显示原始信号与滤波后信号的对比曲线、叠加心电图风格的多通道绘图、或持久化的通道命名与颜色配置),可以基于 Quick Plot 已经验证过的数据格式,进一步在 Serial Studio 中创建正式项目文件(Project Editor),把Channel 1升级为具名的数据集,并搭配 Data Tables、仪表盘等输出控件。串口侧只需要保持"一行、数值、换行"的朴素输出协议,即可平滑地从快速验证过渡到工程化部署。

【免费下载链接】Serial-StudioOpen-source telemetry dashboard. Supports UART, BLE, MQTT, Modbus, CAN Bus and more.项目地址: https://gitcode.com/GitHub_Trending/se/Serial-Studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询