news 2026/6/1 22:00:26

基于XIAO nRF52840与Bitalino ECG模块的可穿戴心率监测器DIY全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于XIAO nRF52840与Bitalino ECG模块的可穿戴心率监测器DIY全流程

1. 项目概述:从零构建一个可穿戴心率监测器

心率监测,听起来像是专业医疗设备才有的功能,但如果你手头有一块像XIAO nRF52840这样的低功耗蓝牙微控制器,再搭配一个合适的生物医学传感器,自己动手做一个其实并不遥远。这个项目就是一次将嵌入式系统开发与生物医学信号处理相结合的实践,目标是打造一个可以佩戴在身上的、能够实时显示心率状态的可穿戴设备。整个过程涉及硬件选型、电路设计、信号处理、固件编程以及外壳制作,算是一个比较完整的微型产品开发流程。

我这次使用的核心是Seeed Studio出品的XIAO nRF52840开发板,它最大的特点就是“小”和“省电”。尺寸只有21mm x 17.5mm,比一枚硬币大不了多少,但内部搭载了Nordic的nRF52840芯片,这是一颗ARM Cortex-M4内核的处理器,性能足够处理实时信号,并且原生支持蓝牙5.0。对于需要长时间佩戴、依赖电池供电的设备来说,它的超低功耗特性(深度睡眠时电流仅5uA)简直是福音。另一个关键部件是Bitalino生物医学传感器套件中的ECG(心电图)模块。Bitalino本身是一个开源的生物信号采集平台,它的ECG模块已经为我们做好了信号放大和初步滤波,让我们可以更专注于应用逻辑,而不是从头开始设计模拟前端电路。

整个系统的思路很直观:通过贴在胸部的三个电极采集微弱的体表心电信号,经过Bitalino ECG模块的调理后,将模拟信号送入XIAO nRF52840的ADC(模数转换器)引脚。微控制器内部的程序会实时分析这个数字信号波形,识别出代表心跳的R波峰值,从而计算出瞬时心率和心率变异性等信息。最后,处理结果一方面可以通过蓝牙发送到手机App进行记录和查看,另一方面也能直接驱动一组LED灯,用灯光闪烁的节奏来直观反映心跳,实现一个脱离手机的、纯粹的“光效”心率指示器。下面,我就把从电路焊接、编程调试到外壳装配的每一步拆开,详细说说其中的门道和踩过的坑。

2. 核心硬件选型与设计思路解析

2.1 为什么选择XIAO nRF52840与Bitalino组合?

在做健康监测类项目时,硬件选型直接决定了项目的可行性、功耗和最终体积。我选择XIAO nRF52840和Bitalino ECG模块的组合,是基于几个非常实际的考量。

首先看主控。市面上常见的Arduino Uno或NodeMCU虽然入门简单,但体积大、功耗高,根本不适合做可穿戴设备。而一些更小的板子,比如ATtiny系列,性能又可能不足以处理实时的信号分析。XIAO nRF52840在这中间找到了一个完美的平衡点。它的nRF52840芯片内置了浮点运算单元(FPU),这对于处理ECG信号这类需要滤波和数学运算的任务非常有帮助,比用软件模拟浮点运算要快得多、也省电得多。蓝牙5.0的支持意味着我们可以轻松地将数据流式传输到手机,进行更复杂的显示或云端记录,而板载的电池充电管理电路,让我们可以直接连接一颗3.7V的锂聚合物电池,省去了外接充电模块的麻烦和空间。

