Introduction: ECG With PPG Using Arduino

ECG With PPG Using Arduino

体积描记图是血容量与时间的关系图,光电容积脉搏波 (PPG) 使用光来测量血容量,通常使用手指探头。

您可以在 eBay 上非常便宜地购买脉搏血氧仪。它使用光电容积脉搏波来测量您的心率。通过比较红外光与红光的吸收,它还可以测量血氧饱和度。

构建测量红光和红外吸收的 PPG 很简单,但校准它是一个问题。此处描述的 PPG 仅使用红外光。

这个项目是我的 ECG 项目的附加组件 - 我假设您已经构建了 ECG 硬件。此处描述的附加硬件和软件在心电图迹线旁边显示光电容积脉搏波图。探头夹在手指上,让红外线穿过手指。

接收的 IR 量是手指血容量的量度。

您可以使用两个电路来收集 PPG 数据:

  •  构建自己的放大器
  •  使用AD8232模块

构建自己的放大器稍微便宜一些,而且您可能已经拥有了所有组件。AD8232模块的工作量较少,但您必须等待它交付。

要构建原始ECG项目,您需要一个Arduino Nano,一个ILI9341 320x240 SPI显示器,一个AD8232模块,某种电池,一个按钮和一些电阻器。

我已经包括了一个 3D 打印的 PPG 夹子的设计,或者您可以使用一块 PVC 管道。

