4. 模拟前端(AFE)配置与增益调试:LED驱动电流设置,跨阻放大器增益调节,环境光抑制策略

好,咱们进入血氧仪最核心的硬件环节——模拟前端AFE的调试。说实话,这部分搞不定,后面算法再牛也白搭。我见过太多团队,算法工程师天天抱怨信号太差,结果一查,AFE配置压根没调对。

AFE调试说白了就三件事:把光发出去(LED驱动)、把光收回来转成电压(跨阻放大器)、把干扰滤掉(环境光抑制)。咱们一个一个来拆。

4.1 LED驱动电流设置——不是越亮越好

很多人上来就把LED电流开到最大,觉得信号强就好。嗯,这是个坑。我早期做的一款指夹式血氧仪,红光LED开到20mA,结果手指一放上去,ADC直接饱和,波形平得像一条直线。

LED驱动电流的选择,其实是个平衡艺术:

  • 电流太小:光信号弱,穿透手指后光电二极管几乎没反应,信噪比极差
  • 电流太大:一是发热,LED温度漂移会影响波长;二是容易让接收端饱和
  • 还有个隐藏问题:大电流会缩短电池寿命,尤其是可穿戴设备

我个人习惯的调试方法是:

  1. 先把电流设到典型值(红光一般5-10mA,红外8-15mA)
  2. 用示波器看跨阻放大器输出端的波形
  3. 调整电流,让PPG波形的峰峰值在ADC满量程的30%-70%之间
  4. 如果波形太小,优先调增益,而不是无脑加电流

关键经验:红光和红外光的驱动电流通常不一样。因为不同波长在组织中的吸收特性不同,红外穿透性更好,所以红外LED的电流可以比红光小一些。我一般先让两者在接收端的信号幅度接近,这样后续算法处理起来更公平。

实际项目中,LED驱动常用的是恒流源方式。以AFE4404为例,它的LED驱动寄存器是这样配置的:

// AFE4404 LED驱动电流配置示例
// LED电流 = (LED_CODE / 256) * 50mA
// 红光LED设到8mA
AFE4404_REG_LED1_DRV = (uint8_t)(8.0 / 50.0 * 256);  // 约41

// 红外LED设到10mA
AFE4404_REG_LED2_DRV = (uint8_t)(10.0 / 50.0 * 256); // 约51

小技巧:调试时别只盯着静态值。把手指拿开再放回去,观察波形恢复速度。如果恢复很慢,说明LED电流可能偏大,组织被加热了,血流量在变化。

4.2 跨阻放大器增益调节——信号放大的艺术

跨阻放大器(TIA)是AFE的咽喉。光电二极管产生的电流只有微安级,必须通过TIA转成电压才能被ADC采集。增益怎么选?我见过有人直接套用参考设计,结果换了手指厚度就不行了。

TIA的增益由反馈电阻Rf决定:Vout = Ipd × Rf。Rf越大,增益越高,但噪声也越大。这是个典型的信噪比取舍问题。

我在项目中总结了一套增益调节的步骤:

  • 第一步:估算信号范围。正常手指透射光产生的光电流大约在10nA到1μA之间,具体取决于皮肤厚度和血氧饱和度
  • 第二步:确定目标电压。ADC的满量程是参考电压Vref,一般留20%裕量,目标峰值电压设为0.8×Vref
  • 第三步:计算Rf。Rf = Vtarget / Ipd_max。比如Vref=3V,目标2.4V,最大光电流1μA,那Rf=2.4MΩ

注意:Rf不是越大越好。反馈电阻大了,带宽会下降。我踩过这个坑——为了追求高增益用了10MΩ电阻,结果PPG波形的高频细节全没了,脉率计算偏差很大。一般血氧仪的TIA带宽至少要能通过10Hz的信号,算下来Rf最好不要超过5MΩ。

实际芯片里,增益通常是可编程的。比如MAX30102的TIA增益有7个档位:

// MAX30102 TIA增益配置
// 0x0E: 7.81pF, 增益50kΩ
// 0x0F: 7.81pF, 增益100kΩ  
// 0x10: 7.81pF, 增益200kΩ
// 0x11: 7.81pF, 增益400kΩ
// 0x12: 7.81pF, 增益800kΩ
// 0x13: 7.81pF, 增益1600kΩ
// 0x14: 7.81pF, 增益3200kΩ

