当前位置:   article > 正文

基于Waffle Nano的便携心电监测仪_ad8232采样频率

ad8232采样频率

基于Waffle Nano的便携心电监测仪

前言

​ 本次暑假短学期,在黑胡桃实验室做了个显示心电图和心率的小项目,细节方面还有待完善。本文主要讲解如何利用AD8232和Waffle Nano制作心电监测仪。开发环境点此WaffleMaker

概览

在这里插入图片描述 在这里插入图片描述

功能简介

​ 1.显示实时心率

​ 2.显示实时心电图

​ 3.手势右划进入心电图界面,手势左划返回主界面

使用方法

​ 使用时将配套的电极贴片的L端贴左胸,R端贴右胸,COM端贴左腹(顺便提一句,L和R端贴反会显示和原波形刚好相反的波形)
在这里插入图片描述

AD8232传感器

在这里插入图片描述

​ AD8232是一款用于心电信号测量及其他生物电测量的集成信号调理模块。该芯片可以在有运动或远程电极放置产生的噪声的情况下提取、放大及过滤微弱的生物电信号。该芯片使得模数转换器(ADC)或嵌入式微控制器(MCU)能够便捷的采集输出信号。

传感器接线
Waffle Nano传感器
3V33.3V
G02LO+ #用于脱落检测
G14LO- #用于脱落检测
G05OUTPUT #输出采集到的人体生理电信号
GNDGND
/SDN #可通过赋予高低电平使传感器进入启动或休眠状态,本次项目未使用
AD8232数据采集

​ AD8232采集到的是电信号,我们需要的是数字信号,因此可以使用ADC(模数转换器)将电信号转换为数字信号用于之后的数据处理。Waffle Nano的多个引脚具有ADC功能,本次使用5号引脚。我写了个简单的库文件来调用AD8232。

from machine import ADC, Pin
class AD8232:
    def __init__(self,analogPin,LO1Pin,LO2Pin):
        self.adc = ADC(Pin(analogPin))
        self.adc.equ(ADC.EQU_MODEL_8)
        self.LO1Pin = Pin(LO1Pin, Pin.IN)
        self.LO2Pin = Pin(LO2Pin, Pin.IN)
    def value(self,LO = 1):
        if LO == 1:
            return self.LO1Pin.value() #返回LO+,LO-电平值
        elif LO == 2:
            return self.LO2Pin.value()
    def read(self):
        data = self.adc.read() #读取心电数据
        return data
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
AD8232数据处理

​ 我们算法设置的采样频率为100HZ,即通过计时器每0.01s采集一个数据,这0.01秒内实际可获得51个左右的ADC数据,将ADC数据进行简单过滤(去掉一个最大值和最小值,再求算术平均)得出一个数据值,该值就是我们之后绘制心电图和计算心率实际用到的数据。同时由于我们除去计时器完成一次主循环所耗时间几乎可以忽略,所以计时器设置的0.01s就是完成一次数据采集耗费的时间,之后R-R间期的时间间隔可通过 循环次数*0.01s 计算得出。

def fliter_adc(): #过滤0.01秒内的adc数据,取均值作为采样值
    global size
    start = utime.ticks_ms()
    while True:
        if(size < 70):
            if heartSensor.value(LO = 1) != 1 and heartSensor.value(LO = 2) != 1: #判断电极片是否脱落
                adc_data[size] = heartSensor.read()
                size +=1

        if(utime.ticks_diff(utime.ticks_ms(),start)>=sample_time*1000):
            break
    
    if size > 5:
        aver = (sum(adc_data[0:size]) -  max(adc_data[0:size]) - min(adc_data[0:size])) / (size -2)
    else:
        aver = 888
    
    size =0
    return aver
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

PAJ7620手势识别

在这里插入图片描述

​ 手势识别在本次项目中只是辅助功能,我们需要传感器能检测左划和右划手势。7620本身已经写好算法可以判断我们作出的是何种手势,只需要向存储手势的寄存器读取数据即可。

​ 使用方法简单来讲分三步

