【DigiKey创意大赛】便携生命探测仪05+心电数据解析并在PC显示
[复制链接]
播放器加载失败: 未检测到Flash Player,请到 安装
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端子上,并用热熔胶固定好。
心电电极飞线:板子上有留有三个电极的焊盘测试点,我找到一个耳机插头形式的导联线,只需要在板上焊接一个耳机插座即可,这个比较容易,焊好后用热熔胶固定。最终的成品如下图。
- 软件编写
首先是分析LH001-91评估板的程序可知,最终输出的每个采样点数据是一个字符串,如下图所示。
这个字符串中包含心电原始数据,滤波后数据,心率,导联状态等信息,最后以回车换行结尾。数据格式有整型和浮点两种,解析的时候可以都转换成浮点数。实际转换代码如下。
代码1:
- #include <Arduino.h>
-
-
- float dataArray[10];
- int dataArrayIndex = 0;
- String data = "";
-
- void setup() {
-
- Serial0.begin(1500000);
- Serial1.begin(1500000);
-
- data.reserve(200);
- }
-
- void loop() {
-
- data = "";
- if (Serial0.available() > 0) {
-
- data = Serial0.readStringUntil('\n');
-
- data.trim();
-
-
- 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};
-
-
-
-
-
-
-
-
- void Float2Byte(float *target,unsigned char *buf,unsigned char beg)
- {
- unsigned char *point;
- point = (unsigned char*)target;
- buf[beg] = point[0];
- buf[beg+1] = point[1];
- buf[beg+2] = point[2];
- buf[beg+3] = point[3];
- }
-
-
- void setup() {
-
- Serial0.begin(1500000);
- Serial1.begin(256000);
-
- data.reserve(200);
- }
- int fps_num = 0;
- void loop() {
-
- data = "";
- if (Serial0.available() > 0) {
-
- data = Serial0.readStringUntil('\n');
-
- data.trim();
-
-
- 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;
-
- Serial1.write(DataScope_OutPut_Buffer,14);
-
- fps_num = 0;
- }
- fps_num ++;
-
-
-
-
-
-
-
-
-
-
-
- }
- }
手头没有心电信号模拟仪,只好亲自上阵,电极片贴在胸口,如下图。
期间经过多次调试修改错误,最终实现在PC端显示心电波形。具体效果见开头视频。
数据解析没问题后,下一步就是将这部分整合到主控端,就基本完成本次作品设计了。
|