You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中捕获传感器波形的连续最大/最小峰值?

波形信号峰谷检测的C++实现方案

问题描述

我有一个每周期包含一个最大值和最小值的波形信号,需要在检测到波谷(最小值)时保存该最小峰值,检测到波峰(最大值)时保存该最大峰值,直到下一组峰谷出现。尝试了如下代码但未能成功:

#include <Wire.h>
#include <DFRobot_MAX30102.h>

DFRobot_MAX30102  particleSensor;
int               savedRed;
bool              increase;

void setup() {
  Serial.begin(9600);
  // Initialize sensor
  if (particleSensor.begin() == false) {
    Serial.println("MAX30102 was not found. Please check wiring/power. ");
    while (1);
  }
  particleSensor.sensorConfiguration(0x1F,SAMPLEAVG_4,MODE_MULTILED,SAMPLERATE_400, PULSEWIDTH_411,ADCRANGE_4096);
  savedRed = particleSensor.getRed();
  increase = true;
}
 
void loop() {
  int red = particleSensor.getRed();
  red = particleSensor.getRed(); // 重复读取无意义
  if (increasing) {} // 变量名错误(定义为increase)+ 多余大括号导致逻辑混乱
    if (red < savedRed) {
      Serial.print(savedRed);
      increasing = false;
    }
  } else if if (red > savedRed) { // 语法错误:else if if 无效
    Serial.print(savedRed);
    increasing = true;
  }
  savedRed = red;
}

原代码存在以下问题:

  • 变量名不一致:定义increase但使用未声明的increasing
  • 语法错误:多余大括号、else if if无效语法
  • 逻辑缺陷:仅比较相邻两个采样值,易被传感器噪声干扰,无法准确识别真正的峰谷(短暂波动会被误判为趋势反转)

是否可以用等待局部最小值的状态机来实现?试过if/else循环,但要么无法清除上一个峰值直到出现更小的峰值,要么无法正确保存峰值。


解决方案:状态机实现峰谷检测

状态机非常适合这类需要跟踪状态切换的场景,我们可以定义两个核心状态,结合趋势判断和噪声过滤来准确识别峰谷:

核心思路

  1. 定义状态:
    • STATE_WAIT_TROUGH:跟踪下降趋势,寻找波谷(最小值)
    • STATE_WAIT_PEAK:跟踪上升趋势,寻找波峰(最大值)
  2. 趋势判断:通过连续多个采样点的变化确认趋势,避免单帧噪声干扰
  3. 峰谷确认:当趋势发生反转且持续达到阈值时,确认峰谷并保存值,切换状态

完整实现代码

#include <Wire.h>
#include <DFRobot_MAX30102.h>

DFRobot_MAX30102 particleSensor;

// 状态枚举定义
typedef enum {
  STATE_WAIT_TROUGH,  // 等待波谷状态
  STATE_WAIT_PEAK     // 等待波峰状态
} PeakTroughState;

PeakTroughState currentState = STATE_WAIT_TROUGH;
int currentExtremeValue;  // 当前跟踪的极值(波谷/波峰)
int previousValue;        // 上一次采样值
int trendCounter = 0;     // 趋势持续计数器,过滤噪声
const int TREND_THRESHOLD = 3; // 连续N个点趋势一致才确认反转,可根据噪声调整

void setup() {
  Serial.begin(9600);
  
  // 初始化传感器
  if (particleSensor.begin() == false) {
    Serial.println("MAX30102未找到,请检查接线/电源。");
    while (1);
  }
  particleSensor.sensorConfiguration(0x1F, SAMPLEAVG_4, MODE_MULTILED, SAMPLERATE_400, PULSEWIDTH_411, ADCRANGE_4096);
  
  // 初始化采样基准值
  previousValue = particleSensor.getRed();
  currentExtremeValue = previousValue;
}

void loop() {
  int currentValue = particleSensor.getRed();
  
  switch(currentState) {
    case STATE_WAIT_TROUGH:
      // 跟踪最小值,判断是否从下降转为上升
      if (currentValue < currentExtremeValue) {
        currentExtremeValue = currentValue; // 更新当前最小值
        trendCounter = 0;
      } else if (currentValue > previousValue) {
        trendCounter++; // 累计上升趋势计数
        // 连续达到阈值,确认波谷
        if (trendCounter >= TREND_THRESHOLD) {
          Serial.print("检测到波谷:");
          Serial.println(currentExtremeValue);
          // 切换到寻找波峰状态
          currentState = STATE_WAIT_PEAK;
          currentExtremeValue = currentValue;
          trendCounter = 0;
        }
      } else {
        trendCounter = 0; // 趋势未变,重置计数器
      }
      break;
      
    case STATE_WAIT_PEAK:
      // 跟踪最大值,判断是否从上升转为下降
      if (currentValue > currentExtremeValue) {
        currentExtremeValue = currentValue; // 更新当前最大值
        trendCounter = 0;
      } else if (currentValue < previousValue) {
        trendCounter++; // 累计下降趋势计数
        // 连续达到阈值,确认波峰
        if (trendCounter >= TREND_THRESHOLD) {
          Serial.print("检测到波峰:");
          Serial.println(currentExtremeValue);
          // 切换到寻找波谷状态
          currentState = STATE_WAIT_TROUGH;
          currentExtremeValue = currentValue;
          trendCounter = 0;
        }
      } else {
        trendCounter = 0;
      }
      break;
  }
  
  previousValue = currentValue;
  delay(1); // 可选:添加小延迟避免采样过密
}

代码说明

  • 状态切换:通过switch语句清晰区分波谷/波峰跟踪逻辑,避免if/else嵌套混乱
  • 噪声过滤:TREND_THRESHOLD可根据传感器噪声情况调整,噪声越大阈值可设越高
  • 极值跟踪:每个状态下持续更新当前极值,确保捕获到真正的峰谷值
  • 闭环检测:确认峰谷后自动切换状态,实现连续的周期峰谷检测

内容的提问来源于stack exchange,提问作者tenebris in kux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 00:03:12