// 我一般从200kΩ开始试
max30102_write_reg(0x0E, 0x10);  // 设置增益200kΩ

调试建议:先用手边最厚的测试者(比如大拇指)来调增益。如果最厚的手指都能得到不错的信号,那薄手指可以通过降低LED电流来适配,而不是反过来。

4.3 环境光抑制策略——白天黑夜都要准

环境光干扰是血氧仪最头疼的问题之一。你想想看,用户在户外阳光下测血氧,和在被窝里测,环境光强度差了几百倍。如果不做抑制,ADC早饱和了。

环境光干扰主要有两种:

  • 直流分量:太阳光、室内照明等持续光源,会让光电二极管产生较大的直流偏置
  • 交流分量:50Hz/60Hz的荧光灯频闪,会叠加到PPG信号上

常用的抑制策略有三种,我按效果排序:

策略 原理 优点 缺点
采样时序法 LED亮时采一次,灭时采一次,相减 实现简单,无额外硬件 对运动伪影敏感
模拟低通滤波 在TIA后加低通滤波器 抑制高频噪声效果好 会滤掉部分PPG信号
环境光消除环路 用DAC产生反向电流抵消环境光 效果最好,动态范围大 需要额外DAC,成本高

我最常用的是采样时序法,因为大多数AFE芯片都内置了这个功能。以AFE4404为例,它的时序是这样的:

// AFE4404 环境光抑制时序配置
// 一个完整的采样周期包含4个阶段:
// Stage 1: 红光LED亮,采样红光+环境光
// Stage 2: 所有LED灭,只采样环境光
// Stage 3: 红外LED亮,采样红外+环境光  
// Stage 4: 所有LED灭,只采样环境光

// 实际信号 = (LED亮时采样值) - (LED灭时采样值)
// 这样就把环境光的直流分量去掉了

我曾经遇到过一个案例:某款手环在户外阳光下血氧值乱跳。查了半天,发现是环境光变化太快,采样时序跟不上。后来把采样率从100Hz提到200Hz,问题解决了。所以环境光抑制不只是硬件的事,时序配合也很关键。

对于50Hz/60Hz的工频干扰,我建议在软件层面再加一道陷波滤波器。硬件滤波虽然也能做,但电容电感会占体积,而且中心频率不好调。软件陷波就灵活多了:

// 50Hz IIR陷波滤波器示例(采样率200Hz)
// 二阶陷波,Q值30
float b0 = 0.9900f;
float b1 = -1.9601f;
float b2 = 0.9900f;
float a1 = -1.9601f;
float a2 = 0.9801f;

float notch_filter(float input) {
    static float x1 = 0, x2 = 0, y1 = 0, y2 = 0;
    float output = b0*input + b1*x1 + b2*x2 - a1*y1 - a2*y2;
    x2 = x1; x1 = input;
    y2 = y1; y1 = output;
    return output;
}

实战经验:环境光抑制的调试,我建议在三个场景下验证:强光直射(户外正午)、弱光(暗室)、频闪光(荧光灯下)。每个场景跑5分钟,看波形稳定性。如果某个场景下波形出现周期性毛刺,那大概率是环境光抑制没做好。

4.4 三个参数的协同调试

LED电流、TIA增益、环境光抑制,这三个参数不是孤立的。它们互相影响:

  • LED电流大了,环境光的影响相对变小,但容易饱和
  • TIA增益高了,信号放大倍数大,但噪声和环境光也被放大了
  • 环境光抑制做得好,就可以用更小的LED电流和更高的增益

我个人的调试顺序是:先定环境光抑制策略 → 再调TIA增益 → 最后微调LED电流。这个顺序能让你少走很多弯路。

最后提醒一句:所有参数调好后,一定要做温度测试。LED的发光效率随温度变化,TIA的增益也有温漂。我有一款产品在常温下测得好好的,拿到东北零下20度,血氧值直接偏了3%。后来加了温度补偿才搞定。

好了,AFE配置这块就讲到这里。下一章咱们聊ADC采样与数字滤波,到时候会用到今天调好的这些参数。记住一句话:AFE调好了,血氧仪就成功了一半