【问题标题】:Function to detect peaks within an array of float values in Arduino? When graphed, displays an ECG reading?在Arduino中检测浮点值数组中的峰值的功能?绘制图形时,显示 ECG 读数?
【发布时间】:2020-04-19 03:25:19
【问题描述】:

我目前有这个由 2560 个值组成的数组,当绘制成图形时,它会形成一个 ECG。我在 MATLAB 中绘制了这个图,得到了下图(x 轴为 [0,2560],y 轴为 [-1, 2]。采样频率为 256 Hz,所以我在这里绘制了 10 秒。这是生成的来自 Physionet 的 ECGSYN,单导联心电波形绘图仪。

心电图数据的Matlab输出:

我将其导出为 csv,并将这些值定义为 Arduino 中具有 2560 个元素的浮点数组。根据图像,我们可以看到大约存在 10 个峰,我一直在尝试计算 Arduino 中此函数中 QRS 复合峰的数量(最终目标是找到每分钟的节拍数)。

运气不佳,因为记录的峰值数量约为 300+(应该是 10)。我已将我的代码的相关部分添加到下面的这篇文章中,并带有来自串行监视器的屏幕截图。我已经将我的问题归结为内部某处的 for 循环,但无法准确确定峰值数。我的目标是找到数组中下一个值小于当前值的最大值,并且数组中的前一个值也小于当前值。还有一个条件是,算作峰值的值必须高于 0.8 的阈值(以确保计数 QRS 复合波而不是心电图的 T 波或 P 波)。

如果我可以在此处提供更多信息,请告诉我。对任何不清楚的地方表示歉意,因为这是我的第一篇文章,而且我的编码语法不是最准确的(对于 Arduino 来说相对较新)。感谢您的帮助。

Serial Monitor Output of BPM and peak number:

这些是初始化的变量、数组(保留所有 2560 个元素)和 BPM 的函数。

const int arraySize = 2560;
int total = 0;
const float Sixty_BPM [arraySize] PROGMEM = {
// All my array elements
};

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  Serial.begin(9600);
}

int get_bpm()
{
  int Num_peaks = 0;
  float threshold_min = 1.0 ;
  float delaycalc = .1;
  for (int x = 1 ; x < arraySize-1; x++) {        
    if ((Sixty_BPM[x] - Sixty_BPM[x-1] > delaycalc )  &&  (Sixty_BPM[x+1] - Sixty_BPM[x] < 0) && (Sixty_BPM[x] > threshold_min)){ 
       Num_peaks++;
    }
  }
    Serial.print("NUMBER OF PEAKS IS");
    Serial.print("\t");
    Serial.print(Num_peaks);
    Serial.print("\n");
    float peakspersec = (float) Num_peaks / (((float) arraySize / 256));
    float bpm = peakspersec * 60;
    Serial.print("\t");
    Serial.print("BPM is ");
    Serial.print(bpm);
    Serial.print("\t");
    Serial.print("\n");
    return bpm;
}

更新:

根据 Ax the B 的建议在 MATLAB 中绘制峰值。这无疑向我展示了该公式的计算结果与我打算使用的任何地方都不相近。这是针对 ECG 绘制的峰值输出(看起来没有峰值模式)。

心电图上叠加峰的索引位置:

我在 MATLAB 中尝试了一个平滑平均滤波器,并没有发现很大的差异。数据本身非常干净(基本上没有噪音)。

关于如何编辑此峰值检测公式还有其他想法吗?感谢您到目前为止的帮助。

【问题讨论】:

    标签: arrays arduino


    【解决方案1】:

    将 for 循环替换为

    Serial.print("peaks = [");
    for (int x = 1 ; x < arraySize-1; x++) {        
      if ((Sixty_BPM[x-1] < threshold_min) && (Sixty_BPM[x] >= threshold_min)) { 
        Serial.print(" ");
        Serial.print(x);
        Num_peaks++;
      }
    }
    Serial.println("]");
    

    只计算值超过阈值的次数。如果它不起作用,那么您可以将峰值数组从串行控制台复制粘贴到 matlab 中,并将其绘制在您的绘图上以查看它们被检测到的位置。如果在阈值线周围聚集了多个假峰,您可能需要先进行一些过滤/平均。

    【讨论】:

    • 奇怪,错误的峰值出现在明显低于阈值的位置,如果 Sixty_BPM[x] 可以尝试打印该值以查看发生了什么。另外,条件也可以简化为 if ((Sixty_BPM[x] > Sixty_BPM[x-1]) && (Sixty_BPM[x] > Sixty_BPM[x+1]) && (Sixty_BPM[x] > threshold_min)) 我是不确定 delaycalc 应该在那里做什么,但它肯定会产生假阴性。
    猜你喜欢
    • 1970-01-01
    • 2021-09-09
    • 2020-12-29
    • 2017-06-09
    • 2016-05-28
    • 1970-01-01
    • 2016-04-03
    • 2013-08-11
    • 1970-01-01
    相关资源
    最近更新 更多