第一章:数字信号处理链——心率监测的“心脏”
各位同学,大家好。我是你们的老朋友,一个在芯片设计领域摸爬滚打十几年的工程师。今天咱们正式开始《智能穿戴芯片心率监测算法硬件实现》这门课。说实话,每次讲到第一章,我都特别兴奋。因为这一章是整个课程的基石,也是你未来设计出稳定、低功耗心率监测芯片的关键。
心率监测,说白了就是从一团乱麻似的光电容积脉搏波(PPG)信号里,把心跳那一下一下的规律给揪出来。但这信号太脆弱了,你动一下、环境光闪一下、甚至皮肤出汗,它都会变样。所以,我们需要一套完整的数字信号处理链来“伺候”它。
这套链子,我习惯把它分成四步:去基线漂移、低通滤波、自适应滤波、峰值检测。每一步都有它的脾气,咱们一个一个来聊。
核心逻辑图:心率监测数字信号处理链
1.1 去基线漂移:高通滤波,0.5 Hz
先说说基线漂移。你想想看,人戴着智能手表,手不可能一动不动。呼吸、走路、甚至脉搏本身的低频波动,都会让PPG信号的基线上下乱飘。这就像你站在一艘摇晃的船上测海平面,不把船晃的影响去掉,你永远测不准。
怎么去掉?用高通滤波器。把0.5 Hz以下的低频成分统统滤掉。为什么是0.5 Hz?因为正常人的心率最低大概在30次/分钟,也就是0.5 Hz。低于这个频率的,基本就是干扰了。
我在项目中遇到过一个问题:滤波器阶数选得太低,基线漂移滤不干净;选得太高,又会导致信号延迟太大,影响实时性。嗯,这里要注意,硬件实现时,我们通常用IIR滤波器,比如一阶巴特沃斯高通,资源省,效果也还行。
个人经验: 我建议在RTL实现时,把滤波器的系数用定点数表示,位宽至少16位。我曾经偷懒用了12位,结果低频抑制比不够,基线还是飘,后来改版才搞定。
1.2 低通滤波:抗混叠,5 Hz
去完基线漂移,信号干净了一些,但还有高频噪声。比如环境光的50 Hz工频干扰、肌肉震颤的高频成分。这些噪声如果不处理,后面采样时会发生混叠——说白了就是高频信号伪装成低频信号,让你误以为是心跳。
所以我们需要一个低通滤波器,把5 Hz以上的成分干掉。为什么是5 Hz?因为正常人的心率上限大概在220次/分钟,也就是3.67 Hz。留点余量,5 Hz足够了。
这里有个坑:低通滤波器的截止频率不能太陡,否则会产生振铃效应。你想想看,一个方波信号经过陡峭的低通滤波器,边缘会 overshoot,这在峰值检测时会造成误判。我个人习惯用 FIR 滤波器,线性相位,不会把波形搞变形。
避坑指南: 我曾经在低通滤波器的实现中,为了省资源用了级联的IIR滤波器,结果相位非线性导致波形畸变,峰值检测的准确率直接掉了15%。后来老老实实换回FIR,虽然寄存器多了点,但心里踏实。
1.3 自适应滤波:LMS/NLMS
前面两步是固定参数的滤波,但运动干扰是时变的。你跑步时和走路时,干扰的幅度和频率都不一样。这时候就需要自适应滤波了。
自适应滤波的核心思想:用一个参考信号(比如加速度计的信号)来模拟运动干扰,然后从PPG信号中减去它。最常用的算法是LMS(最小均方)和NLMS(归一化最小均方)。
LMS的原理很简单:
y(n) = w(n) * x(n) // 滤波器输出
e(n) = d(n) - y(n) // 误差信号
w(n+1) = w(n) + μ * e(n) * x(n) // 权值更新
其中μ是步长因子,控制收敛速度。μ太大,收敛快但容易发散;μ太小,收敛慢但稳定。NLMS就是在LMS的基础上,把步长归一化到输入信号的功率上,这样收敛速度更稳定。
说实话,NLMS在硬件实现上比LMS多不了几个门,但效果好了不止一点。我建议直接上NLMS。
硬件实现要点:
- 滤波器阶数:通常16-32阶就够,阶数太高延迟大,功耗也高
- 数据位宽:输入信号16位,权值用16位,累加器用32位防止溢出
- 步长因子μ:用移位操作实现,比如μ=1/256,避免乘法器
1.4 峰值检测算法:阈值法/斜率法
信号处理完了,终于到了最后一步——找到心跳的峰值。这一步决定了心率值的准确性。
常用的方法有两种:
| 方法 | 原理 | 优缺点 |
|---|---|---|
| 阈值法 | 设定一个动态阈值,信号超过阈值就认为是峰值 | 实现简单,但对运动干扰敏感,阈值需要自适应调整 |
| 斜率法 | 检测信号上升沿和下降沿的斜率变化,找到拐点 | 抗干扰能力强,但计算量稍大,需要缓存几个点 |
我个人更倾向于斜率法。为什么?因为阈值法在运动剧烈时,阈值调整跟不上干扰的变化,容易误检。而斜率法关注的是波形的形状变化,只要心跳的波形特征还在,就能准确找到峰值。
斜率法的硬件实现思路:
// 计算当前点的斜率
slope = signal[n] - signal[n-1];
// 检测上升沿过零点
if (slope_prev > 0 && slope <= 0) {
// 找到峰值点
peak = signal[n-1];
// 计算心率间隔
interval = n - last_peak_index;
heart_rate = 60 * fs / interval;
}
这里要注意:斜率法需要一个“不应期”机制。找到一次峰值后,在接下来200毫秒内不再检测新的峰值,防止把T波误检为R波。
避坑指南: 我曾经在峰值检测模块里忘了加不应期,结果心率值跳得跟过山车一样。后来加了一个简单的计数器,在检测到峰值后锁定200ms,问题就解决了。这种小细节,往往决定了产品的成败。
小结
好了,这一章的内容就到这里。我们讲了心率监测的四个核心步骤:去基线漂移、低通滤波、自适应滤波、峰值检测。每一步都有它的设计考量和硬件实现技巧。
记住,做芯片设计不是写软件,资源、功耗、实时性都是硬约束。你设计的每一个滤波器、每一个状态机,都要在面积和性能之间找到平衡点。这也是为什么我反复强调“硬件思维”——用最少的门,做最靠谱的事。
下一章,我们会深入每个模块的RTL实现细节,包括状态机设计、流水线优化、低功耗技巧等。到时候咱们再细聊。