[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ruMH93P-1578563433204)(http://139.199.225.16/blog_pic/2017_03_10/system_block.jpg)]
这里有一篇TI的测血氧文档http://www.ti.com/lit/an/slaa274b/slaa274b.pdf,其中的给的测血氧的公式没怎么看懂,关键怎么通过这公式得到血氧的含量的 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8cX5Iary-1578563433206)(http://139.199.225.16/blog_pic/2017_03_10/R_SaO2.jpg)]心率
在实际操作中发现,使用IR(红外)读出的心跳值(AC Component)会比较偏大,所以使用IR读出的数据作为测心率的标准。
初始数据读出如下图,注意纵坐标,交流部分只占直流的很少一部分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XM0hMMxx-1578563433208)(http://139.199.225.16/blog_pic/2017_03_10/DataBeforeProcess.jpg)]
滤波一开始采用带通滤波器的方法,目的是滤掉直流部分和交流部分中心率波上面的毛刺可是发现不理想(带通滤波器参数 fs = 100Hz, fls = 0.8Hz, fhs = 2.5Hz, 四阶IIR),选这个参数是因为心跳频率一般在1Hz-2Hz之间。估计是采样频率太低了,但是stm32f103的性能满足不了更高采样率的滤波器, 以后用更高性能的芯片试试。
后来直接区512点的滑动平均求的直流分量,原始数据减去直流分量就得出交流分量,如下图 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LgWMZ6gL-1578563433211)(http://139.199.225.16/blog_pic/2017_03_10/DataAfterAve.jpg)] 做个峰值检测就得到心率
血氧
应该需要进行定标的工作,只根据公式简单写出算法。arm_biquad_cascade_df1_q31(…)这次使用直接I型的IIR滤波器函数,用Matlab的Fdatool求出sos(安富莱教程), 然后将参数写入滤波器初始化函数中就行。注意因为使用的Q31格式,参数也必须是Q31格式,必须将参数缩小到Q31格式能表示的范围内。还要注意的就是输入序列,其值的范围必须在【-0.25 +0.25)中,因为官方库有这样一段话(In order to avoid overflows completely the input signal must be scaled down by 2 bits and lie in the range [-0.25 +0.25).)。
附上一个Matlab 滤波器 与 MCU 滤波器的比较Matlab程序。
function [X1, X2, X3] = MCU_Filter_Test(sos, xin, ymcu, Len) %MCU Filter Test [b, a] = sos2tf(sos); y = filter(b, a, xin); X1 = fft(xin); X2 = fft(y); X3 = fft(ymcu); n = [0 : Len - 1]; subplot(3,2,1); plot(n, xin);title('xin'); subplot(3,2,2); plot(n, abs(X1));title('xin-fft'); subplot(3,2,3); plot(n, y);title('y'); subplot(3,2,4); plot(n, abs(X2));title('y-fft'); subplot(3,2,5); plot(n, ymcu);title('ymcu'); subplot(3,2,6); plot(n, abs(X3));title('ymcu-fft');因为已经转行做软件了,所以将所有的代码公开。当初这个系统是在大学的时候做的,是帮的做毕业设计。
下载 基于MAX30100和stm32的血氧检测系统。