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

前言

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

概览

功能简介

​ 1.显示实时心率

​ 2.显示实时心电图

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

使用方法

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

AD8232传感器

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

传感器接线
Waffle Nano 传感器
3V3 3.3V
G02 LO+ #用于脱落检测
G14 LO- #用于脱落检测
G05 OUTPUT #输出采集到的人体生理电信号
GND GND
/ 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
AD8232数据处理

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

def fliter_adc(): #过滤0.01秒内的adc数据,取均值作为采样值global sizestart = 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 +=1if(utime.ticks_diff(utime.ticks_ms(),start)>=sample_time*1000):breakif size > 5:aver = (sum(adc_data[0:size]) -  max(adc_data[0:size]) - min(adc_data[0:size])) / (size -2)else:aver = 888size =0return aver

PAJ7620手势识别

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

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

​ 1.唤醒7620传感器

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

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

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

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

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

心电图绘制

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

项目复现

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

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

基于Waffle Nano的便携心电监测仪相关推荐

  1. Waffle Nano初相识

    Waffle Nano是一款由黑胡桃实验室开发的基于OpenHarmony系统打造的创客套件,是一款集成了多种物联网标准通信协议传感器和传感器组的兼容Aduino的传感器.可用于开发各种情景. 黑胡桃 ...

  2. 中国远程心电监测仪市场研究与预测报告(2021版)

    内容简介: 远程心电监测是指在一定范围内的心电信息系统支持下,利用通信.互联网和电子计算机技术进行远距离心电信号监测并实时或间断传输心电信号,或和实时和间断存储心电信号,或和对心电信号进行自动/人工分 ...

  3. B002 - 基于嵌入式的老人定位追踪监测仪

    摘要 本项目设计一种可穿戴式的跌倒检测报警系统,通过水平检测模块检测水平信息,采用STC新型单片机进行实时计算.分析,判别是否发生跌倒,若判定为佩戴者跌倒则控制MCU将通过GPS模块实时获取经纬度信息 ...

  4. 【AI达人创造营第二期】基于Jetson nano的餐厅自助结账系统部署

    基于Jetson nano的餐厅自助结账系统部署 一. 前言 二. 开发环境 2.1 硬件 2.2 软件 三. Jetson nano基础环境配置 3.1 镜像烧录 3.2 网络连接 3.3 更换镜像 ...

  5. 基于Jetson Nano与STM32通信的颜色识别与伺服驱动器控制

    基于Jetson Nano与STM32通信的颜色识别与伺服驱动器控制 jetrson nano部分 颜色识别 串口通信 数据传输 完整代码 stm32 部分 数据解读 电机控制 主函数 电机加减速 硬 ...

  6. 基于Jetson nano的人脸识别系统

    基于Jetson nano的人脸识别系统 一.Jetson nano简述 二.人脸检测 A.人脸检测常用算法 B.人脸对齐 C.活体检测 三.人脸跟踪 A.常用跟踪算法 四.TCP/UDP通信协议 A ...

  7. 基于RTT Nano的多任务嵌入式程序设计

    基于RTT Nano的多任务嵌入式程序设计 一.国产RT-Thread操作系统概述 1.简述 2.特点 3.优势 二.RTT-Nano的功能框架 三.在stm32F103上移植RTT Nano 1.添 ...

  8. 《15寸移动式心电监测仪》制作纪实 : 白话ECG导联原理、身体位置与连接

    <15寸移动式心电监测仪>制作纪实 : 白话ECG导联原理.身体位置与连接 写在前面 ECG导联啥原理 ECG导联连身体哪里 ECG导联咋连 写在前面 本系列CSDN为<15寸移动式 ...

  9. 基于jetson nano和yolov5 的 车行人检测(一)

    毕业设计ing,但中途要出去一波.做个记录,备忘. 基于jetson nano和yolov5 的 车行人检测. 目前已经做的工作: 1.数据集的制作,原本是用的老师给的自己拍的一些数据(含夜间),但效 ...

最新文章

  1. 机器学习第10天:模型评价方法及代码实现
  2. 数字图像处理的就业前景
  3. mysql数据库断开连接_解决mysql服务器在无操作超时主动断开连接的情况
  4. Docker中部署项目到容器
  5. java异常体系_Java 异常体系
  6. jmeter 插件 监视器 图形界面使用
  7. 漫画:给女朋友介绍什么是 “元宇宙” ?
  8. 用简单的语言描述C++ 是什么?
  9. MySQL日志审计 帮你揪出内个干坏事儿的小子
  10. php 子类重新定义父类的变量_PHP设计模式 ——(抽象工厂模式)
  11. Java反射机制的缺点
  12. Android中的文字占位符
  13. 使用微软MediaCreationTool21H1.exe制作u盘windous10启动盘
  14. 图形化编程Mixly——RFID智能门禁
  15. python中阶乘怎么写程序_Python 阶乘实例
  16. 解答,修正(JAVA+=运算程序诡异事件 )
  17. 工作找了很多,兜兜转转,就是没遇到合适的,怎么办
  18. safari浏览器的一些兼容性问题总结
  19. python爬取豆瓣图书top250_「豆瓣读书250」爬取豆瓣TOP250书单 - seo实验室
  20. java输出GPA_请完成下列Java程序:实现换算GPA,对于学生学习的每一门课程,都输入两个..._考试资料网...

热门文章

  1. SPI菊花链走线思考
  2. AC电源品字插座和空开接线图
  3. 戴尔 E5480 CDM70 COMPAL LA-E082P REV : 1.0笔记本点位图
  4. 51nod 2382 一半的一半 (sprintf()函数的用法)
  5. 【路径规划】基于蚁群算法实现多式联运路径规划问题matlab源码
  6. C++编写学生成绩管理系统
  7. 后端传递数据给前端做导出Excel的vo类
  8. 西门子S71200与三菱FX5U数据交换
  9. mysql plus crud_Mybatis Plus学习笔记(入门-CRUD)
  10. 关于element table 动态表头+动态表头及内容+表格优化+初始化表格+隐藏功能,技术提升请来!