其次是传感器。直接使用裸电极和自制放大电路来采集ECG信号,是一个门槛极高且极易引入噪声的“深坑”。心电信号非常微弱(毫伏级别),且极易受到工频干扰(50/60Hz)和肌电干扰。Bitalino的ECG模块(如BITalino (r)evolution ECG)实际上是一个高度集成的前端,它内部包含了仪表放大器、带通滤波器和右腿驱动电路。仪表放大器能极大地抑制共模噪声(比如来自电源的干扰),带通滤波器(通常设为0.5Hz到40Hz左右)则能有效滤除基线漂移和高频肌电噪声,只留下我们关心的QRS波群(包含R波)频段。这相当于把最棘手、最专业的模拟电路问题打包解决了,我们拿到手的已经是一个比较“干净”的、幅值在0-3.3V范围内的模拟信号,可以直接送给微控制器的ADC去读取。

注意:Bitalino模块通常输出的是单端信号,其参考电压(REF)引脚需要妥善处理。常见的接法是将其通过一个电阻分压网络(例如两个10kΩ电阻)连接到VCC和GND之间,取中点电压(1.65V)作为偏置,这样信号就能在ADC的量程范围内正负摆动。如果REF直接接地,负向的信号部分就会被削波,导致波形失真。

2.2 系统架构与信号流设计

整个系统的架构可以清晰地分为传感层、处理层和指示层。传感层就是贴在身上的三个电极(RA右臂、LA左臂、RL右腿)和Bitalino ECG模块。处理层是XIAO nRF52840,它负责ADC采样、数字信号处理和心率计算。指示层则包括了一组LED灯和可选的蓝牙无线传输。

信号流的细节值得深入说说。ECG模块的输出线连接到XIAO的某个ADC引脚(例如A0/D1)。XIAO nRF52840的ADC分辨率是12位,参考电压为3.3V,这意味着它可以将0-3.3V的电压量化为0到4095的数值。对于心电信号,我们更关心的是波形的相对变化和节律,而不是绝对电压值,所以12位分辨率提供的动态范围完全足够。

在程序里,我们需要设置一个合适的采样率。根据奈奎斯特采样定理,要无失真地还原信号,采样率至少需要是信号最高频率的两倍。心电信号的有效成分主要在0.5-40Hz,所以理论上采样率大于80Hz即可。但在实践中,为了更精确地定位R波峰值,我们通常需要更高的采样率,一般设置在200Hz到500Hz之间。XIAO nRF52840的M4内核完全能胜任这个速率的实时采样和计算。

处理的核心算法是QRS波检测。一个简单但有效的方法是设置一个动态阈值。程序会持续监测ADC读数的变化,当发现信号值在短时间内快速上升并超过阈值时,就认为检测到了一个R波峰值。记录下两个峰值之间的时间间隔(RR间期),用60除以这个间隔(单位:秒),就得到了瞬时心率(单位:次/分钟)。为了防止噪声引起的误触发,通常还会加入一个“不应期”设置,即在检测到一个R波后的200-300毫秒内,暂停检测,因为生理上不可能在这么短的时间内出现两次心跳。

3. 电路设计与PCB制作实操要点

3.1 从原理图到万用板布局

有了核心模块,我们需要搭建一个最小系统电路,将XIAO、ECG模块、LED指示灯和电源连接起来。虽然最终用了万用板(洞洞板),但先在纸上或EDA软件里画个简单的原理图是非常必要的,它能帮你理清连接关系,避免焊接时抓瞎。

我的连接方案如下:

  1. 电源部分:一颗3.7V/500mAh的锂聚合物电池正负极分别接到XIAO nRF52840的“BAT+”和“GND”引脚。注意,XIAO的USB口和BAT+引脚是连通的,并且板上有充电管理芯片,所以直接接电池是最简洁的方案。整个系统的3.3V电源都从XIAO的“3V3”引脚取电。
  2. ECG模块连接
    • VCC-> XIAO的3V3
    • GND-> XIAO的GND
    • OUT(信号输出) -> XIAO的A0/D1(ADC输入引脚)
    • REF(参考电压) -> 通过一个由两个10kΩ电阻串联的分压网络的中点连接。即:3V3-> 10kΩ电阻 ->REF引脚 -> 10kΩ电阻 ->GND。这样REF点的电压就是1.65V。
  3. LED阵列连接:我用了5个白色LED来模拟心跳闪烁。每个LED的阳极通过一个限流电阻(我后来去掉了,但建议新手保留,例如220Ω)分别连接到XIAO的数字IO口(如D5, D6, D7, D8, D9)。所有LED的阴极连接在一起,接至GND。这样可以通过程序依次点亮LED,形成“流动”的视觉效果。

