ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从PPG到心率算法:MAX30102可穿戴开发与调参全攻略

从PPG到心率算法:MAX30102可穿戴开发与调参全攻略 做可穿戴心率检测PPG这个词躲不开MAX30102这颗芯片八九成也躲不开。它几乎以一己之力把反射式光电容积脉搏波描记法从实验室方案变成了大众化开源组件各种开发板、智能手环、健康戒指上都能见到它的身影。不过把MAX30102焊到板子上读出一串波动的ADC值和真正把一个稳定的心率算法跑通完全是两码事。串口里那组数字背后至少有采样配置、滤波去噪、峰值检测、运动伪影抑制、异常剔除一整套链路任何一环偷懒最终屏幕上跳动的数字都会给你脸色看。这篇文章是我用MAX30102做心率和血氧产品时整个调参过程的复盘适合正在做智能手环、健康手表、IoT健康设备的开发者也适合刚接触PPG信号处理的学生我会尽量把原理、参数、代码和踩坑点写透。1. 硬件底子MAX30102为什么能成为心率传感器的“默认选项”1.1 从分立功放方案到单芯片AFE为什么大家都选MAX30102在很多年的可穿戴项目里PPG信号处理最折磨人的不是算法而是模拟前端。光电二极管输出的电流非常微弱通常只有几纳安到几百纳安要把它变成可被MCU读取的数字信号需要低偏置电流运放、跨阻放大器、抗混叠滤波、高精度ADC还要设计屏蔽和驱动电路。这一套东西做下来PCB面积大、元器件多、EMC问题多而且任何一个环节的噪声控制不到位信号就废了。MAX30102把这条路走通的方式很粗暴把红光LED、红外光LED、光电二极管、LED驱动器、低噪声模拟前端、18bit ADC、温度传感器、FIFO和I2C接口全部封装在一颗芯片里。外部只需要一个MCU用I2C读数据剩下的模拟信号链路全在内部完成。换句话说芯片厂商把最难调的跨阻放大器和ADC都替你调好了你要面对的基本是一个数字传感器。从采购和研发角度看这个方案的优势也很实际单芯片方案大幅减小了物料清单和PCB面积光源和探测器之间的相对位置已经被封装固定不再需要自己去算光功率、调透镜对焦。我见过不少项目用分立光电器件做了几个月最后因为产品反复在“信号穿不透外壳”和“低速运动时波形乱跳”之间摇摆不得不换回集成方案。MAX30102在市面上的开源资料多、参考代码多、价格也透明硬件门槛被压得极低所以它几乎成了这类产品的默认起点。需要注意的是MAX30102并不是唯一选择也不能在所有场景下都无脑用。比如医疗级血氧产品如果要求更高的动态范围和多波长测量往往会选更专业的方案但如果目标是快速做出一个能演示、能验证算法、能小批量落地的可穿戴心率血氧设备MAX30102是目前性价比最均衡的路径。1.2 光路与信号链LED到光电二极管之间发生了什么先讲清楚传感器里那条看不见的信号路径。MAX30102工作时内部LED驱动电路产生脉冲电流让红外光和红光交替照射到皮肤表面。光进入组织后会发生吸收和散射一部分光被血液、骨骼、肌肉、脂肪吸收剩下的反射或散射回光电二极管。关键在“血液”这一项动脉血中血红蛋白的浓度随着心脏搏动呈周期性变化心跳收缩期动脉血容量增加对光的吸收量增加舒张期动脉血容量减少吸收量降低。于是光电二极管接收到的反射光强度呈现一个微弱但规律的波动。这个波动信号经过光电转换、跨阻放大、ADC采样后就变成了我们常说的PPG信号。PPG信号可以拆成两部分直流分量和交流分量。直流分量来自皮肤、骨骼、静脉血等静态组织的吸收数值很大占ADC读数的绝大部分交流分量来自动脉搏动幅度通常只有直流分量的0.1%到几个百分点是非常微弱的一个“小波纹”。很多刚接触的人打开串口看原始ADC值时以为那串大致稳定的大数字就是脉搏波形其实真实的心率信息藏在大数字末几位的变化里。这也是为什么需要18bit级别的ADC如果位数不够那个小波纹直接被量化噪声吞掉了。理解了这个机理后面很多调试逻辑就顺了为什么需要做带通滤波因为要把直流分量和高频噪声丢掉只留下0.5到5Hz的心率频段。为什么运动时信号会崩因为肢体晃动改变了光路长度和反射角度光电二极管收到的信号被叠加上了一个巨大的、非周期性的低频扰动。这些问题后面会逐个展开。1.3 硬件设计上容易被忽略的三个关键点很多人在STM32、ESP32开发板上用杜邦线连一下MAX30102模块就能出波形就以为硬件设计很简单。但真正做可穿戴产品时硬件上几个细节没处理好算法再强也救不回来。第一个是光学隔离。MAX30102封装里虽然集成了LED和光电二极管但模块表面和PCB上仍然需要做遮光处理。LED发出的光如果直接通过外壳、PCB走线缝隙或贴片焊盘边缘窜进光电二极管接收区就会形成一条“直通光路”产生极大的静态偏置甚至饱和压缩交流分量的动态范围。我建议在传感器和外壳之间加环形遮光泡棉让光只能走“出射—皮肤—反射—接收”这条路线外界杂光和内部直通光都被挡掉。第二个是接触压力。传感器的佩戴压力直接决定信号质量。压力太小传感器和皮肤之间有空隙外界光会漏进去运动时相对位移也大压力太大毛细血管被压扁局部灌注不足交流分量又会变弱甚至消失。比较合适的标准是佩戴后传感器紧贴皮肤没有明显晃动但皮肤上也没有勒痕。量产壳体设计时传感器区域要略凸出保证和皮肤充分接触。第三个是电源和布局。MAX30102的红外LED峰值电流可能到几十毫安虽然它是脉冲驱动平均功耗不高但如果供电纹波大LED电流的波动会直接调制到光信号上。建议LED电源用独立的LDO或加磁珠隔离I2C线上拉电阻按400kHz速率配置传感器尽量远离WiFi模块天线和其他高频干扰源。电源纹波这个问题排查起来很隐蔽因为波形看起来像正常PPG但幅度和形态总会微小变化很容易被误判为算法问题。2. 信号采集与配置ADC数据只是起点不是终点2.1 采样率、LED电流与ADC精度怎么配才合理MAX30102的寄存器配置选项比较多项目里最常动的就是采样率、LED电流和ADC脉宽这三个参数它们互相制约不能拍脑袋填。采样率方面心率的物理范围大概在30到240bpm折算成频率是0.5到4Hz。根据奈奎斯特定理理论上8Hz采样就够但实际滤波和峰值检测对波形细节有要求取50到100sps是比较合理的范围。我在产品里常用100sps偶尔用50sps省电再高到200sps并没有带来明显收益反而挤占FIFO和MCU带宽。这里有一个常见误区有人觉得采样率越高测得越准。PPG信号本身带宽有限采样率再高也只是多采了噪声和高频毛刺对心率精度几乎没有提升。LED电流是决定信号质量的关键。如果电流太大光电二极管接收到的光强可能把ADC顶到满量程附近交流分量被“压扁”如果电流太小信号幅度太低信噪比不足。一个实用的调法是以红外通道为基准观察ADC平均值落在满量程的40%到70%之间。我用18bit ADC时满量程约262143理想情况下红外通道的平均值在10万到18万之间。如果读数长期高于这个范围就降低LED电流如果低于这个范围就提高直到找平稳点。这个调整通常是在不同肤色、不同佩戴位置的人群上反复测最后取折中值。ADC脉宽和分辨率是绑定关系脉宽越长每个样本的积分时间越长等效分辨率越高最高可以到18bit。但脉宽也不是越长越好太长了会限制最高采样率而且对快速变化的心率信号来说过长的积分时间等于做了额外平滑反而模糊了波的形态。一般我用411us脉宽配合18bit采样率100sps城市环境下表现比较稳。2.2 寄存器配置与驱动初始化照着这个步骤来MAX30102的驱动初始化不算复杂但顺序有讲究容易出错的地方是没给芯片复位留足时间就开始配置。我习惯的流程是拉高电源等待芯片稳定执行软复位等10ms以上。配置模式寄存器选择SpO2模式或心率模式。心率模式只点亮红外LED功耗更低SpO2模式红/红外双LED工作可以同时算血氧代价是功耗高一些。配置采样率、ADC脉宽和量程。配置LED电流寄存器。清空FIFO开启FIFO满中断或直接轮询FIFO数据计数。读取一次FIFO数据确认能拿到有效样本。下面是一段初始化示意寄存器名称按MAX30102数据手册为准具体位定义以你的手册版本为准void max30102_init(void) { // 软复位 max30102_write_reg(REG_MODE_CONFIG, 0x40); delay_ms(20); // SpO2模式红/红外双LED max30102_write_reg(REG_MODE_CONFIG, 0x03); // SPO2_CONFIG100sps采样率411us脉宽18bit量程按手册推荐值 // 不同库对位定义封装不同建议对照手册填入 max30102_write_reg(REG_SPO2_CONFIG, 0x67); // 红光LED电流0x24附近大概在10mA档位需按手册换算 max30102_write_reg(REG_LED1_PA, 0x24); // 红外LED电流同样需要实测调整 max30102_write_reg(REG_LED2_PA, 0x24); // 清FIFO max30102_flush_fifo(); }这段代码里的数值不是万能值我特意不把每个寄存器的每个位全列出来是因为不同厂家封装的库函数定义并不完全一样直接抄一个魔数反而容易出问题。建议你初始化完成后做两件事第一读一下FIFO数据确认不是0也不是满量程第二把ADC值实时打印出来肉眼看到类似脉搏波的“小山包”再继续往下调算法。2.3 读FIFO的正确姿势防止数据溢出和错位MAX30102内部有个32样本深度的FIFOMCU如果轮询不及时FIFO满了之后新数据会覆盖旧数据。虽然芯片有溢出标志位但更稳妥的方法是开启FIFO_A_FULL中断或者用固定周期读取确保读取速度大于数据产生速度。以100sps为例每秒产生100个样本对MCU每10ms读一次就能稳定跟上。读取时要注意数据格式每一笔FIFO数据包含红、红外两个通道各3字节的18bit样本按从高位到低位的顺序拼接。读的时候要一次性读出6字节然后拼成两个int32_t不能拆开读否则中间插入了写指针变化就可能导致数据错位。拼完的原始值是unsigned型做算法前建议转成有符号float减去一个基线方便后续滤波。在嵌入式端我会维护一个长度为300到600的环形缓冲区相当于保存3到6秒的历史数据。这样无论是做中值滤波、滑动窗口还是频谱分析都有足够的数据可用。缓冲区按照“写入新样本、丢弃最老样本”的方式滚动这是后面所有算法的基础。3. 心率算法实战从一条PPG曲线到一个心率数值3.1 预处理去直流、带通滤波与参数选择拿到原始ADC序列后第一件事是去掉直流分量。最简单的方法是计算一个较长窗口的滑动平均作为基线估计再从原信号里减掉它。窗口长度要覆盖至少几个心跳周期通常取1到2秒。如果直接对整个序列减均值在实时系统中会因为新数据进来导致基线不断变化反而引入额外误差。去直流之后信号里还存在呼吸引起的低频基线漂移、肌肉电噪声、电源工频干扰等。这些噪声主要集中在两个频段0.5Hz以下的缓慢漂移和几十Hz以上的高频毛刺。心率本身在0.5到4Hz之间所以用一个带通滤波器把范围卡住是最标准的做法。滤波器参数怎么选高通截止频率0.5Hz对应30bpm低通截止频率5Hz对应300bpm这个范围覆盖了绝大多数人群的极限心率。如果产品只面向日常静息和轻运动场景可以收紧到0.8到3.5Hz能把更多噪声挡在外面。我建议一开始先用0.5到5Hz调完峰值检测没问题再根据实测波形慢慢收紧。滤波器的实现有两种思路离线分析时用Python的scipy做零相位滤波开发阶段方便看波形嵌入式实时运行时用IIR滤波器计算量小、延迟低。以Python验证为例import numpy as np from scipy.signal import butter, filtfilt def preprocess_ppg(raw, fs100.0): # 去直流 baseline np.convolve(raw, np.ones(int(fs)) / fs, modesame) x raw - baseline # 0.5~5Hz 带通 b, a butter(2, [0.5, 5.0], btypebandpass, fsfs) y filtfilt(b, a, x) return y用filtfilt做零相位滤波是为了画图时波形位置不偏移方便观察峰和谷的对应关系。到了MCU上不能用filtfilt它是离线函数会引入整个信号长度的延迟。实时场景一般用两个二阶IIR级联一个高通一个低通或者用一个四阶巴特沃斯带通IIR。IIR滤波器的相移会导致峰值位置偏移计算峰间间隔时如果每个峰偏移量一致其实不影响间期长度但如果滤波参数切换就可能引入伪的间期变化所以配置了滤波器参数之后不要随便改。3.2 峰值检测阈值法、斜率法和自适应阈值哪个实用滤波后的信号是规律的心跳脉冲接下来要从里面找到每个心跳峰的位置也就是完成峰值检测。最简单的思路是阈值法设定一个固定幅度阈值信号超过阈值且达到局部最大就认为是峰值。这个做法在静息状态、信号幅度稳定的场景下能跑但一旦佩戴松紧变化或者运动PPG幅度会剧烈波动固定阈值要么漏检要么把噪声当峰值。更可靠的是斜率法先计算信号的一阶差分当差分值从正变负、且当前信号值超过一个动态设定的阈值时记为候选峰。这个“正变负”的时刻对应信号由上升转为下降的拐点也就是波峰位置。斜率法比单纯阈值法更稳因为它更关注波形形态而不是绝对幅度。实践中我反而更喜欢一种结合方案用一个粗阈值做预检测比如阈值取当前窗口信号RMS的0.6倍先用它把可能是峰的局部区域标出来然后在每个局部区域里找最大值精确定位。这种方法计算量小也基本不会和重搏波搞混。重搏波是主动脉瓣关闭后造成的二次小隆起幅值通常比主峰低很多只要粗阈值设得合适它不会被当成主峰。自适应阈值是进一步提升鲁棒性的关键。算法不是用固定阈值而是实时统计最近一段时间内检测到峰值的幅度中位数用这个中位数去更新下一次检测的阈值。公式大约是threshold 0.6 * median_peak_amplitude。如果连续2秒没有检测到新的峰值就认为阈值设高了按一定比例衰减阈值防止漏检。另外必须加上最小峰间间隔限制。两个峰之间的时间间隔不可能是零即便心率飙到240bpm间隔也有250ms。所以我一般设置最小间隔为250ms小于这个间隔的候选峰直接丢弃。这个限制能有效过滤掉双峰误检和部分高频毛刺。3.3 心率估计与异常值剔除策略检测到足够多的峰值后把相邻峰之间的间隔算出RR间期序列单位是秒。单次瞬时心率等于60 / RR。但单个间期非常容易受到噪声和误检影响直接输出会很飘所以要在滑动窗口内做统计。做法是保留最近5到10个RR间期先做一次异常值剔除对每个RR间期计算它与窗口中位数之间的偏差如果偏差超过20%就判定为异常丢弃。然后对剩余有效间期取中位数或均值再用60 / 平均间期得到心率。中位数比均值抗离群点能力强我通常用中位数。输出到上层时还需要做一个平滑否则屏幕上数字会每隔一秒跳好几下。指数移动平均是简单有效的方案hr_smooth alpha * hr_new (1 - alpha) * hr_smoothalpha取多少要看产品定位。追求响应速度时alpha取0.5到0.7运动模式下数字更新快但有抖动追求平稳显示时alpha取0.2到0.3数字稳但反应慢。我通常做两档连续检测阶段alpha取0.4一旦刚启动或信号质量差时强制拉高alpha让算法快速收敛到真实心率等稳定后再降回来。这里有个很重要的细节如果只输出一个平滑后的心率很多人会忽略信号质量评估对用户体验的影响。算法不知道自己算错了它会很自信地输出一个错误数值。所以一定要在算法内部维护一个“置信度”或者“信号质量指数”当信号质量差时宁可不更新心率也不要输出一个跳变很大的数值。宁可屏幕上数字保持2秒不变也不能让它从70突然跳到130再跳回来后者会让用户直接放弃这个产品。3.4 低成本信号质量评估让算法学会“认怂”信号质量评估有很多高大上的方法但在MCU上朴素的三条规则就能解决大部分问题第一看峰间间隔规则性。正常情况下RR间期虽然会波动但不会瞬间剧烈变化。如果最近5个RR间期的标准差很大比如超过平均间期的30%说明峰值检测不可靠信号质量打分就要降低。第二看峰值幅度一致性。如果相邻峰幅度忽高忽低差异非常大大概率是运动伪影叠加而不是真实血流信号。第三看窗口内信噪比。计算带通滤波后信号的能量和目标频段外能量的比值这个比值过低时直接判定为低质量信号。我经常把信号质量指数分成三档高质量、低质量、不可用。高质量时正常输出心率更新平滑参数低质量时延长窗口、不做输出或打上低置信度标签不可用时保持上一帧输出并在上层提示“请佩戴紧一些”。这个“认怂”机制看似简单却能在真实使用场景中减少大量售后投诉。4. 运动伪影心率算法最容易翻车的地方4.1 运动伪影是怎么产生的为什么静态好用一动就乱运动伪影是PPG方案最大的痛点没有之一。它的本质是运动导致传感器和皮肤之间发生相对位移皮肤组织和毛细血管床的光路被改变光电二极管接收到的光强产生大幅度变化。偏偏走路、跑步的摆臂频率大约在1到3Hz和心率的频段几乎完全重叠滤波器根本无法干净地把它们分开。我拿示波器看过大量运动状态下采集的原始信号搏动波形被叠加上了一个频率接近、幅度大好几倍的大波浪波峰和波谷已经分不清是心跳还是运动产生的。这种情况下峰值检测算法会同时检测出很多假峰心率计算结果就是乱跳。既然频域分不开工程上就只能从三个角度下手硬件上减小相对位移算法上利用额外信息做补偿策略上在信号确实不可恢复时放弃输出。前两个是提升上限第三个是兜底。4.2 加速度计辅助与自适应滤波能救回来一部分如果你做的产品里本来就有加速度计可以尝试用自适应滤波消除一部分运动噪声。思路是把加速度信号的模值或某个轴的分量当作运动噪声的参考信号用LMS或NLMS算法自适应地估计运动噪声在PPG信号中的权重然后从PPG信号中减掉。简化版的NLMS公式长这样// nlms伪代码参考信号acc为加速度幅值ppg为滤波后PPG for (i 0; i n; i) { y[i] w * acc[i]; e[i] ppg[i] - y[i]; mu 0.01 / (acc[i] * acc[i] 1e-6); w mu * e[i] * acc[i]; }这个方案看着不难实际调起来很费劲。μ系数、参考信号选哪个轴、是取幅值还是原始三轴分别滤波都会影响效果。我在项目里试过多次发现它对走路这种规律运动有一定改善但对摆臂频率和心率恰好接近、或者运动突然开始结束的场景效果不稳定。一个经验是自适应滤波只能作为辅助手段不能作为主力方案。主链路仍然是峰值检测信号质量评估自适应滤波能减小误检率但一旦信号质量指数显示不可用就应该果断断掉输出。如果计算资源允许还可以用短时傅里叶变换或自相关分析做心率估计把它们和峰值检测结果互相校验。比如窗口内FFT频谱的主峰频率对应的心率和峰值检测得到的心率如果差异较大就以信号质量更高的那个结果为准或者直接置为低置信度。4.3 实测场景记录静止、快走、跑步下的表现我在实际测试中记录过一组典型数据比较能说明问题静止坐姿信号质量高时误差基本在±2bpm以内属于算法稳定区。正常走路摆动手臂规律心率约90到110bpm峰值检测的误检率明显上升。此时如果开启加速度计辅助滤波误差大约从±8bpm降到±4bpm但依然偶尔有跳变。上下楼梯或快走运动幅度大且不规则误差会达到±15bpm以上。这种时候我选择启用“低置信度保持策略”让心率显示保持上一帧同时给上层一个信号质量低的标志。跑步且腕带偏松说实话MAX30102这种单路反射式传感器能直接输出的结果非常不可靠如果产品定位是专业跑步心率我会建议在算法里检测到连续低质量信号时明确提示用户重新佩戴而不是硬输出一个错误数值误导训练。这些测试必须在真实目标人群上做不能只在自己手上测。不同肤色、不同手腕粗细的人的信号幅度和信噪比差异很大有些人静息时信号好到可以数毛刺有些人则无论怎么调LED电流都只有很小的AC分量。5. 排障与调参实录问题速查表和独家经验5.1 实测中常见的12个问题与排查方法我把项目里遇到过、也帮别人排查过的典型问题整理成了一张速查表方便你出问题时对号入座现象可能原因排查方法ADC读数一直接近满量程LED电流过大、传感器被完全遮挡、光学直通降低LED电流检查遮光泡棉和外壳开孔ADC读数一直为0或极小芯片初始化失败、LED未点亮、I2C读取错误重新配置寄存器检查供电和复位检查I2C地址波形有规律但幅度太小佩戴过紧导致局部缺血、LED电流太低调整佩戴压力提高LED电流波形存在缓慢大波浪呼吸引起的基线漂移、环境光变化提高高通截止频率检查外壳是否漏光心率偶尔跳到两倍或一半峰值误检或漏检、重搏波被误判为主峰增加最小峰间间隔优化自适应阈值检查滤波参数心率高频抖动平滑系数太小、信号质量不稳定增大指数平滑提高信号质量门限静止正常走路就乱运动伪影开启加速度计辅助滤波低质量时保持输出不同人测试同一算法效果差异大肤色、血管状态、佩戴差异调整LED电流增加信号质量评估必要时做个体校准低灌注场景信号丢失局部血流不足、冬天手凉提高LED电流让用户搓热手优化佩戴位置FIFO溢出读取不及时提高轮询频率或改用FIFO满中断I2C读写偶尔失败上拉电阻过大、时钟速度太高检查I2C上拉降低到100kHz验证功耗偏高LED电流设置过高、采样率过高降低LED电流用低采样率模式这个表格不是万能的但覆盖了80%以上的常见问题。最值得记住的一点是出现问题先看原始ADC波形不要盯着最终心率值猜。心率值是经过好几层处理的结果很容易掩盖原因。5.2 波形诊断把信号画出来再调参我一直坚持一个原则如果无法画出滤波前后的波形就不要开始调算法。原因很简单只有看到波形你才能判断问题出在哪一层。串口打印ADC原始值在电脑上收集几百个样本画成图这一步花不了半小时但能省下好几天的盲目调参。画图之后重点看三个指标。第一DC基线的高度和稳定性。基线高说明接收光强强可以考虑降低LED电流基线剧烈波动说明有环境光干扰或运动伪影。第二AC波形的幅度和形态。幅度太小说明信噪比不足幅度忽大忽小说明接触不稳定。第三滤波后波形是否干净。滤波后应该能看到清晰的脉冲串如果还能看到明显的慢漂移说明高通截止频率太低如果波形上有大量毛刺说明低通截止频率太高。我在调试时会同时打印四个数据原始ADC、去直流后的信号、带通滤波后的信号、峰值位置标记。这样任何一个环节出错一眼就能看出来。千万不要只在最后串口上看到心率数字就以为算法是好的因为一个看起来不错的心率数字可能是靠强力平滑“硬抹”出来的假象。5.3 跨肤色、跨佩戴方式的适配经验MAX30102这类反射式传感器对不同肤色的响应差异非常大。肤色深的人皮肤表皮层对红光的吸收明显增加红光通道的AC信号可能弱到几乎看不见红外波长受黑色素影响小信号相对稳定。所以我通常优先用红外通道做心率计算只有需要算血氧时才依赖红光通道。血氧算法里红光和红外通道的AC/DC比值是核心参量动笔之前先确认两个通道的PPG波形都合格否则算出来的SpO2没有意义。佩戴方式上腕带式和胸贴式的调试重点完全不同。腕带式最大的问题是运动伪影和佩戴松紧胸贴式由于接触面积大、相对稳定信号质量通常更好但要做到不磨皮肤且持续贴合结构设计上更难。如果做的是耳夹、戒指这类小体积产品尺寸小、光学路径短更容易受外界光干扰遮光要求会更苛刻。还有一个容易被忽视的点冬季或低温环境下末梢血管收缩AC分量会显著变小。很多产品夏天测试没问题冬天一到用户反馈心率测不出来就是这个原因。应对措施是提高LED电流或者在算法里加一个针对低灌注状态的自动增益控制检测到信号AC幅度持续偏低时自动调高LED电流直到信号幅度进入合理区间。这个机制对用户体验的提升非常明显。最后再分享一个实用经验参数调好后不要只在自己手腕上验证。找十个不同性别、不同年龄段、不同肤色、不同胖瘦的人每个人分别在静息、走路、小跑三种状态下测一遍把数据留下来作为后续迭代的依据。你很快会发现真正阻碍心率算法落地的往往不是数学原理而是那些在实验室里根本不会出现的真实佩戴细节。把这些细节一个个解决掉算法才算真正“能打”。
返回列表