一、背景
2022年6月,很高兴能够参与到腾讯云AIoT应用创新大赛,有机会认识到各种行业背景的物联网爱好者,作为一个新手,接触了面向物联网领域的TencentOS Tiny系统、腾讯云物联网开发平台以及RISC-V芯片的应用实例等。
高血压作为一种常见的心血管疾病,大大的增加了心脏、肾脏等器官的负担,其初期症状主要有:头晕,耳鸣,头疼以及心悸等;调研可知,市面上销售有多款医疗监测设备,能够实现血压、血糖等生物指标的在线监测,然而依据患者实际使用体验,大多产品普遍存在精度低、可靠性差等弊端,不能切实满足用户的医疗需求;因此,最近借助AloT应用创新比赛探究了TencentOS Tiny系统以及RISC-V芯片在可穿戴医疗设备的应用前景,具体内容如下所示:
图1 基于TencentOS Tiny的电子血压计及测量结果
项目亮点:
- 基于CH32V_EVB RISC-V开发板,实现了物联网+血压计的应用demo;
- 编写了血压解算算法:通过FIR滤波的方式从压力传感器输出结果中提取脉搏波信号,相较于基于时域的血压解算方法,对ADC采样频率的依赖程度更低;
- 为人工智能算法应用于慢性病管理提供前提基础。
二、血压的测量原理
市面上销售的血压计大多采用示波法检测血压的幅值,其工作过程是:1、将袖带充气以阻断动脉血流;2、放气过程中通过听诊器探究血压与袖带压力之间的关系;3、通过信号调理以及电压采集电路检测袖带的压力变化,后续利用相应的算法提取脉搏波信号,具体过程如图2所示:
图2 血压监测的过程以及原理——示波法
三、项目整体架构
本项目基于TencentOS Tiny CH32V\_EVB RISC-V开发套件,设计了一款电子血压计demo,核心的流程框架为:采用压力传感器实时采集袖套的压力变化,后续通过算法解算出血压幅值,最终上传到腾讯物联网云平台并显示在腾讯练练小程序端,具体如图3所示。
图3 基于TencentOS Tiny的电子血压计
四、硬件组成
4.1 TencentOS Tiny CH32V\_EVB RISC-V开发板
TencentOS Tiny CH32V\_EVB RISC-V开发板主要包含主控CH32V307、ESP8266 wifi模块、ST7789屏幕以及WCH-Link等,具体如图4所示。比赛过程中学习了《TencentOS Tiny RISC-V端云AIoT一体化解决方案示例》,后续为了能够解决图像识别算法泛化能力差等弊端,编写了能够接收RGB565图像数据的matlab程序,最后调用yolov5算法实现图像的识别;具体内容见往期文章【基于TencentOS Tiny的图像识别案例】。
图4 TencentOS Tiny CH32V\\\_EVB RISC-V开发板
4.2 压力传感器
本项目中采用了XGZT6847A压力传感器模块,广泛应用于电子血压计、呼吸机、胎压计以及压力仪表等场景;其内部结构主要包含4个压敏电阻,通过惠斯通电桥将外界压力信号转变为电压信号。该款压力传感器的工作原理以及封装工艺在前期推文中具有详细描述,具体可以参考:【MEMS压力传感器—工作原理】和【mems压力传感器—封装工艺】。
图5 XGZT6847A压力传感器及工作原理
4.3 袖套以及辅助元件
电子血压计设计过程中需要用到多种辅助元件,主要包含有气囊、袖带、转接口以及杜邦线,具体如图6所示:
图6 电子血压计的配件(气囊及袖套)
五、程序源代码
基于TencentOS Tiny的电子血压计主要用到了CH32V\_EVB开发板的key、ADC模块、LCD模块以及WiFi模块等,具体架构及程序运行流程如图7所示,项目的核心在于袖带压力检测、血压计算以及MQTT通信。
图7 血压计的架构及程序运行流程
5.1 电压信号采集
前期研究表明,袖带压力的采集精度与血压计的性能息息相关;近来从硬件成本、技术难度以及工作量等多种角度出发,利用CH32V307板载的adc模块采集XGZT6847A压力传感器的输出电压,通过key1和key2分别控制血压测量的开始及结束时间,所用的程序为:
void xueyacaijiadc(uint32_t yanshi,u8 timess)
{
u16 ADC_val;
while(1)
{
u8 ii=0;
u16 i=0;
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
{
tos_task_delay(20);
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
{
while(1)
{
ADC_val = Get_ADC_Average( ADC_Channel_8, timess );
Delay_Ms(yanshi);
ADC_val = Get_ConversionVal(ADC_val);
xueyashuju(ADC_val,i);
i=i+1;
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
{
tos_task_delay(20);
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
{
tos_sem_post(&xueyaReady);
i=i-1;
xueyazhi=xueyajisuan(i);
ii=1;
break;
}
}
}
}
}
if(ii)
{
break;
}
}
}
5.2 滤波算法
项目实施过程中采用matlab Filter Designer工具箱,通过滤波算法从压力传感器的输出信号中提取脉搏波和袖带压两种特征(基于信号的频率),具体的参数设置如图8所示。由人体脉搏波的生理特征可知,其频率特征一般为0.5-25Hz;考虑到电压信号的采样频率为20hz,本项目采用高通滤波器,具体框架如图8所示:
图8 基于matlab的FIR滤波器设计
为了能够将滤波器应用于嵌入式设备,实现血压的在线监测,需要将FIR滤波器的参数输出为C文件格式,具体结果下所示:
#include "tmwtypes.h"
const int BL = 277;
const real64_T B[277] = {
0.004032097827315, -0.01361253802573,2.597171096933e-05, 0.003348334864088,
0.003625434828895, 0.003075252870792, 0.002363330670909, 0.001684305478472,
0.001086888354097, 0.000577314540584, 0.000150303226719,-0.000203595824125,
-0.0004926710990588,-0.0007227263390531,-0.0009016784083378,-0.001032396319006,
-0.001120672276141,-0.001168532570402,-0.001180365895233,-0.001156474414754,
-0.001101740427144,-0.001015878136264,-0.0009024994467314,-0.0007626855367863,
-0.0006023408366827,-0.0004221566176204,-0.0002278010444023,-2.194638011082e-05,
0.0001881785279959,0.0003997734340485,0.0006050358020624,0.0008005298221407,
0.0009782209243579, 0.001134430633007, 0.001261549186962, 0.001357407502196,
0.001415113703677, 0.001433556195906, 0.001408713236901, 0.001341963856305,
0.001229572975887, 0.001075239871217,0.0008795732861174,0.0006489666716781,
0.0003852551502332,9.872454417174e-05,-0.0002059121142722,-0.0005180020684175,
-0.0008320332250745,-0.001134172783683, -0.00141866471304,-0.001671996894583,
-0.001888430504748,-0.002055203813477,-0.002170534807299,-0.002222600479273,
-0.002212008028482,-0.002130544174645, -0.00198321289329,-0.001762747894781,
-0.001481894556659,-0.001137634776605,-0.0007460555145065,-0.0003053610713622,
0.0001577643868071,0.0006523796587688, 0.001138643754299, 0.001628607274255,
0.002085903767237, 0.002501813092496, 0.002876533604827, 0.003164214837755,
0.00338851877287, 0.003517760801587, 0.003539564797592, 0.003462967347778,
0.003281533504934, 0.002979428624974, 0.002579062725162, 0.002082149606443,
0.001493040074613,0.0008203270186895,9.469626294734e-05,-0.0006720547052417,
-0.001463763987657,-0.002259865982444,-0.003026453103984,-0.003743966181793,
-0.004391268544832,-0.004948402698578,-0.005386969969742,-0.005688090821732,
-0.005835495632912,-0.005821005029434,-0.005632151124321,-0.005262401312117,
-0.004709057485807, -0.00398126201767,-0.003089332315323,-0.002049702462558,
-0.0008797479345688,0.0003953388863763, 0.001747264964925, 0.003138571980546,
0.004531450492127, 0.005886315826933, 0.007166383757553, 0.008329678988278,
0.009334244731398, 0.0101362881621, 0.0106984004083, 0.01098554300518,
0.01096865186478, 0.0106200513836, 0.009921005429631, 0.00885679757615,
0.007419733712968, 0.00560728586161, 0.003430936137808,0.0009078874704657,
-0.001938037629184,-0.005077694888244,-0.008470486259104, -0.0120743843455,
-0.01584139953131, -0.01971705386372, -0.0236399855461, -0.02755185216501,
-0.0313904739043, -0.03509178030298, -0.03859570273574, -0.04184621012791,
-0.04478623773664, -0.04736318149261, -0.04954152912819, -0.05127042363801,
-0.05253132389338, -0.05329580730867, 0.946448561442, -0.05329580730867,
-0.05253132389338, -0.05127042363801, -0.04954152912819, -0.04736318149261,
-0.04478623773664, -0.04184621012791, -0.03859570273574, -0.03509178030298,
-0.0313904739043, -0.02755185216501, -0.0236399855461, -0.01971705386372,
-0.01584139953131, -0.0120743843455,-0.008470486259104,-0.005077694888244,
-0.001938037629184,0.0009078874704657, 0.003430936137808, 0.00560728586161,
0.007419733712968, 0.00885679757615, 0.009921005429631, 0.0106200513836,
0.01096865186478, 0.01098554300518, 0.0106984004083, 0.0101362881621,
0.009334244731398, 0.008329678988278, 0.007166383757553, 0.005886315826933,
0.004531450492127, 0.003138571980546, 0.001747264964925,0.0003953388863763,
-0.0008797479345688,-0.002049702462558,-0.003089332315323, -0.00398126201767,
-0.004709057485807,-0.005262401312117,-0.005632151124321,-0.005821005029434,
-0.005835495632912,-0.005688090821732,-0.005386969969742,-0.004948402698578,
-0.004391268544832,-0.003743966181793,-0.003026453103984,-0.002259865982444,
-0.001463763987657,-0.0006720547052417,9.469626294734e-05,0.0008203270186895,
0.001493040074613, 0.002082149606443, 0.002579062725162, 0.002979428624974,
0.003281533504934, 0.003462967347778, 0.003539564797592, 0.003517760801587,
0.00338851877287, 0.003164214837755, 0.002876533604827, 0.002501813092496,
0.002085903767237, 0.001628607274255, 0.001138643754299,0.0006523796587688,
0.0001577643868071,-0.0003053610713622,-0.0007460555145065,-0.001137634776605,
-0.001481894556659,-0.001762747894781, -0.00198321289329,-0.002130544174645,
-0.002212008028482,-0.002222600479273,-0.002170534807299,-0.002055203813477,
-0.001888430504748,-0.001671996894583, -0.00141866471304,-0.001134172783683,
-0.0008320332250745,-0.0005180020684175,-0.0002059121142722,9.872454417174e-05,
0.0003852551502332,0.0006489666716781,0.0008795732861174, 0.001075239871217,
0.001229572975887, 0.001341963856305, 0.001408713236901, 0.001433556195906,
0.001415113703677, 0.001357407502196, 0.001261549186962, 0.001134430633007,
0.0009782209243579,0.0008005298221407,0.0006050358020624,0.0003997734340485,
0.0001881785279959,-2.194638011082e-05,-0.0002278010444023,-0.0004221566176204,
-0.0006023408366827,-0.0007626855367863,-0.0009024994467314,-0.001015878136264,
-0.001101740427144,-0.001156474414754,-0.001180365895233,-0.001168532570402,
-0.001120672276141,-0.001032396319006,-0.0009016784083378,-0.0007227263390531,
-0.0004926710990588,-0.000203595824125, 0.000150303226719, 0.000577314540584,
0.001086888354097, 0.001684305478472, 0.002363330670909, 0.003075252870792,
0.003625434828895, 0.003348334864088,2.597171096933e-05, -0.01361253802573,
0.004032097827315
};
后续将滤波算法部署到主控CH32V307上,具体使用的代码为:
double state[FIR_FILTER_LENGTH+1]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void process(double *x,double *y,u16 N)
{
int i = 0,j = 0,k=0,mm=0;
double temp;
for (k = 0; k < N; k++)
{
state[0] = x[k];
for (i = 0, temp = 0; i < FIR_FILTER_LENGTH; i++)
temp += FIR_COFFES[i] * state[i];
y[k] = temp;
for (j = FIR_FILTER_LENGTH - 1; j > -1 ; j--)
state[j+1] = state[j];
}
}
电压与血压之间的转化关系为(ADC与mmHg之间的转化):
double ADC_mmhg(double adc)
{
double pressure,mmhg,val_mv;
val_mv = (adc*3.3)/4096;
pressure=(40*val_mv)/2.7;
mmhg=pressure/0.13;
return mmhg;
}
5.3 MQTT通信代码及腾讯连连小程序设计
电子血压计通过MQTT协议将测量结果上传到腾讯云LoT平台,具体采用的格式为:
#define REPORT_DATA_TEMPLATE "{\\\"method\\\":\\\"report\\\"\\,\\\"clientToken\\\":\\\"00000001\\\"\\,\\\"params\\\":{\\\"pressure\\\":%d\\}}"
后续在腾讯云IoT Explorer中创建项目—创建产品—创建设备—创建数据模板,实现云端设备的对接,核心步骤如图9所示:
图9 腾讯云IoT Explorer平台端云对接的步骤
最后采用腾讯连连的默认的可视化页面模板,将测量结果进行可视化,具体如图10所示:
图10 腾讯连连可视化页面配置及结果展示
六、总结与展望
电子血压计设计过程中应该尽可能避免外界干扰,主要有:1. 压力传感器的环境适应能力(减小温度等因素造成的干扰);2. 信号调理电路的误差;3. AD采样的速率和精度;4. 血压解算程序的准确度;希望后续有时间的话对项目进行优化改进。