610|6

282

帖子

7

TA的资源

一粒金砂(高级)

楼主
 

【DigiKey创意大赛】便携生命探测仪05+心电数据解析并在PC显示 [复制链接]

 
000

 
上一帖介绍了驱动BME680并将检测结果显示在屏幕上,然后设计一个操作交互界面,实现用户操作功能。本帖介绍如何获取心电数据并解析协议,最终显示在电脑上。

一、方案和开发板的选择

本次作品为了实现心电采集,我选用了领慧立芯推出的医疗级模拟前端心电采集方案。具体实现采用的是领慧立芯的心电采集评估板,该评估板基于LH001-91设计。
LH001-91是专门针对心电信号采集而开发的医疗级模拟前端,集成了24位Σ-Δ ADC,可编程增益放大器,150Hz带内噪声3μVpp,包括右腿驱动,导电脱落监测等功能的AFE。产品的性能指标优越,其中输入参考噪声2.9 μVpp ,共模抑制比 117dB,内部参考温漂16ppm/℃;静态功耗0.1μW,各项核心指标均达到国际品牌的水平,甚至整体性能优于国际厂商同类型产品,并得到国内医疗客户的专业评测,是目前国内极少能够通过医疗测试的国产芯片。使国内高精度信号链产品有望进入医疗领域,结束被欧美品牌垄断的局面。
更详细资料见如下链接:
下图是我申请到的LH001-91的评估板,主要由AFE(LH001-91),通用MCU和两侧的三个电极组成。
领慧立芯同时提供全套的软件演示方案,下图是基于领慧立芯的评估板获得的心电图实时波形图,心电特征明显,满足医疗级应用。
为了降低主控端的软件复杂度,我还选用了一块ESP32-C6开发板做心电数据解析,该开发板由DFRobot设计研发,型号是FireBeetle 2 ESP32-C6。如下图所示。
FireBeetle 2 ESP32-C6是一款基于ESP32-C6芯片设计的低功耗物联网主控板,适用于智能家居项目。ESP32-C6支持Wi-Fi 6、Bluetooth 5、Zigbee 3.0、Thread 1.3通讯协议,可接入多种通讯协议的物联网网络。FireBeetle 2 ESP32-C6支持Type-C、5V DC、太阳能供电,部署时有更多的供电方式选择。
在本次作品中主要是用到了ESP32-C6的两个串口做协议转换。原理框图如下图。
我在PC端用了一个能显示串口数据波形的软件,ESP32-C6负责从LH001-91评估板接收字符串数据,然后转换成上位机软件能识别的协议,再从另外一个串口发出去。

二、硬件电路连接

LH001-91评估板只有一个type-c接口,采集心电用的板子上的焊盘做电极。为了能跟ESP32-C6板连接,需要将电源和串口飞线出来。为了方便采集心电,也需要引出导联线接口。
电源和串口飞线:电源部分直接从USB的5V网络焊盘上引出电源和接地。串口是从板子上的CH340E芯片TX和RX直接飞线出来,为了防止TX线输出信号线与导致烧IO口,我把PCB走线割断串联了一个100欧姆的电阻。最终将飞线出来的接头汇总到一个PH端子上,并用热熔胶固定好。
心电电极飞线:板子上有留有三个电极的焊盘测试点,我找到一个耳机插头形式的导联线,只需要在板上焊接一个耳机插座即可,这个比较容易,焊好后用热熔胶固定。最终的成品如下图。
  1. 软件编写
首先是分析LH001-91评估板的程序可知,最终输出的每个采样点数据是一个字符串,如下图所示。
这个字符串中包含心电原始数据,滤波后数据,心率,导联状态等信息,最后以回车换行结尾。数据格式有整型和浮点两种,解析的时候可以都转换成浮点数。实际转换代码如下。
代码1:
#include <Arduino.h>

// 定义一个足够大的数组来存储浮点数
float dataArray[10];  // 假设我们知道数组的最大长度
int dataArrayIndex = 0;
String data = "";

void setup() {
  // 初始化串口通信
  Serial0.begin(1500000);  //pin 16/17  to ECG
  Serial1.begin(1500000);  //pin 4/5    to PC or Main board
    // reserve 200 bytes for the inputString:
  data.reserve(200);
}

void loop() {
  // 检查是否有数据可读
  data = "";
  if (Serial0.available() > 0) {
    // 读取串口数据
    data = Serial0.readStringUntil('\n');
    // 移除字符串末尾的换行符
    data.trim();

    // 使用 split 方法按照逗号拆分字符串
    int lastIndex = 0;
    for (int i = 0; i < data.length(); i++) {
      if (data[i] == ',') {
        // 将子字符串转换为浮点数并存储在数组中
        String numberString = data.substring(lastIndex, i);
        dataArray[dataArrayIndex++] = numberString.toFloat();
        lastIndex = i + 1;
      }
    }

    // 处理最后一个元素
    String lastNumberString = data.substring(lastIndex);
    dataArray[dataArrayIndex++] = lastNumberString.toFloat();

    // 重置索引,准备发送数据
    dataArrayIndex = 0;
    if (0 != dataArray[6]) {
      // 将浮点数数组转换回字符串,以逗号分隔,并添加回车符
      for (int i = 0; i < 10; i++) {
        Serial1.print(dataArray[9 - i]);
        if (i < 9) {
          Serial1.print(",");
        } else {
          Serial1.println();
        }
      }
    }
  }
}

 