​ 1.唤醒7620传感器

​ 2.向使能寄存器写入数据以控制7620传感器只识别需要的手势

​ 3.从手势识别中断标志寄存器读取数据来获得手势信息

在这里插入图片描述

​ 我们只用到左划和右划手势,所以只需要将bit[2]和bit[3]设置为1,其余为0

i2c.write(115, b'\x41\x0C')  #设置为只有向左移动和向右移动可以被识别
  • 1

在这里插入图片描述

ges = i2c.readfrom_mem(115, 0x43, 1) #将读取出来的数据进行if条件判断即可实现我们想要的功能
  • 1
传感器接线
Waffle Nano传感器
3.3VIN
IO1SCL
IO0SDA
GNDGND

心电图绘制

​ 本项目使用的显示屏模块为st7789,我们将每一个可用数据赋予屏幕坐标,并两两连线,最后显示出来的效果就是心电图了。X值只需每次自增加一即可,Y值则需要将数据的大小映射到[0,240]区间。

在这里插入图片描述

心率计算

在这里插入图片描述 在这里插入图片描述

​ 我们观察绘制出来的波形以及网上搜到的心电图波形,可以看到特征鲜明(变化快,幅度大)的R波。心率可通过R-R间期来计算。所以我们的主要目标就是识别R波。最初我是根据他的斜率特征进行判别,当前数据值减去前一个数据值的差值(X的差值自然为一)即是斜率,通过设置一个阈值条件来判别,就可识别R波了。这样做确实能计算出心率,但是这样得出来的结果,稳定性不是很高。我们需要找寻一个更好的R波识别算法。在快速浏览网络上有关心率计算的文章后,我最后使用了一种动态阈值的算法来识别R波,本来此方法是用于通过脉搏计算心率的,脉搏传感器识别出来的数据波形是每个周期都只有一个明显波峰,而我们的波形一个周期内的高峰既有R波又有T波。但是没有关系,可以观察到R波和T波间隔时间极短,我们可以将间隔的时间也加入if条件以排除掉同一周期内的其他高峰。

动态阈值识别R波
preReadData = readData
readData = fliter_adc()
if readData - preReadData < num_filter:   #滤除突变噪声信号干扰
    data[idx] = readData                        #填充缓存数组
    idx += 1	

if idx >= DATA_SIZE:
    idx = 0	                      # 数组填满,从头再填
    max_data = max(data)          # 通过缓存数组获取波峰、波谷值,并计算中间值作为判定参考阈值
    min_data = min(data)
    mid = (max_data + min_data) / 5 * 2.65  #该系数可微调,升高或降低阈值
    num_filter = (max_data - min_data) / 2

pre_Flag = Flag	
if readData > mid:
    Flag =  1
else: 
    Flag =  0

if pre_Flag == 0 and Flag == 1 and timeCount > 35 and readData - preReadData >= 5:  # 寻找到“信号上升到振幅中间位置”的特征点
    rCount += 1
    rCount %= 2
    if rCount == 1: #两次心跳的第一次
        timeCount=0   
    
    elif rCount == 0: # 两次心跳的第二次
        if timeCount > 35:
            IBI = timeCount * sample_time	#计算相邻两次心跳的时间,得到 IBI,可以加上计时器时间以获得更精准的值
            BPM = 60 / IBI                  # 通过 IBI 得到心率值 BPM
            if BPM > 170:                   #限制BPM最高显示值
                BPM = 170
            elif BPM < 30:                  #限制BPM最低显示值
                BPM = 30
            print(calcul_averBPM() , BPM)
        else:
            rCount = 1
        timeCount=0 
else:
    Flag =  0

timeCount += 1   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

项目复现

Github项目源码,相关细节见代码注释。

​ 你需要准备Waffle Nano 、AD8232、PAJ7620、st7789屏幕模块、一块面包板以及杜邦线若干。在WaffleMakerIDE上烧录ad8232.py和main.py就可以观察自己的心电图和心率了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/246435
推荐阅读
相关标签
  

闽ICP备14008679号