在万用板上布局时,我的原则是“功能分区,走线最短”。我把XIAO的母座放在板子中央,电源接口和电池线放在一侧,ECG模块的接口放在靠近ADC引脚的另一侧,LED阵列则布置在板子边缘方便光线透出。对于数字和模拟部分,虽然没有做严格的隔离,但尽量让ECG的信号线远离LED的驱动线,以减少开关噪声对微弱模拟信号的干扰。

3.2 焊接、组装与调试中的“坑”

焊接过程本身是基本功,但有几个细节决定了成败。首先,一定要先焊接电阻、母座这类高度较低的元件,最后再焊接ECG模块这种有排针或体积较大的元件。我一开始先焊了ECG模块,结果在焊接旁边的小电阻时,烙铁头非常容易碰到模块的塑料外壳,甚至可能导致引脚短路。

其次,给XIAO使用母座(排母)而不是直接焊死在板子上,是一个明智的选择。这不仅仅是为了复用,更重要的是便于调试。在开发阶段,你可能会频繁地拔插USB线来下载程序和监控串口输出,直接焊接会使得这些操作非常困难,也增加了损坏板子的风险。

实操心得:焊接多引脚排母时,可以先将其插在XIAO开发板上,然后将这个“组合体”一起放到万用板上焊接。这样能确保排母与板子绝对垂直,并且引脚位置分毫不差。焊好一排针脚后,再轻轻取下XIAO即可。

焊接完成后,万用表是你最好的朋友。在上电前,必须做以下检查:

  1. 电源短路测试:用蜂鸣档测量电池正负极接入点之间的电阻,确保没有直接短路。
  2. 电压测试:接上电池,测量XIAO的3V3引脚对地电压,确认是稳定的3.3V左右。
  3. 信号通路测试:测量ECG模块REF引脚的电压,确认是否为1.65V(一半的3.3V)。

我遇到的一个真实问题是LED不亮。检查后发现,我在布局时为了整齐,将LED的阴极都接到了一条公共的铜箔走线上,但这根走线在某个过孔处因为焊接不良而断裂了,导致所有LED阴极悬空。用万用表蜂鸣档沿着走线一点点测,才找到这个断点。所以,焊接完一定要仔细检查每一根你认为连接了的走线,特别是那些长的、拐弯多的。

另一个教训是关于机械强度的。万用板本身比较脆,在固定到外壳或进行组装时,如果受力不均或者被挤压,很容易从焊盘处断裂。我的第一版板子就是在用台钳固定准备打孔时,因为用力稍大,直接裂成了两半。所以,对于需要承受一定机械应力的项目,要么选择更厚实的玻纤板,要么在布局时避免在受力点附近放置重要线路,或者考虑用3D打印一个支撑结构来分担压力。

4. 固件编程:信号采集与心率算法实现

4.1 开发环境搭建与基础配置

为XIAO nRF52840编程,最方便的方法是使用Arduino IDE并添加Seeed Studio的板卡支持。首先,在Arduino IDE的“文件->首选项->附加开发板管理器网址”中,添加以下网址:https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json。然后,在“工具->开发板->开发板管理器”中,搜索“Seeed nRF52”,安装“Seeed nRF52 Boards”这个包。安装完成后,就可以在开发板列表中选择“Seeed XIAO nRF52840 (Sense)”了。

选择正确的端口后,还需要配置两个重要的选项:Bootloader选择Seeed UF2Port选择对应的串口。UF2是一种很方便的拖放式烧录协议,但在进行深度调试时,我更喜欢使用J-Link (via CMSIS-DAP)作为调试器,这可以通过选择BootloaderCMSIS-DAP来实现,它能提供单步调试等更强大的功能。