新软件包括用于计算心电图信号QT间期的代码。如果您已经构建了我的心电图项目,则可以升级该项目以显示 QT 间期。(请参阅下面的“分析”步骤。您无需构建 PPG 硬件。

这不是一个医疗设备,它是你为了好玩而建造的东西。请参阅我的心电图项目第 2 步中的完整免责声明。

第 1 步:光电容积脉搏波显示什么?

PPG 浪潮有快速上升和缓慢下降。在下降期间,出现了第二个高峰。第一个峰是“收缩峰”,第二个峰是“舒张峰”。两个峰值之间的倾角是“双峰缺口”。

收缩峰值是由于收缩期(心室收缩时)从心脏流出的血液脉搏所致。舒张峰值是由于该脉搏从动脉系统的其他部分反射而来的。

阻抗发生急剧变化的任何地方都会发生反射。主要反射来自主动脉和髂动脉的交界处。还有其他来自早期交界处的交界处,但它们往往隐藏在PPG的收缩峰中。

舒张峰值的大小随您在身体上测量 PPG 的位置而变化。它在额头上很大,在脚趾处几乎消失了。

舒张峰的大小也随年龄而变化。对于年轻人来说,它相当大,并且随着年龄的增长而变小。对于年轻人来说,双峰切迹也很大,并且随着年龄的增长而变小。

使用 PPG 可以很容易地测量心率,因此 PPG 可以帮助检测心律失常、心动过速、心房颤动等。但它们也可以使用心电图迹线来检测。

PPG 波的总高度可用于检测您的呼吸频率。吸气时脉搏振幅降低,心率增加。这些影响非常小,并且有更简单的方法来检测呼吸。

心电图的 R 波(最大峰值)与向 PPG 收缩期峰值上升的最陡峭部分之间的时间称为脉冲到达时间。

(还有其他略有不同的定义:有些人测量到收缩压峰值的顶部,有些人测量到收缩压峰值的开始。

脉冲传输时间是脉搏从肩膀到手指或面部到脚趾传播所需的时间。

  • PAT(脉冲到达时间) - 脉冲从心脏到达 PPG 探头的时间
  • PTT(脉冲传输时间) - 脉冲从肩部到手指的时间

但有些人将两者都称为脉冲传输时间。

我将把从R波到手指的时间称为PAT。

典型的 PAT 范围为 200mS 至 300mS。其中,大约 35mS 是血液在 R 波峰值后开始离开心脏所需的时间。

脉冲到达时间 (PAT) 和脉冲传输时间 (PTT) 都可用于估计血压、动脉硬度、动脉粥样硬化、动脉硬化等。然而,个体之间存在很多自然差异。

PAT和血压之间的关系必须针对每个人进行校准。PAT可能有助于发出血压突然变化的信号,例如,在临床过程中;它可以比袖带更快地发出变化信号。

PAT 是一种测量血压的不良方法。PTT 稍微好一点,特别是当它与心率测量相结合时。如果你在网上搜索,你会发现数百篇论文试图预测PPG的血压,但在我看来,没有人成功。

PPG的总高度与脉冲压力成正比。脉压是动脉收缩压和舒张压之间的差值。较高的脉压可能会增加心脏病发作或卒中的风险。

它可能表明动脉粥样硬化和动脉变硬。当然,振幅还取决于您将手指戳入 PPG 夹的距离。

PPG是一个活跃的研究领域。最重要的是,它可能对诊断有用,也可能没有。个体之间的正常差异可能大于各种健康状况造成的差异。这张图(上图)显示了问题所在。对于每个人来说,PAT和血压之间存在相关性,但它被个体之间的差异所淹没。

因此,您似乎可以使用PPG来监测个体的变化,但不能将该个体与一般人群进行比较。

通常,当心率升高时,血压也会升高,因此 PAT 会下降。但随着内出血,血压会下降,心率会上升以代偿,但 PAT 也会上升。想象一下在紧急情况下使用 PPG。这篇论文表明,800毫升失血使PAT(在麻醉猪中)延长了50%。对我来说,这似乎是PAT可以揭示的最有用的东西。

网上有很多好的评论和讨论。本文综述了 118 篇文章,本文综述了 162 篇文章。其他评论是 这里 和 这里.

 步骤2:AD8232电路

如果您正在构建自己的放大器,请跳到下一步。

AD8232芯片内置高质量、低噪声仪表放大器和信号调理功能,可消除噪声。它主要用于记录心电图,但它非常适合记录 PPG 信号。

购买一个像照片中那样的模块。在eBay上搜索“AD8232模块”或“ECG模块”。您不需要带有引线和电极垫的。您应该已经有一个类似的模块来测量心电图。

R8 和 LED1 产生红外光,通过手指传递到 PD1。流经 PD1 的电流在 R1 两端产生电压。该电压与AD8232模块的RA和LA输入交流耦合。

AD8232模块的RA和LA输入通过1M电阻连接到AD8232的RL(驱动接地)输出。这样可以使RL和RA的电压保持在正确的范围内。

您可以使用3.5mm插孔插头将PPG电路连接到AD8232模块,也可以将导线焊接到AD8232 PCB的孔中。

我建议您在条形板上构建电路 - 它的组件很少。

R6 的值决定了 PPG 信号的大小。尝试介于 100R 和 470R 之间的值。

当您使用 USB 引线将电路连接到计算机时,该模块会产生电源嗡嗡声。当设备断开连接时,嗡嗡声会消失。

第 3 步:自制放大器电路

如果您使用的是AD8232模块,请跳至下一步。

该电路由一个红外 LED 发射器、一个红外光电晶体管接收器和一个基于 LM358 运算放大器的放大器/滤波器组成。

通过光电晶体管的电流在R1两端产生电压。该电压交流耦合到 U1a 的输入端(截止频率为 3Hz)。U1a 的 V/V 增益为 22 倍。C1 在 7Hz 以上提供缓慢滚降。

U1b周围的电路构成一个约10Hz的低通巴特沃斯滤波器,V/V增益为3倍。模拟公司在这里发布一个好的滤波器设计工具。

R1与U1a交流耦合,因为如果它是直流耦合的,则整体光电平的变化会使R1两端的电压发生变化,并可能将运算放大器输出驱动到电源轨。如果夹子中没有手指,则 R1 变为 5V(或任何功率电平)。

当您插入手指时,C1 最多需要 10 秒才能放电到 U1a 的合理输入水平。D1 阻止 R1 高于 D1 的 Vf(硅二极管约为 0.6V)。没有 D1 电路也能正常工作,但需要很长时间才能开始。

D1可以是任何小信号硅二极管。

红外 LED 通过一个 270 欧姆电阻器驱动,提供 15mA 至 18mA 的电流。红外 LED 通常可以占用高达 50mA 的电流,但我不想过快耗尽电池电量。

U1b 的输出信号高约为 1V。

红外发射器和接收器的波长应在 900nm - 940nm 范围内。这些波浪会穿过皮肤、肌肉血液等。但是如果你的皮肤很黑,它们会被部分阻挡——那是因为黑色素的作用是阻挡光线。

选择与接收器波长相匹配的红外发射器。我选择了

  •  红外 LED = L-34F3C
  • 红外光电晶体管 = L-3DP3C

峰值在940nm处。许多其他 LED 和光电晶体管也同样工作得很好——我碰巧有很多这样的 LED。在eBay或您最喜欢的供应商中搜索“红外LED”和“红外光电晶体管”,并选择直径为3mm的供应商。

确保波长在 900nm - 940nm 范围内。

该电路由锂电池(高达 4.2V)或 4xAA 电池供电(请参阅我的 ECG 项目的第 12 步)。因此,原理图中的“5V”仅表示来自锂电池的 4V 或来自 Arduino 的 5V。

如果你把它构建为一个医疗设备,你会使用不同的过滤。您会担心滤波器引入的相移 - 切比雪夫滤波器和巴特沃斯滤波器具有不同的相移。而且你会使用质量更好的运算放大器!

第 4 步:构建电路

如果您已经构建了自己的放大器:

我在条带上建造了电路。这是一个简单的电路,我太不耐烦了,无法等待商用PCB。为了保持较小的面积,我垂直安装了大部分电阻器。该板为 1“x2”,高 15 毫米。你可以看到我使用的布局。

如果您更喜欢使用“真正的”PCB,那么您可以使用SM零件来降低高度。

光电晶体管安装在电路板的中央。该板固定在夹子中,并布置有泡沫橡胶,因此光电晶体管穿过夹子上的孔。

LED 安装在电线末端夹子的另一半。它被粘在适当的位置 - 我使用了 UHU,它足够坚固,可以工作,但如果需要,可以将其拉开。

如果您使用的是AD8232模块:

光电晶体管、LED、R6 和 R8 可以组装在 PPG 夹内。R7、R11、C7 和 C8 可以焊接在心电图机外壳内的一小块条板上。

 第 5 步:探头夹

我用3D打印机制作了探针夹。STL文件附在下面。

与3D打印一样,您需要对零件进行打磨,锉削和钻孔,以便它们适合。您需要一个 3.5 毫米(也可能是 4 毫米)的 LED 孔钻头,也许需要一个 1.5 毫米的螺丝孔钻头(取决于您使用的螺钉)。

CAD 模型是使用 Designspark Mechanical 设计的。可以从 RS 组件下载免费版本。我的 Designspark 源文件可在此处找到。

我在夹子上衬上了 1 毫米厚的旧鼠标垫软橡胶。它为您的手指提供了更好的防光密封,并且更舒适。自行车内胎也可以使用。

夹子的两半通过弯曲的电线和弹簧固定在一起。我用圆珠笔的弹簧切成两半。线材为0.5mm钢;一个精美的回形针可能会起作用。

夹子用 2x6mm 自攻螺钉拧在一起。在 eBay 上搜索“M2 沉头自攻螺钉”。我发现它们是组装小型 3D 打印物品的有用尺寸。

在开发过程中,我将 LED 和光电晶体管粘在黑色塑料管的壁上。如果您不想 3D 打印剪辑,您可以使用 PVC 管道制作该设置的更永久版本。

“1/2 英寸”管的外径为 21.4 毫米,内径为 18.0 毫米,除非您的手指特别大,否则应该没问题。

或者,您可以拆开商用脉搏血氧仪。eBay 上最便宜的不到 6 英镑。(花 7 英镑,您可以购买两个 - 一个用于此项目,一个用作血氧仪。

如果您使用的是AD8232模块:PPG夹子上不需要一个大盒子来容纳放大器,它就在ECG的外壳内。因此,打印两份较小的“上层”框的副本。

第 6 步:心电图单元硬件

这个体积描记图是我心电图项目的附加组件。PPG 的输出连接到 Arduino 的 A4 模拟输入。

我决定使用 3 针 0.1 英寸 Molex 连接器。立体声插孔看起来更好,但ECG的AD8232模块已经使用了3.5mm插孔。重要的是不能混淆这两个连接器:您不想将 5V 电源连接到连接到您身体上的 ECG 电极。

2.5 毫米立体声插孔会比 0.1 英寸 Molex 更好,但我手头没有 2.5 毫米插头/插座。

你可以看到我是如何将PPG插座安装到(相当拥挤的)心电图箱中的。毫无疑问,您的布局会有所不同。

如果您已经构建了自己的放大器:三根线连接到 Arduino Nano 的 0V、5V 和 A4。

如果您使用的是AD8232模块:光电晶体管、LED、R6和R8可以组装在PPG夹内。R7、R11、C7 和 C8 可以焊接在心电图机外壳内的一小块条板上。

 第 7 步:分析

计算心电图和 PAT 之间的间隔。

PAT是从心电图R波的峰值到收缩峰值的某个地方测量的。一些研究人员测量到收缩峰值的顶部,一些研究人员测量收缩峰值的最大向上斜率(这就是这张草图的作用)。

程序显示的 PAT 值是通过 5 阶中值滤波器和低通滤波器滤波的计算 PAT。当噪声产生几个非常奇怪的值时,中值滤波器很有用。低通滤波器会阻止显示值变化过快。

要启用 PAT 计算,请确保在草图开头附近定义 bHasPAT。

#define bHasPAT<br>

草图还可以估计 QT 间期。要启用 QT 估计,请确保在草图开头附近定义 bHasQT。

#define bHasQT<br>

QT 间期是预测室性心律失常的有用测量方法。“长QT综合征”可以是先天性的,也可以是由于各种药物或药物引起的。

计算很难自动化,许多医生不信任自动化系统。算法有很多不同的尝试,这对我来说意味着问题还没有“解决”。你得到的结果可能取决于你把线索放在哪里。

QT 间期定义为从 Q 波开始到 T 波结束的时间。Q 波的开始是 ECG 信号在大 R 尖峰之前开始下降的时间。T 波的末端是穿过 T 波下降部分的线与基线相交的地方。在教科书中,这看起来很容易。

在现实世界中,这要困难得多。信号中有噪声。“基线”在哪里?T波的斜率是多少?你在哪里测量它?

此步骤的其余部分将介绍我的解决方案。除非你对数学感兴趣,否则你可以跳过它。

Q 波的开始很容易。它是在 R 尖峰之前最后一次信号差为正之后的样本。您必须平滑信号以消除最糟糕的噪音。

我说 Q 波很容易,因为 Q 波太快了,你犯的任何错误都只会影响估计的 QT 间隔几毫秒。

T波更难,因为它更慢,更模糊。我开发的用于查找 T 波末端的算法如下。

心电图信号被区分和平滑。R波的峰值与分化心电图信号的最大值相对应。

T波的峰值位于。它是 R 波后 200mS 和 500mS 之间的 ECG 信号的最高值。

一旦找到T波的峰值,程序就会计算信号从峰值到峰值后100mS的回归线。程序开始收集:

  • 总和
  • T 之和,
  • T*a 之和
  • T*T 的总和

(其中“T”是自 R 峰值以来的时间,“a”是心电图信号)

求和在R峰值后100mS停止,并计算线。但是,这些值是加权的,因此 100mS 间隔的一半值值更高。

求和的值允许我们计算回归线。

您将在任何统计课程中学习回归公式:

a = (Σxy - Σx*Σy/n)/(Σx²-Σx*Σx/n);

 b = (Σy-a*Σx)/n;

(其中 y = ax + b}

T 波的末端是线穿过“基线”的地方,但基线在哪里?

心电图信号呈指数平滑。当每个样品到达时,使用

smoothed_sample = smoothed_sample*alpha + 样本*(1-alpha);

Alpha 应计算为

 阿尔法 = exp(-1/Tau);

但它可以更便宜地近似为

阿尔法 = 1 - 1/Tau;

Tau(时间常数)越大,信号越平滑;即平滑信号变化越慢。

估计的基线是信号的指数平滑副本。当信号远离当前估计基线时,指数的时间常数更长:

  • “sample”是最新的示例
  • diff 是(样本的一阶导数)²
  • ds 是 diff 平滑的,time_const=20mS
  • Tau = 2*(ds+sqr(样本基线)+1)

基线是使用 Tau 时间常数平滑的“样本”(最新样本)。因此,由于突然发生的巨大变化(如R波和T波),基线变化缓慢,但接近(人类认为的)真正的基线。

“样本的一阶导数”实际上是样本[i]-样本[i-n]。其中 n 被选择在 20mS 之前。(“n”的值越大,差分越平滑。

我承认,很多算法是相当武断的,但它至少和你在科学论文中找到的其他算法一样好。上图显示了应用于包含各种错误的典型“真实世界”记录数据库时的结果。

正常的 QT 间期在以下范围内:

  •  男子 390 - 450ms
  •  女士 390 - 460ms

但这取决于心率。因此,调整 QT 间期以补偿心率以提供 QTc。

使用了几种补偿公式:

  • BazettQTc = QT/sqrt(RR/1000)
  • FridericiaQTc = QT/((RR/1000)^(1/3))
  • FraminghamQTc = QT + 0.154 * (1000 - RR)
  • 霍奇斯QTc = QT + 1.75 * (BPM - 60)

(QT 和 RR 以 mS 为单位,RR = 60000/BPM)

这些公式的图表如上所示:400mS 的 QT 间期被“补偿”为各种心率。

本文比较了配方(针对 6000 多名患者)。它完全拒绝了 Bazett,并建议 Fridericia 比其他人略好。因此,我选择了 Fridericia 公式。

事实上,我已经将 Fridericia 公式重新计算为二次方程,这样就不必计算立方根(这在 Nano 上非常慢)。我们称之为“彼得公式”:

  • 彼得公式:QTc = QT * ((0.00728 - 0.0000164*BPM)*BPM + 0.622)

它给出的答案与 Fridericia 公式相同,在正常范围 QT 间期和心率上优于 0.5%。

程序显示的 QTc 值是通过 5 阶中值滤波器和低通滤波器滤波的计算出的 QTc。

第 8 步:心电图单元软件

当心电图软件处于“大显示”或“小显示”模式时,会显示 PPG 信号。PPG 迹线以青色绘制。

下载下面的文件。将以下文件复制到名为 ArduECGPPG 的文件夹中:

  •  ArduECGPPG.ino
  •  简单ILI9341.h
  •  SimpleILI9341.cpp

关闭警告。我的代码会产生很多警告,我觉得这些警告过多且无用。在Arduino IDE(版本1.8或更高版本)中,选择File|“首选项”菜单项以打开“首选项”对话框。将“编译器警告”设置为“无”。关闭对话框。

要启用 PPG 跟踪,请确保在草图开头附近定义了 bHasPPG。

#define bHasPPG<br>

如果将其注释掉,则不会执行任何 PPG 代码。

在小模式下,程序可以显示过去 15 分钟内心率和 PAT 变化情况的图表。在上面的示例中,您可以看到运动期间心率如何增加,而 PAT 如何降低。

若要启用图表,请确保在草图开头附近定义 bHasChartMode。

#define bHasChartMode<br>

编译文件并将它们上传到 Nano。

如果您已经构建了自己的放大器:

在 ArduECGPPG.ino 中,A4(PPG 信号)定义为

pinMode(A4,INPUT_PULLUP)<br>

因此,如果 PPG 削片断开,则输入被拉至 5V。草图识别 PPG 信号为高电平,但不显示它。

如果您使用的是AD8232模块:

使用AD8232模块时,“上拉”技巧不起作用,AD8232始终产生正确范围内的输出。但是,当PPG削片与AD8232模块断开连接时,该模块会产生大量噪声。

因此,作为一项额外的测试,草图着眼于总“能量”(整个扫描的总变化)。如果“能量”大于阈值,则不会显示屏幕的下一次扫描。

 第 9 步:未来

如何推进这个项目?

您可以在测量时仅打开 LED 来节省功耗,但放大器必须快速响应,并且必须在 s/w 中完成滤波。您可以在 LED 熄灭然后亮起的情况下测量两次光照水平,并使用差异来补偿环境光水平。

保存一整天的数据会很好。这大约是 68MB 的数据(假设为一个字节值)。SD卡的写入时间变化很大,所以我可能会使用两个Arduino:一个用于收集样本,另一个用于缓冲它们并写入SD卡。

您可以完全省去心电图。例如,您可以只显示 PPG 和 Poincare 显示器。

您可以自动对 PPG 信号进行进一步分析。研究人员试图自动测量PPG信号的各个方面:

  • 脉冲到达时间 (PAT)
  • 收缩脉搏的上升时间
  • 舒张期脉搏的下降时间
  • 收缩期和舒张期峰值的相对高度
  • 从收缩峰值到舒张峰值的时间
  • 收缩峰值的振幅
  • 双峰切口的深度
  • 曲线不同部分的面积
  • PPG峰的宽度

然后,他们试图将不同的测量值与血压、每搏输出量、动脉硬度、动脉粥样硬化、疼痛程度、呼吸频率、情绪压力等相关联。

他们研究 PPG 的一阶、二阶和三阶导数,甚至使用傅里叶变换和小波分析。通过比较近端和远端 PPG 的 PAT,可以估计不同动脉的状态。

问题在于,人与人之间的差异很大。它可能取决于皮肤类型、环境光、肢体长度、体温等。

您需要校准每个人,以便它仅在统计上对大量人群有用,或用于评估个体对治疗的持续反应。

您可以添加第二个 PPG 探头并测量脉冲到达时间和脉冲传输时间。该小组使用一个与手指一样长的夹子,两端各有一个 PPG 传感器来测量脉搏波速度。他们声称收缩压的准确率为 90%,舒张压的准确率为 63%。

已经提出了各种方程:

  • BP = a*ln(PTT) + b
  • BP=a/PTT + b
  •  BP=a/(PTT+c)² + b

其中 a、b 和 c 是常数。不幸的是,很少有人说出这些常数是什么!大多数人都同意你必须校准每个人。这个小组说你还必须考虑心率。这个小组建议这些常量:

  • t = 60000/HRbpm - 帕特
  • 收缩压 = 184.3 - 1.329*HRbpm + 0.0848*t
  • 舒张压 = 55.96 - 0.02912*HRbpm + 0.02302*t

(但这些数字对我不起作用。

PAT取决于血压,但也取决于“血管张力” - 动脉壁的硬度。PAT越短,血压越高,血管张力也越高。有一种观点认为,血管张力与PPG峰的宽度有关。也许可以使用脉冲宽度从 PAT 中删除血管音调成分。

一些研究人员认为,仅从PPG信号的形状就可以估计血压。PPG波不同高度的相对脉冲宽度可能与心血管健康有关。

您可以在 MIMIC 数据库上尝试自己的算法。该小组通过使用在数据库上训练的神经网络来预测PGG的BP,取得了非常好的结果;当然,由于它是一个神经网络,你不知道它在做什么。该小组使用手工制作的算法。本文。描述如何使用在自己的数据上训练的神经网络。

外伤引起的失血对PAT有很大影响。你可以从你的手指上得到一个心电图信号:它的质量很差,但足以看到R波。想象一下,在患者手指上的 PPG 夹中加入心电图电极。带屏幕的电子设备绑在另一只手的手腕上;它也有一个电极。

显示屏显示当前心率、PAT 和过去 10 分钟的“图表”显示。心率上升和 PAT 升高意味着失血。

这是对这项研究的一个很好的(10 年前)的调查。这群人说脚趾比手指好。PAT和PTT可能比舒张压更能预测收缩压。

正如你现在一定已经猜到的那样,很多人有很多不同的想法,但没有人设法说服医学界相信他们的想法是可行的。