设计此代码我取了个巧,直接把需求写清楚发给Kimi,然后Kimi会给出一份参考代码,我在参考代码上修改成我需要的形式,省去不少脑细胞。下图是我截取的转换后数据,程序转换效果不错。
然后按照上位机软件的协议要求修改发送代码,上位机显示只需要滤波后的波形数据,心率,导联信息,其他的可以都舍弃掉。改完的代码如下。
代码2:
#include <Arduino.h>

// 定义一个足够大的数组来存储浮点数
float dataArray[10];  // 假设我们知道数组的最大长度
int dataArrayIndex = 0;
String data = "";

unsigned char DataScope_OutPut_Buffer[15] = {0};	   //串口发送缓冲区


//函数说明:将单精度浮点数据转成4字节数据并存入指定地址 
//附加说明:用户无需直接操作此函数 
//target:目标单精度数据
//buf:待写入数组
//beg:指定从数组第几个元素开始写入
//函数无返回 
void Float2Byte(float *target,unsigned char *buf,unsigned char beg)
{
    unsigned char *point;
    point = (unsigned char*)target;	  //得到float的地址
    buf[beg]   = point[0];
    buf[beg+1] = point[1];
    buf[beg+2] = point[2];
    buf[beg+3] = point[3];
}


void setup() {
  // 初始化串口通信
  Serial0.begin(1500000);  //pin 16/17  to ECG
  Serial1.begin(256000);  //pin 4/5    to PC or Main board
    // reserve 200 bytes for the inputString:
  data.reserve(200);
}
int fps_num = 0;//丢点计数
void loop() {
  // 检查是否有数据可读
  data = "";
  if (Serial0.available() > 0) {
    // 读取串口数据
    data = Serial0.readStringUntil('\n');
    // 移除字符串末尾的换行符
    data.trim();

    // 使用 split 方法按照逗号拆分字符串
    int lastIndex = 0;
    for (int i = 0; i < data.length(); i++) {
      if (data[i] == ',') {
        // 将子字符串转换为浮点数并存储在数组中
        String numberString = data.substring(lastIndex, i);
        dataArray[dataArrayIndex++] = numberString.toFloat();
        lastIndex = i + 1;
      }
    }

    // 处理最后一个元素
    String lastNumberString = data.substring(lastIndex);
    dataArray[dataArrayIndex++] = lastNumberString.toFloat();

    // 重置索引,准备发送数据
    dataArrayIndex = 0;

    if (fps_num > 8) 
    {
      //丢点处理,防止屏幕刷新过快
      DataScope_OutPut_Buffer[0] = '$';  //帧头
      Float2Byte(&dataArray[5],DataScope_OutPut_Buffer,1);
      Float2Byte(&dataArray[6],DataScope_OutPut_Buffer,5);
      Float2Byte(&dataArray[7],DataScope_OutPut_Buffer,9);
      DataScope_OutPut_Buffer[13] = 13;
      // for (int i = 0; i < 14; i++) {
        Serial1.write(DataScope_OutPut_Buffer,14);      
      // }
      fps_num = 0;
    }
    fps_num ++;
    // if (0 != dataArray[6]) {
    //   // 将浮点数数组转换回字符串,以逗号分隔,并添加回车符
    //   for (int i = 0; i < 10; i++) {
    //     Serial1.print(dataArray[9 - i]);
    //     if (i < 9) {
    //       Serial1.print(",");
    //     } else {
    //       Serial1.println();
    //     }
    //   }
    // }
  }
}

 

手头没有心电信号模拟仪,只好亲自上阵,电极片贴在胸口,如下图。
期间经过多次调试修改错误,最终实现在PC端显示心电波形。具体效果见开头视频。
数据解析没问题后,下一步就是将这部分整合到主控端,就基本完成本次作品设计了。

最新回复

楼主分享的内容确实值得学习,希望有机会能亲自动手实验一下啊   详情 回复 发表于 2024-9-25 13:29
点赞 关注
 
 

回复
举报

7294

帖子

2

TA的资源

版主

沙发
 
3导联应该只能出一个心电数据吧?

点评

是的,只有单导数据  详情 回复 发表于 2024-9-26 12:20
 
 
 

回复

421

帖子

7

TA的资源

纯净的硅(初级)

板凳
 
别光顾着开发新东西,也要适时锻炼身体,看这肉...........

点评

年纪大了,练不动了  详情 回复 发表于 2024-9-26 12:20
 
 
 

回复

756

帖子

4

TA的资源

纯净的硅(高级)

4
 

楼主分享的内容确实值得学习,希望有机会能亲自动手实验一下啊

点评

那就申请板子动起来  详情 回复 发表于 2024-9-26 12:21
 
 
 

回复

282

帖子

7

TA的资源

一粒金砂(高级)

5
 
wangerxian 发表于 2024-9-23 20:55 3导联应该只能出一个心电数据吧?

是的,只有单导数据

 
 
 

回复

282

帖子

7

TA的资源

一粒金砂(高级)

6
 
lansebuluo 发表于 2024-9-24 08:23 别光顾着开发新东西,也要适时锻炼身体,看这肉...........

年纪大了,练不动了

 
 
 

回复

282

帖子

7

TA的资源

一粒金砂(高级)

7
 
chejm 发表于 2024-9-25 13:29 楼主分享的内容确实值得学习,希望有机会能亲自动手实验一下啊

那就申请板子动起来

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表