程序的第一步是包含必要的库和定义引脚。除了基本的Arduino.h,我们还需要analogRead函数来读取ADC,以及可能用到的数学库。

// 引脚定义 const int ecgPin = A0; // ECG信号输入引脚,对应D1 const int ledPins[] = {5, 6, 7, 8, 9}; // LED连接的引脚数组 const int numLeds = 5; // 心率计算相关变量 int sensorValue = 0; unsigned long lastHeartbeatTime = 0; unsigned long heartbeatInterval = 0; int bpm = 0; bool pulseDetected = false; // 信号处理变量 const int sampleRate = 250; // 采样率,250 Hz const int sampleInterval = 1000000 / sampleRate; // 以微秒计的采样间隔 unsigned long lastSampleTime = 0; // 阈值与滤波 int threshold = 512; // 初始阈值,ADC量程中点附近 int signalMax = 0; int signalMin = 1023; const int noiseFloor = 10; // 噪声阈值

4.2 核心心率检测算法剖析

心率检测的核心在于从连续的、带有噪声的ECG信号中,可靠地识别出R波峰值。我采用了一个简化但鲁棒性不错的“阈值自适应”算法。这个算法不依赖于复杂的数字滤波器(如带通或陷波),而是通过跟踪信号的局部最大值和最小值来动态调整触发阈值。

在主循环loop()中,我们以固定的时间间隔(由sampleRate决定)读取ADC值。为了消除工频干扰,一个简单的方法是计算连续几个采样点的移动平均值。这里我用了4个点的平均:

void loop() { unsigned long currentMicros = micros(); // 固定间隔采样 if (currentMicros - lastSampleTime >= sampleInterval) { lastSampleTime = currentMicros; // 读取ADC并做简单平滑 int rawValue = analogRead(ecgPin); sensorValue = (3 * sensorValue + rawValue) >> 2; // 一阶低通滤波,近似于移动平均 // 动态更新信号的最大最小值 if (sensorValue > signalMax) { signalMax = sensorValue; } if (sensorValue < signalMin) { signalMin = sensorValue; } // 每200个采样点(约0.8秒)重置一次最大最小值,实现滑动窗口 static int sampleCount = 0; sampleCount++; if (sampleCount >= 200) { sampleCount = 0; // 根据过去窗口内的峰峰值,动态计算阈值。阈值设为信号幅值(峰峰值)的60%加上最小值。 int amplitude = signalMax - signalMin; if (amplitude > noiseFloor) { // 避免在无信号或低信号时误触发 threshold = signalMin + (amplitude * 6 / 10); // 阈值为最小值 + 幅值的60% } signalMax = 0; signalMin = 1023; } // 心率检测逻辑 if (sensorValue > threshold && !pulseDetected) { pulseDetected = true; unsigned long currentTime = millis(); if (lastHeartbeatTime > 0) { heartbeatInterval = currentTime - lastHeartbeatTime; bpm = 60000 / heartbeatInterval; // 计算BPM // 限制心率在合理范围内,例如30-200 BPM if (bpm < 30) bpm = 30; if (bpm > 200) bpm = 200; } lastHeartbeatTime = currentTime; // 触发LED效果 animateLeds(); } // 在检测到峰值后,设置一个“不应期”,防止同一个R波被多次检测 if (pulseDetected && sensorValue < threshold) { pulseDetected = false; } } }

animateLeds()函数控制LED的动画效果。最简单的实现是让所有LED随心跳同步闪烁。但为了更直观,我实现了一个“流水灯”效果,让灯光像波浪一样从一端流向另一端,其速度可以与心率挂钩(心率快则流水快)。

void animateLeds() { // 先全部熄灭 for (int i = 0; i < numLeds; i++) { digitalWrite(ledPins[i], LOW); } // 实现流水效果 for (int i = 0; i < numLeds; i++) { digitalWrite(ledPins[i], HIGH); delay(50); // 每个LED点亮间隔,可根据bpm调整 digitalWrite(ledPins[i], LOW); } }

这个算法在信号质量较好时工作得很稳定。它的优势是计算量小,非常适合在资源有限的微控制器上运行。但它对基线漂移和大的运动伪影比较敏感。在实际佩戴中,如果电极接触不良或人体移动,信号可能会剧烈变化,导致阈值计算失常。

4.3 蓝牙数据传输与手机端显示(可选进阶)

如果想让数据在手机上可视化或存储,蓝牙功能就派上用场了。XIAO nRF52840支持蓝牙低功耗(BLE),我们可以将心率(BPM)和原始的ECG波形数据作为一个特征值(Characteristic)广播出去。

这里需要使用ArduinoBLE库。首先在setup()中初始化BLE,创建一个服务(Service)和一个特征值。特征值需要设置可读(READ)和可通知(NOTIFY)属性,这样手机端在订阅后,每当心率更新,设备就会自动推送新值。

#include <ArduinoBLE.h> BLEService heartRateService("180D"); // 标准心率服务UUID BLEUnsignedCharCharacteristic bpmCharacteristic("2A37", BLERead | BLENotify); // 标准心率测量特征 void setup() { // ... 其他初始化代码 if (!BLE.begin()) { // 蓝牙初始化失败处理 } BLE.setLocalName("XIAO_HR_Monitor"); BLE.setAdvertisedService(heartRateService); heartRateService.addCharacteristic(bpmCharacteristic); BLE.addService(heartRateService); bpmCharacteristic.writeValue(0); // 初始值 BLE.advertise(); } void loop() { // ... 原有的采样和计算代码 // 当计算出新的bpm后,更新BLE特征值 static int lastReportedBpm = 0; if (abs(bpm - lastReportedBpm) > 1) { // 避免频繁发送微小变化 bpmCharacteristic.writeValue(bpm); lastReportedBpm = bpm; } BLE.poll(); // 处理BLE事件 }

在手机端,可以使用像LightBlue这样的通用BLE调试App来查看数据,或者自己用MIT App InventorReact Native等工具开发一个简单的应用来接收并绘制心率曲线。通过BLE,这个可穿戴设备就从单纯的视觉指示器升级为了一个真正的无线健康数据采集终端。

5. 机械结构设计与3D打印装配

5.1 外壳设计:功能性与佩戴体验的平衡

对于可穿戴设备,外壳设计至关重要,它需要保护内部电路,提供舒适的佩戴感,并方便用户操作。我的设计分为三个部分:主壳体、LED灯罩和胸部电极固定带。

使用Fusion 360进行设计。主壳体是一个扁平的盒子,内部有支撑柱和卡槽,用于固定万用板、电池和XIAO开发板。设计时要特别注意以下几点:

  1. 尺寸精确:用卡尺精确测量万用板和电池的外形尺寸,并在建模时留出至少0.5mm的装配间隙。太紧会装不进去,太松则设备会在壳体内晃动。
  2. 开孔设计
    • USB接口:为XIAO的Type-C接口开一个足够大的方孔,方便充电和调试。
    • LED窗口:在主壳体正面开一排与LED位置对应的小孔,或者设计一个独立的、半透明的灯罩部件,通过散射让灯光更柔和均匀。我选择了后者,用白色PLA打印灯罩,透光效果很好。
    • 电极线出口:在壳体侧面设计一个小孔,让ECG模块的电极线能够穿出。
    • 散热:虽然功耗很低,但仍在底部设计一些细小的通风孔。
  3. 固定方式:我采用了最简单的上下盖卡扣配合。在设计卡扣时,悬臂梁的厚度和钩子的角度需要仔细调整,打印后可能需要用小刀稍微修整才能达到合适的松紧度。也可以设计螺丝柱,用M2的小螺丝固定,这样更可靠但组装稍麻烦。

胸部电极固定带的设计目标是舒适和稳定。我设计了一个扁平的、弧形的塑料片,中间有一个孔用于穿过三根电极线。塑料片的两端留有槽口,用于固定弹力织带。织带的长度可调,以适应不同的胸围。

5.2 打印与后处理实战经验

打印材料选择PLA,因为它容易打印、无异味且成本低。打印参数设置上,层高我选用0.2mm以获得较好的表面质量,填充率设为20%以兼顾强度和重量。对于主壳体这类需要承重和卡扣功能的部件,打印方向很重要。务必让卡扣的钩子部分在打印时是“站立”的,而不是平躺的。平躺打印时,卡扣的钩子部分会是悬空打印,强度极差,很容易断裂。而站立打印,每一层都是完整的轮廓,强度高得多。

重要提示:在切片软件(如Creality Slicer或Cura)中,务必为模型添加“支撑(Support)”。外壳内部的支撑柱、卡扣的悬空部分都需要支撑材料。我最初尝试不加支撑打印卡扣,结果悬空部分拉丝严重,形状一塌糊涂,根本无法使用。支撑材料虽然会增加打印时间和后处理工作量,但对于保证复杂结构的成型质量是必须的。

打印完成后,需要小心地去除支撑材料。使用扁口钳或镊子一点点剥离,对于内部难以触及的支撑,可以用小刀或专用的支撑去除工具。去除支撑后,用细砂纸(例如400目、800目)轻轻打磨结合面的毛刺和粗糙处,特别是上下盖的接触边缘,确保能平整闭合。

组装时,我使用了401或496瞬干胶(俗称“快干胶”)来粘合PLA部件。在粘合前,先用酒精棉片清洁粘合面,去除油脂和灰尘。涂抹胶水要少量、均匀,对准位置后按压30秒左右即可初步固定。切记保持通风,并避免胶水接触皮肤或眼睛

对于电极线出口和电池线等位置,为了防止长期弯折导致线材断裂,需要进行“应力消除”。理想情况下应该使用热缩管,但我手头没有合适直径的,就用了热熔胶在出口处打了一个“应变释放结”,将线材固定住,避免内部焊点受力。虽然不如热缩管美观,但效果一样可靠。

6. 系统集成测试与问题深度排查

6.1 上电测试与功能验证流程

所有硬件焊接完毕、外壳组装完成后,不要急于佩戴,必须进行系统的上电测试。

第一步:静态功耗测试。不接ECG电极,将设备开机,用万用表的电流档串联在电池回路中,测量整机工作电流。XIAO nRF52840在运行上述心率检测程序、LED熄灭时,电流大约在5-10mA左右。当LED被点亮时,电流会有明显上升(每个LED约5-20mA,取决于限流电阻和亮度)。这个测试可以帮你估算电池续航。一颗500mAh的电池,如果平均电流10mA,理论续航约50小时。进入深度睡眠模式可以进一步省电,但本项目需要实时监测,所以常开是合理的。

第二步:信号模拟测试。在没有真人测试前,可以用一个简单的信号源来验证整个信号链是否工作。找一个函数发生器(或者用另一个Arduino模拟DAC输出),产生一个频率在1-2Hz(模拟60-120 BPM)、幅值在1-2V峰峰值、偏置在1.65V的正弦波或方波,连接到ECG模块的信号输入点(注意共地)。观察LED是否能够以相应的频率闪烁,同时通过Arduino IDE的串口绘图器(Serial Plotter)查看ADC读取的波形是否正常。这个步骤能快速排除硬件连接和基础软件逻辑的错误。

第三步:真人静态测试。清洁皮肤(用酒精棉片擦拭可以减少接触电阻),贴好电极(右锁骨下、左锁骨下、左下胸部),连接设备。保持静止,观察LED闪烁是否规律,同时通过串口监视器输出实时的心率数值和波形图。一个正常的ECG波形应该能清晰看到P波、QRS波群和T波,虽然我们的算法只关注R波。串口绘图器里应该看到规律的尖峰。

6.2 典型问题、根源分析与解决方案

在实际测试中,你几乎一定会遇到下面这些问题。这里我把它们、可能的原因和解决办法整理成表,方便快速排查:

问题现象可能原因分析排查步骤与解决方案
LED完全不亮1. 电源未接通或电池没电。
2. LED公共阴极/阳极连接断路。
3. 程序未正确配置IO口模式(应设为OUTPUT)。
4. 限流电阻过大或LED极性接反。
1. 用万用表测电池电压、XIAO的3V3引脚电压。
2. 用万用表蜂鸣档检查LED电路通路。
3. 检查setup()中是否有pinMode(ledPin, OUTPUT)语句。
4. 短路限流电阻测试,或检查LED长脚(阳极)是否接对了正极。
LED常亮不闪烁1. 心率检测算法失效,pulseDetected标志位一直为true。
2. 阈值(threshold)设置过低,导致信号持续高于阈值。
3. ECG信号输入持续为高电平(如REF引脚接错)。
1. 通过串口打印sensorValuethreshold,观察数值。
2. 检查REF引脚电压是否为1.65V左右。
3. 检查算法中“不应期”逻辑和阈值重置逻辑是否正确。
心率读数极快且不稳定(如>200 BPM)1.最常见原因:电极接触不良或脱落,导致信号充满高频噪声,算法将噪声峰值误判为R波。
2. 肌电干扰(肌肉紧张、身体移动)。
3. 工频干扰(50Hz)严重。
1.重新粘贴电极,确保与皮肤接触良好。可在电极片上涂抹少量导电膏。
2. 保持测试者静止、放松。
3. 在软件中增加一个简单的50Hz陷波滤波器,或检查设备是否远离强交流电源。
心率读数极慢或为零1. 信号太弱,R波峰值未超过阈值。
2. ECG模块增益不足或损坏。
3. 电极位置贴错(参考标准I导联位置)。
1. 通过串口绘图器观察原始波形,看QRS波群幅值是否明显(通常应有数百个ADC单位的变化)。
2. 尝试交换RA和LA电极位置。
3. 确保ECG模块供电正常。
蓝牙无法连接或数据不更新1. 手机蓝牙未打开或权限未授予。
2. XIAO的BLE未成功初始化或开始广播。
3. 手机App与服务/特征UUID不匹配。
4. 程序卡死,未执行BLE.poll()
1. 用nRF Connect等BLE扫描工具查看是否能发现“XIAO_HR_Monitor”设备。
2. 检查setup()中BLE初始化部分的返回值。
3. 确认手机App订阅的特征UUID与代码中一致。
4. 确保loop()中定期调用BLE.poll()
设备发热严重1. 电源短路。
2. LED驱动电流过大(未加限流电阻或电阻值太小)。
3. 微控制器持续高频运行。
1. 立即断电,用万用表检查短路点。
2. 测量LED点亮时流过的电流,计算公式:I = (3.3V - LED压降) / 电阻。白色LED压降约3.0V,若用220Ω电阻,电流约(3.3-3.0)/220≈1.4mA,是安全的。若无电阻,电流可能很大。
3. 检查程序是否有死循环。

关于我更换LED的教训:最初我使用了红色LED搭配220Ω电阻,但在环境光稍亮时,灯光效果非常不明显。后来我换成了白色LED,由于其本身更亮,我去掉了限流电阻以增加亮度。这是一个有风险的操作,因为IO口的最大拉电流能力是有限的(通常每个引脚约20mA,所有引脚总和有限制)。直接驱动白色LED可能导致电流超标,长期可能损坏IO口。更安全的做法是保留一个较小阻值的电阻(如10Ω-100Ω),或者使用晶体管来驱动LED。我的做法是在评估了闪烁占空比很低(每次点亮时间很短)后的一种权衡,不推荐初学者模仿。

6.3 优化与改进方向

这个项目作为一个原型已经可以工作,但还有很大的优化空间:

  1. 算法优化:引入更专业的数字滤波器(如巴特沃斯带通滤波器)来进一步抑制噪声。可以使用开源的心率检测算法库,如Pan-Tompkins算法,它能更稳健地在噪声中检测QRS波。
  2. 功耗优化:当前LED是全亮驱动,功耗大户。可以改用PWM调光,降低亮度。在未检测到心跳一段时间后,让系统进入轻度睡眠,仅ADC定时唤醒采样,可以大幅延长续航。
  3. 佩戴优化:目前的胸部固定带可能不适合长时间运动佩戴。可以考虑改用更柔软、透气的医用级硅胶或织物材料,设计成类似心率胸带的样式。
  4. 数据可视化:开发一个简单的手机App,不仅能显示实时心率,还能绘制心电图波形,计算心率变异性(HRV),并具备历史数据记录和导出功能。
  5. 无线充电:为外壳集成一个Qi无线充电接收线圈,实现无接触充电,提升产品的完整度和用户体验。

这个基于XIAO nRF52840和Bitalino的心率监测系统项目,从芯片选型到外壳打印,完整地走了一遍嵌入式可穿戴产品的开发流程。它最宝贵的价值不在于做出了一个多么精密的医疗设备,而在于亲身实践了如何将生物电信号这种微弱的模拟量,通过硬件调理、数字采样、软件算法,最终转化为直观可读的信息。过程中遇到的每一个问题,从焊接断裂到信号干扰,从算法调试到结构设计,都是极其宝贵的经验。当你看到LED灯随着自己的心跳规律闪烁时,那种连接了硬件与生命的成就感,正是嵌入式开发与生物医学工程交叉魅力的最佳体现。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 21:59:38

UnityExplorer终极指南:快速掌握游戏调试与修改的免费神器

UnityExplorer终极指南&#xff1a;快速掌握游戏调试与修改的免费神器 【免费下载链接】UnityExplorer An in-game UI for exploring, debugging and modifying IL2CPP and Mono Unity games. 项目地址: https://gitcode.com/gh_mirrors/un/UnityExplorer 还在为Unity游…

作者头像 李华
网站建设 2026/6/1 21:59:02

终极指南:如何在5分钟内快速上手微软Lens文本转图像模型

终极指南&#xff1a;如何在5分钟内快速上手微软Lens文本转图像模型 【免费下载链接】Lens 项目地址: https://ai.gitcode.com/hf_mirrors/microsoft/Lens 微软Lens是一款3.8B参数的文本转图像基础模型&#xff0c;专为高效训练和快速高分辨率生成而设计。它结合了密集…

作者头像 李华
网站建设 2026/6/1 21:55:12

终极指南:如何选择最适合你的DrakeTyporaTheme十二款Typora主题

终极指南&#xff1a;如何选择最适合你的DrakeTyporaTheme十二款Typora主题 【免费下载链接】DrakeTyporaTheme 十二种主题风格 - Material Google JetBrains Vue Juejin Purple Ayu Dark 项目地址: https://gitcode.com/gh_mirrors/dr/DrakeTyporaTheme 你是否厌倦了Ty…

作者头像 李华
网站建设 2026/6/1 21:55:09

Sora 2教程视频制作全流程拆解(含帧率抖动修复/物理引擎对齐/时序一致性校准三重硬核方案)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Sora 2教程视频制作的底层逻辑与范式演进 Sora 2并非传统意义上的视频生成模型&#xff0c;而是一套融合时空建模、语义对齐与多阶段编排的生成式创作范式。其底层逻辑建立在“分层解耦—联合优化—反馈重校准…

作者头像 李华