基于单片机的常规肺活量SVC简单计算
常规肺活量 SVC(Slow Vital Capacity)是指尽力吸气后缓慢而又完全呼出的最大气量。
成年男性的肺活量通常在 3500-4000ml 之间,成年女性的肺活量通常在 2500-3000ml 之间。
单片机一般通过外接流量传感器,使用ADC高速采集的方式来获取当前流速数据。
肺活量吹气检查流程大致为 : 呼气 --> 吸气 --> 呼气 --> 深吸气到头 --> 深呼气到头 --> 深吸气 --> 深呼气 --> 深吸气 --> 深呼气。。。
#define nFLOW_SAMPLE (10)//ms
#define qAbs(x) (((x) > 0.0f) ? (x) : -(x))
#define qFuzzyIsNull(x) (qAbs(x) <= 0.00001f)
#define qMax(x,y) ((x) > (y) ? (x) : (y))
#define qMin(x,y) ((x) < (y) ? (x) : (y))
#define STAGE_MAX_SIZE (1000)
static float vecdStage_1[STAGE_MAX_SIZE] = {0};
static float vecdStage_2[STAGE_MAX_SIZE] = {0};
static float vecdStage_3[STAGE_MAX_SIZE] = {0};
static float vecdStage_4[STAGE_MAX_SIZE] = {0};
//SVC(slow VC)常规肺活量指标
typedef struct {
int bIsIntact; // 源头数据完整性
float dVT; // 潮气量 静息呼吸时每次吸入或呼出的气体容积
float dIRV; // 补吸气量 平静吸气末用力吸气所能吸入的最大气容积
float dERV; // 补呼气量 平静呼气末用力呼气所能呼出的最大气容积
float dIC; // 深吸气量 平静呼气末用力吸气所能吸入的最大气容积 IC = VT + IRV
float dVC; // 慢肺活量 尽力深吸气后作深慢呼气所能呼出的最大气容积 VC = IC + ERV
float dDvVC; // 肺活量差值(3次中的最大差值)
}LungVolExamParam;
/**
过零点位置如下:
呼气 --> (1)吸气 --> (2)呼气 --> (3)深吸气到头 --> (4)深呼气到头 --> (5)深吸气 --> (6)深呼气 --> (7) 深吸气 --> (8) 深呼气 (9)
*/
LungVolExamParam __calc_svc_test(float*dFlowData,int nSumCnt)
{
LungVolExamParam tLungVolExamParam = {0};
tLungVolExamParam.bIsIntact = true;
int vecdStage_1_count = 0;
int vecdStage_2_count = 0;
int vecdStage_3_count = 0;
int vecdStage_4_count = 0;
//流速零点
int nZeroPoint = 0;
//开始引索
int nStartIdx = 0;
float dMaxVal, dMinVal;
float dTmpCapatity = 0;
float dTmpVC_1, dTmpVC_2, dTmpVC_3;
int real_start_idx = 1;
//分段
for (int i = real_start_idx; i < nSumCnt; i++) {
//两点间经过零点
if (dFlowData[i - 1] * dFlowData[i] <= 0
&& !qFuzzyIsNull(dFlowData[i]))
nZeroPoint++;
if(i == nSumCnt - 1) nZeroPoint++;
//第一段数据采集
if (3 == nZeroPoint && !vecdStage_1_count) {
memcpy(vecdStage_1,dFlowData + nStartIdx,(i - nStartIdx) * sizeof(float));
vecdStage_1_count = i - nStartIdx;
nStartIdx = i;
}
//第二段数据采集
else if (5 == nZeroPoint && !vecdStage_2_count) {
memcpy(vecdStage_2,dFlowData + nStartIdx,(i - nStartIdx) * sizeof(float));
vecdStage_2_count = i - nStartIdx;
nStartIdx = i;
}
//第三段数据采集
else if (7 == nZeroPoint && !vecdStage_3_count) {
memcpy(vecdStage_3,dFlowData + nStartIdx,(i - nStartIdx) * sizeof(float));
vecdStage_3_count = i - nStartIdx;
nStartIdx = i;
}
//第四段数据采集
else if (9 == nZeroPoint && !vecdStage_4_count) {
memcpy(vecdStage_4,dFlowData + nStartIdx,(i - nStartIdx) * sizeof(float));
vecdStage_4_count = i - nStartIdx;
//算上最后一个数据
nStartIdx = i + 1;
}
//达到8后的第一个零点
if(8 == nZeroPoint &&
dFlowData[i - 1] * dFlowData[i] <= 0 &&
!qFuzzyIsNull(dFlowData[i - 1]))
nZeroPoint++;
}
//验证分段数据完整性
if(!(vecdStage_1_count > 0 && vecdStage_2_count > 0 && vecdStage_3_count > 0
&& vecdStage_4_count > 0))
tLungVolExamParam.bIsIntact = false;
//第一段数据计算
dMaxVal = dMinVal = dTmpCapatity;
for (int i = 0; i < vecdStage_1_count; i++) {
//流速为L/min,累计流量为当前流速乘以时间
dTmpCapatity += vecdStage_1[i] * (nFLOW_SAMPLE / 1000.0 / 60.0);
if (dMaxVal < dTmpCapatity) dMaxVal = dTmpCapatity;
if (dMinVal > dTmpCapatity) dMinVal = dTmpCapatity;
}
//潮气量
tLungVolExamParam.dVT = dMaxVal - dMinVal;
//第二段数据计算
dMaxVal = dMinVal = dTmpCapatity;
float dTmpVal = dTmpCapatity; // 记录阶段开始时的气容量
for (int i = 0; i < vecdStage_2_count; i++) {
//流速为L/min,累计流量为当前流速乘以时间
dTmpCapatity += vecdStage_2[i] * (nFLOW_SAMPLE / 1000.0 / 60);
if (dMaxVal < dTmpCapatity) dMaxVal = dTmpCapatity;
if (dMinVal > dTmpCapatity) dMinVal = dTmpCapatity;
}
// 深吸气量
tLungVolExamParam.dIC = dTmpVal - dMinVal;
tLungVolExamParam.dIRV = tLungVolExamParam.dIC - dTmpVal; // 补吸气量
tLungVolExamParam.dERV = dMaxVal - dTmpVal; // 补呼气量
dTmpVC_1 = dMaxVal - dMinVal; // 第一轮的肺活量
//第三段数据计算
dMaxVal = dMinVal = dTmpCapatity;
for (int i = 0; i < vecdStage_3_count; i++) {
//流速为L/min,累计流量为当前流速乘以时间
dTmpCapatity += vecdStage_3[i] * (nFLOW_SAMPLE / 1000.0 / 60);
if (dMaxVal < dTmpCapatity) dMaxVal = dTmpCapatity;
if (dMinVal > dTmpCapatity) dMinVal = dTmpCapatity;
}
dTmpVC_2 = dMaxVal - dMinVal; // 第二轮的肺活量
//第四段数据计算
dMaxVal = dMinVal = dTmpCapatity;
for (int i = 0; i < vecdStage_4_count; i++) {
//流速为L/min,累计流量为当前流速乘以时间
dTmpCapatity += vecdStage_4[i] * (nFLOW_SAMPLE / 1000.0 / 60);
if (dMaxVal < dTmpCapatity) dMaxVal = dTmpCapatity;
if (dMinVal > dTmpCapatity) dMinVal = dTmpCapatity;
}
dTmpVC_3 = dMaxVal - dMinVal; // 第三轮的肺活量
// 慢肺活量 - 取三次均值
tLungVolExamParam.dVC = (dTmpVC_1 + dTmpVC_2 + dTmpVC_3) / 3;
dMaxVal = qMax(dTmpVC_1, dTmpVC_2);
dMaxVal = qMax(dMaxVal, dTmpVC_3);
dMinVal = qMin(dTmpVC_1, dTmpVC_2);
dMinVal = qMin(dMinVal, dTmpVC_3);
// 最大差值
tLungVolExamParam.dDvVC = dMaxVal - dMinVal;
return tLungVolExamParam;
}