1 绪论1.1 课题来源及背景人类社会从猿类时代进化到现在的高科技时代,人们的生活需求也一直在改变,从对基本温饱的需求转变为现在的健康需求,正在逐步升华。2013年 11 月,有关调查报告指出:我国有近 65%的人群是处于亚健康状态的,这一特殊人群虽然没有直接表现出明确的疾病,但是他们内在活力却不断下降,长此以往,会非常容易引起各种疾病,因此,这部分人群特别需健全、便捷、舒适的家庭健康监护及医疗保健服务[1]。然而目前在医院中使用的大型医疗监护设备无法满足在家庭对这部分特殊群体的健康监测,需要开发设计一种更加舒适、便捷、廉价、人性化的智能化家庭健康监护系统来适应人们对健康监护设备的应用需求。
继互联网之后,互联网+的时代也渐渐到来,智能这个词也呗使用的越来越广泛,有关的智能技术也逐渐浮现出来,并且相当多的领域也开始使用智能技术[2]。“智能化”正在慢慢地使人们的生活健康方式发生变化。如今智能化的健康医疗产品在设计方面主要有以下两种体现:①智能化健康医疗产品在其功能上更加符合人们的需求和愿望。比如,现在的智能电子血压仪,替代了以往老式的血压仪,其体积变得更加轻盈,不仅使用场合不再受限制,而且可以随时随地的记录用户和患者自身的血压状况,可以帮助其管理自身健康和病情,并且通过最近3次血压平均值显示更精准。自动感应高度功能,正确提示使用者的测量姿势,获得准确精值。并且通过智能手机连接应用实时记录健康信息。传统的血压仪同样也运用的物理及生物技术,但与传统相比,新型智能血压仪本质性区别在于它的功能变得智能化,更加满足人们的需求,实现了血压问题患者的愿望[3]。②这类健康医疗产品的操作非常便捷,人机交互友好。友好的人机交互会给使用者带来不错的使用体验。比如,在以往的医疗环境中,化验血尿等常规检查的流程极为烦冗,而且等待的排队时间会让人失去耐心。现在医院中为患者提供的自动化验以及自动取单机,只需要把取样放到机器中,录入病例里的个人信息二维码,机器会提示过多久来取化验单。取单时只需把病例上的二维码扫入机器,单子便可轻松取出。这种智能化医疗设备不仅为患者节省了时间,同时也为医护人员减轻了很多工作负担[4]。
智能化家庭健康监护系统就是一种新型家庭医疗监护设备,将人体健康数据采集,并且具有数据交叉分析与处理以及本地健康问题咨询和云共享等多种功能,可以将传统的病人去医院就诊模式转变为客户健康信息实时上传至云端服务器,同时也会传送给手机APP,能够由医生对病人的信息进行监护和管理,主动上门就诊。
1.2 课题研究内容及结构本文设计希望通过前端硬件采集多生理参数,通过蓝牙远程传输给手机APP,从而实现对身体健康的远程监护。主要的研究工作在于对多生理参数同时采集和蓝牙传输系统的设计方法,以及对整体框架进行分析,主要从硬件系统设计和软件编程两个方面展开工作设计和开发一个智能化家庭健康监护系统。整个系统分为两个部分:一是前端硬件,进行生理参数的采集、分析处理以及远程传输;二是手机APP客户端,负责接收前端硬件采集的数据,并进行实时显示。前端硬件包括:ATMEGA2560单片机、非接触式红外测温模块、血氧饱和测量模块、BC417143B蓝牙模块、TFT液晶屏、供电系统。软件设计方面,采用C语言编写Arduino的程序,JAVA语言编写手机APP程序,实现与硬件蓝牙对接,接受数据后进行实时显示。
本文首先介绍了硬件电路设计的思路,然后详细阐明了芯片的选择及其各自的特点,也引用了部分有关该课题设计方面的基本知识。然后叙述了手机APP的编程方法和过程,使用流程图和程序代码比较直观的介绍了本设计的编程思路以及需要注意的一些问题。最后是硬件和软件测试,通过具体的测量和控制说明智能化家庭健康监护系统开发与设计的合理性和完整性。
1.3 主要创新点本课题设计主要涉及到多生理参数的同时采集以及波形的实时显示,还有硬件设备与手机APP通过蓝牙对接建立通信链路。主要创新之处有以下几点:
(1)在无线远程传输上采用2.4GHz的ZigBee模块和蓝牙模块,可以实现移动设备与前端硬件设备之间的短距离数据交换,并且在功耗方面具有极大优势,其自身具有超低功耗的特点,此外,传输数据稳定可靠,支持双向传输。
(2)实现多生理参数采集,本系统在运行时,会同时测量使用者的血氧饱和度、脉搏、体温,并且将具体的数值实时显示在液晶屏上,较为直观。另外,本系统设计为便携式,配备有可充电的移动电源,便于随身携带并使用。
2 硬件电路设计2.1 系统硬件电路构成本设计是以ATMEGA2560单片机为微处理器,与非接触式红外测温模块、血氧饱和度测量模块、蓝牙、ZigBee、液晶组成了一个集多生理参数数据采集、处理、液晶显示、无线传输、手机APP显示为一体的智能化家庭健康监护系统。系统硬件电路主要由红外测温传感器、血氧饱和度测量模块、单片机、TFT液晶显示、蓝牙传输模块和ZigBee传输模块组成。其原理图如图2.1所示:

图2.1 硬件原理构成图
生理参数采集模块中,在单片机ATMEGA2560的控制下,非接触式红外测温传感器会先采集外界的温度并经过模拟转换后通过单总线接口传输给微控制器进行判断处理,然后通过ZigBee传输模块发送数据给主板上的ZigBee协调器。血氧饱和度采集数据后通过串口传输给单片机,经过处理后数据一方面在模块上通过TFT液晶显示器进行数值和波形的实时显示,另一方面通过蓝牙无线模块发送到手机APP客户端进行显示。在APP客户端接收数据时,需要开启手机蓝牙功能,在客户端搜索附近的蓝牙设备,找到ID为BluetoothBee并输入连接密码建立通信链路。然后客户端就会收到来自前端硬件的生理参数数据,APP收到监护系统的数据后会判断该数据是否有效,若有效,则在手机屏幕上显示出来。
2.2 Arduino微处理器最小系统本设计采用的MCU是ATMEGA2560芯片。ATMEGA2560芯片适用于需要大量IO接口的设计。下面主要介绍所用芯片及相应电路设计。
2.2.1 单片机控制芯片ATMEGA2560的内部资源非常丰富,提供了大量的IO接口,包括有54路数字IO口,其中有16路可以作为PWM输出,此外,还有16路模拟采集引脚,每一路模拟输入在芯片内部为10位的A/D数据转换器,可以采集多路模拟量[5]。在通用全双工异步串行口(UART)方面,ATMEGA2560具有3路串行口可以使用,此外,还有一些引脚可以通过程序修改来实现虚拟软串口,故在串行口通信方面ATMEGA2560具有丰富的资源。
2.2.2 ATMEGA2560单片机电路设计Arduino ATMEGA2560的最小系统电路与STC系列的51单片机基本类似,对于AREF引脚,是AD转换的参考电压输入端,即模拟端口输入的电压值是与此处的参考电压相比较的,开发者可以通过改变这个引脚以及程序中的模拟电压输入设置函数,来实现测量电压范围的改变[6]。在烧写程序时,可通过RX0和TX0引脚以及GND引脚与PC机相连来实现。电路设计图如图2.2所示:

图2.2 Arduino mega2560电路设计图
2.3 蓝牙无线通信模块蓝牙通信技术是一种工作在2.4 GHz 频段的无线通信技术。目前蓝牙技术已经逐渐趋向成熟。因为蓝牙技术的日趋成熟,在使用和远程传输方面具有非常好的系统稳定性和抗干扰能力。本设计使用的蓝牙模块如下图2.3所示:



图2.3 蓝牙传输模块(图A为正面,图B为反面)
在局域网范围内,可以使用蓝牙无线传输给具有蓝牙功能的设备发送数据,并且可以实现自主组网。在本设计中,蓝牙无线通信模块采用的是BC417143B这款芯片,该芯片具有内置天线、有超低功耗模式、收发灵敏度高、成本低、低功耗等优点,而且只需配备少许外围器件就可以实现其强大的功能。
1、主要特性
蓝牙模块具有全球开放的2.4GHz ISM 频段免许可证;功率等级为Class 2,其自身为主从一体,抗干扰的能力比较优秀,因此非常适合应用在工业控制的场合;具有12路可AT命令编程的输出IO口,1路带硬件流控的UART接口,3路8位ADC输入接口,板载有蓝牙天线;无线串口数据透传,其UART兼容3.3~5V的接口,具有128-bit安全校验机制,符合ROHS等多种国际认证[7];运行在可配对连接模式时,电流最低可达3.3mA,在通讯模式下最低可达20mA;低功耗3.0 -3.6V 工作,关机模式下为29uA;
2、开发方式
蓝牙模块的开发方式分为2两类:一类是基于TI公司的CC2560双模蓝牙的协议栈开发,即在TI公司开放的蓝牙协议栈上做二次开发;一类是基于蓝牙透传模块的AT指令开发,这类开发相较前者而言难度稍微小一点,是使用串口与蓝牙通信,通过发送AT指令的方式来对蓝牙模块进行配置以及相关的控制功能。
本设计采用的蓝牙芯片是BC417143,支持蓝牙2.0版本的标准协议,默认波特率为9600b/s。蓝牙芯片与另外一个蓝牙设备可以进行远程无线通信,同时,蓝牙芯片也可以通过串口与单片机进行通信,单片机可以通过串口通信的方式用AT指令控制蓝牙芯片。
2.4 ZigBee无线通信模块ZigBee是一种低功耗局域网通信协议。该名字是源自蜜蜂的八字舞,蜜蜂之间是通过飞行和嗡嗡抖动自己的翅膀来与同伴进行沟通交流的。ZigBee技术的突出特点是复杂度较低、自组网、超低功耗、低成本,非常适用于蜂窝网中的远程信息传输与自动控制,这种协议也可以嵌入各种MCU中进行使用。
本设计采用的ZigBee芯片为CC2530芯片,内嵌有标准ZigBee协议栈,在芯片内部集成了8051内核,是增强型的51单片机。在ZigBee网络中,所有的节点设备分为3种类型,一种是协调器,一种是路由器,一种是终端。在同一个网络中,需要一个协调器来启动并维护整个网络,这个协调器负责所在网络中的各个节点设备的16位地址分配(为自动分配)[8]。路由模块的作用是在协调器模块启动后,协助其维护整个网络中的设备,同时,路由模块也可以作为信息传递的中转站,使得信息传递的距离更远。而终端设备即处于网络边缘的设备,一般用于控制器,执行来自路由器或协调器的命令。
ZigBee网络的组建方式各种各样,有星状,网状,树状等等。星状网络,是以协调器为中心,向四周发散开来,连接路由设备或者终端设备。网状网络,是由协调器、路由器组成的一个类似蜘蛛网般的网状网络,路由与协调器之间可以互发互收数据。
本设计使用的ZigBee模块为无线透传模式,通过软件配置模块的PAN ID,即网络号,用于分辨不同的网络,所以在同一个网络中的设备的PAN ID需要设置为同一个ID[9]。其次,需要设置ZigBee的串口通信波特率,用于与外部单片机的通信。ZigBee模块的实物图如下图2.4所示:
图2.4 ZigBee模块的实物图(图A为正面,图B为反面)
每个ZigBee模块在出厂时,就有一个终身属于它的64位地址,例如这个ZigBee模块的唯一64位地址为0x0013a20040e830dd,这个唯一地址可以用于在一个网络中的唯一识别,也可以作为数据接收终端地址。
2.5 红外测温模块MLX90614是一个应用于非接触式的红外温度传感器,其集成了红外探测热电堆芯片与信号处理专用集成芯片,且全部都封装在TO-39。17位ADC、低噪声放大器和强大的DSP处理单元的全集成,使传感器实现了高分辨率,高精度的测量。处理好的被测目标温度和环境温度均存储在MLX90302的RAM内,分辨率为0.01 ˚C。传感器的测量结果均出厂校准化,数据接口为数字式的PWM和SMBus(System Management Bus) 输出。传感器出厂默认,上电复位时为SMBus通信[10]。
对于MLX90614芯片而言,引出了4个引脚,它们分别为VSS、SCL/Vz、PWM/SDA、VDD。接地端为VSS,接地端也与金属封装连通,使得信号更好,SCL/Vz是SMBus串行时钟的输入端。 VDD为电源的输入端。
对于脉宽调制,PWM的数位带宽为10bit,PWM的输出周期为1.024ms,输出高电位电压值时,I=2mA,输出低电位电压值时,I=2mA,输出驱动电流为7mA,输出反向电流为13.5mA。对于SMBus标准双线的参数如下表2.5所示:
表2.5 SMBus标准双线的参数
在自然界中,通过对某物体自身的红外辐射收集并测量可以较精确的得出该物体的体表温度。本设计使用的红外测温模块由光电探测器、光学系统、信号处理和信号放大器及输出等部分组成。红外测温的原理大致如下图2.6所示:

图2.6 红外测温原理图
MLX90614系列测温模块是由Melexis公司生产的,用于非接触式红外测温非常方便。这家公司生产的所有模块在出厂前都进行了必要的校验,使得红外测温模块可以直接输出线性信号,免去了复杂的校正过程。
环境温度和目标温度由81101内置的一个热电偶测定测量,两路温度信号经由放大器放大后,再由一个17-bit的模数转换器和较强大的数字信号处理单元后输出。
MLX90614的SMBus协议:
1 7 1 1 8 1 1
S Start condition(起始位)
Sr Repeated start cordition(重复起始位)
Rd Read(读标志位)
Wr Write(写标志位)
A Acknowledge(应答位)
S Stop Condition(停止位)
PEC Packet Error Code(出错数据包)
数据传输时序图入下图2.7所示:

图2.7 数据传输时序图
PWM/SDA为数据脚,若数据脚需要变化,将SCL引脚拉低300ns之后即可。而数据被捕获需要在SCL为上升沿的时刻。数据传输时,16bit数据需分两次传输,每个字节均按照高位(MSB)在前,低位(LSB)在后的顺序传输。
2.6 血氧饱和度传感器2.6.1血氧饱和度测量原理血氧饱和度在进行测量时,使用两个发光二极管,发射的波长分别为660nm和940nm,在手指的上下两端分别放置发射管和接受管。发射管发射的光波透过手指后会在另一端被接受管接受,因为人体的内部组织对于这种光的吸收系数是恒定的,所以此时的光波会有一定的衰减,通过衰减程度再配合一定的计算方法,我们便可以得出测量者的血氧饱和度为多少,如图2.8所示

图2.8 血氧饱和度测量原理
2.6.2 血氧饱和度探头血氧饱和度探头是测定人体血液中的氧浓度即血氧饱和度的一种仪器,传感器由两只发光管和一只光电管组成,在外科手术或危重病人的监护中可及时了解血液中氧含量。
在本设计中发射管采用的是660~905nm波长的发射管,接收管为235。这种血氧饱和度探头为数字血氧探头,其传输出来的信号为数字信号[11]。在采集模块上,使用了一块STM32核心芯片进行初步的采集以及处理,然后通过UART接口与atmega2560芯片相连,将数据传输过去,由atmega2560进行下一步的处理。其中数据传输协议入下表2.5.2所示:
与单片机进行数据传输时是默认设置:波特率为9600b/s;每秒发送50个数据包,每个数据包含有5个字节。
字节0:
字节1:
字节2:
字节3:
字节4:
2.7 SD卡存储模块SD卡即安全数码卡,是继MMC之后发展的一种快闪记忆器的新一代记忆设备,目前已经被广泛应用在许多设备上。SD卡拥有大容量、速数据传输快、移动灵活性强以及高安全性等优点。
SD卡使用的电压为3.3V。同时,若在SPI模式下,需要注意的是,SPI通信的引脚均需要外加10~100K左右的上拉电阻才能保证其正常工作[12]。
SD卡有5个寄存器,如下表2.9所示:
表2.9 SD卡寄存器
操作SD卡的6条重要命令:
SD卡初始化过程:
- 初始化与SD卡连接的硬件条件;
- 上电延时;
- 复位卡,进入IDLE状态;
- 发送CMD8,检查是否支持2.0协议;
- 根据不同协议检查SD卡;
- 取消片选,发送多于8个CLK,结束初始化;
SD卡读取数据:
- 发送CMD17;
- 接收卡响应R1;
- 接收数据起始令牌0XFE;
- 接收数据;
- 接收2个字节CRC,若不用CRC,这两个字节在读取后可丢掉;
- 禁止片选,发多于8个CLK;
SD卡存储数据:
- 发送CMD24;
- 接收卡响应R1;
- 发送写数据起始令牌0XFE;
- 发送数据;
- 发送2字节的伪CRC;
- 禁止片选,发多于8个CLK;
在本设计中,由ATMEGA2560采集血氧饱和、脉率、体温的数据,进行处理后,在每次测量完毕后,这些数据会以TXT文件存储到SD卡中,便于之后的数据分析。
3 系统软件编程设计3.1 软件开发环境3.1.1 Arduino IDE简介Arduino是一款基于ATMEL AVR单片机的控制器平台,便捷灵活而且较为容易上手。Arduino是一个开源的系统,除了不能使用Arduino作为商标,任何人或公司都可以利Arduino公布的文档来制作属于自己的电子物品,而且Arduino的价格低廉,非常受国内外广大的电子爱好者欢迎[13]。
Arduino具有特定的标准扩展口,可以在扩展口上使用各种传感器来采集或控制周边事物,例如窗帘上的步进电机、房间的照明灯、室温等等[14]。这款芯片可以通过Arduino特有的API(应用程序编程接口)函数来编写自己的程序。编译生成二进制文件,烧录编译文件都可以使用Arduino IDE软件完成[15]。
Arduino IDE的编程界面如下图3.1所示:
Arduino IDE的编程方式与51单片机是相似的。在软件编程界面有两个空的函数:void setup()和void loop(),前者中需要填写程序的初始化部分,后者为整个程序的主循环内容[16]。编写完程序后,就要进入下载部分。Arduino的核心板具有ISP功能。这个功能可以在不改变硬件连接,即使硬件仍然在运行内部代码时,不需要分离任何电路也可以立即下载新的程序代码,这样就可以节省很多开发时间[17]。在Arduino的芯片内部都有一个bootloader,这个bootloader可以帮助MCU加载程序,当单片机在复位时,首先会跳转到bootloader中判断之后进入的数据是否属于程序代码,若为程序代码就将其安置到内存的剩余空间中。所以因为有bootloader的存在,使得Arduinod 程序代码非常便于下载[18]。

图3.1 Arduino IDE界面
3.2 软件各模块程序设计3.2.1 血氧饱和及心率数值采集 血氧饱和度测量模块在采集到血氧数值后,会通过串口(UART)的方式发送给单片机,其格式在上文已经有过介绍,血氧模块回以每秒50个数据包的速度发送数据,每个数据包包含有5个字节的数据,其中有3个字节的数据是我们所必须的,一个字节是探头监测位,需要通过判断这个位的数据来判断传感器是否连接成功[19];一个字节是血氧饱和度的数值,共有8位,将这8位2进制数值转换成10进制的数值,即血氧饱和度的数值;一个字节是描述心率的数值,与血氧饱和度一样,将二进制转换为10进制即可显示出来。所以在单片机处理时,需要定义一个数组来存储我们所需的字节[20]。
3.2.2 体温温度数值采集非接触式红外温度传感器是采用的SMBus协议进行读取、写入数据操作的。
读器件的数据格式(命令决定是读RAM或EEPROM)如下图3.2所示:
图3.2 读数据格式
写器件的数据格式(命令决定是写RAM或EEPROM)如下图3.3所示:
图3.3 写数据格式
在主程序中调用函数readObjectTempC();即可读取温度的数值。
3.2.3 蓝牙无线通信本设计使用的蓝牙通信模块为AT指令开发,可以通过AT指令修改串口通信的波特率,设置配对码等。具体的AT指令如下:
1、设置和查询配对码:
AT+PSWD = <Param>
Param: 配对码
2、设置和查询串口参数:
AT+UART = <Param1>,<Param2>,<Param3>
Param1:波特率(bits/s)
Param2:停止位
Param3:校验位
3、设置和查询模块角色:
AT+ROLE = <Param>
Param :0——从角色(slave),被动连接,可以与任何蓝牙适配器连接通信
1——主角色(master),主动连接,建立通信数据传输通道
2——回环角色(slave--loop),被动连接,接收主设备发送数据并返回给主设备
在进行程序设计之前可以先通过AT指令将模块的参数配置完成,然后在程序中设置好波特率后即可直接使用串口发送函数,将数据通过串口发送给蓝牙模块,然后蓝牙模块会自动再将数据远程发送给手机APP端[21]。
整个系统的程序设计流程图如下图3.4所示:
图3.4 系统程序设计流程图
3.2.4 ZigBee无线通信本设计使用的局域网无线通信模块为美国DIGI的一种ZigBee通信模块,其内置有ZigBee协议栈,可以使用DIGI提供的X-CTU软件通过AT指令的方式配置ZigBee模块的相关参数,包括通信波特率、运行模式(协调器或路由或终端)、网络ID、发送数据的目的地址等等[22]。
X-CTU软件可以配置ZigBee模块,界面如下图3.5所示:
图3.5 X-CTU界面
左上角的两个按钮用于发现设备,将ZigBee模块通过串口与电脑端连接后,即可使用该功能发现设备进行下一步的配置,MAC寻找界面如下图3.6所示:
图3.6 MAC寻找界面
在这个界面读出模块后,会显示一些基本参数,比如此串口号和模块的64为地址。然后点击Add selected devices,即可进入参数读取/配置界面,如下图3.7所示:
图3.7 读取/配置参数界面
在设置参数时,主要设置以下参数:首先为模块波特率,用于与单片机之间的通信,本设计中设置为115200;然后设置PAN ID,这个ID用于加入网络,当多个ZigBee模块的PAN ID相同时,便能实现自组网,形成局域网络进行通信;最后为发送数据的目的地址,在本设计中,是终端设备发送数据给协调器,故在终端设备中需要设置协调器的64位唯一地址[23]。也可以在协调器上设置终端的64位唯一地址,使用协调器给终端发送数据。
3.3 Android监护软件设计3.3.1 系统的开发环境与安装本设计开发android程序是采用的eclipse环境,eclipse编译器是一款比较强大的APP开发软件,相较其他的开发平台而言,具有比较大的优势,比如界面的操作简单,在编写程序的过程中可以非常清晰、直观地发现问题[24]。
开发android软件是采用的eclipse软件,安装时,先在官网eclipse.org中下载安装包,分为32位与64位,注意要与电脑配置一致。下载完安装包后,解压并运行eclipse.exe[25]。现在首先需要安装java环境,第一要设置工作环境,选择你希望安装的盘,点击OK。如下图3.8所示:

图3.8 设置工作环境
然后创建项目,选择file->new->java project,如下图3.9所示:
图3.9 创建项目
键入项目名,点击finish。完成项目创建后,点击Java按钮,然后在菜单的左侧选择test项目,右键点击new->class,键入工程名,完成。最后在代码框中就可以开始敲代码开发了。
3.3.2 Android应用程序开发过程Android应用程序的设计分为以下几个过程:在程序运行时,会开启一个主线程,用于主界面的显示,然后需要搜索手机附近开启的蓝牙设备,搜索到相关的蓝牙设备后即可连接,在连接时会开启一个子线程用于socket连接。当建立与设备的连接后,会不断接收来自前端蓝牙设备发送的多参数生理数据值,每次接收到数据后,程序会首先判断该数据是否为有效数据,若是,则在屏幕上显示出来,若不是,则继续监测数据。
程序设计的流程图如下图3.10所示

图3.10 APP程序流程图
3.3.3 主要应用模块的实现首先进入APP界面后,会进行一系列的初始化过程,进入界面后会有一个搜索按钮,用于发现周围的可连接蓝牙设备。
点击搜索按钮后,在界面会出现一个设备列表,用于展现发现的所有蓝牙设备,此时,选择我们的前端蓝牙设备“BluetoothBee”,进行连接,连接过程是一个基于socket通信的连接,因为其相对来说耗时较长,故不能运行在主线程,所以开辟了另外一个子线程供手机与蓝牙设备进行连接。当手机APP与前端蓝牙设备建立连接后,即可开始读取数据。
读取完数据后需要进行解析数据,然后会在界面上显示相应的生理参数。
手机APP的界面以及生理参数数值显示实物图如下图3.11:
图3.11 APP界面
在APP客户端显示的数据都是根据主控板采集的数据实时变化的,可以方便使用者非常直观的看到自己的生理参数数值。
4 系统整体功能测试4.1 智能化家庭健康监护系统实物图智能化家庭健康监护系统是一个便携式的多生理参数实时监测系统,在整套系统中包含有主控板ATMEGA2560、Arduino模块、血氧饱和度测量模块、红外测温模块、蓝牙传输模块、ZigBee无线传输模块、TFT液晶屏、充电模块、升压模块、充电电池。在实际使用时,进行血氧饱和度、心率、体温的参数测量,并且每次测量时都会将数据实时传入手机APP端进行显示,可以让使用者很直观的看到测量的具体参数。对于电源,采用的是充放电电池,并设计有充电电源口,当电池电量不足时可以通过这个接口充电,使用起来非常方便。具体的实物图如下图4.1所示:
图4.1 系统整机图
对于红外测温模块,在另外一个节点设备上,打开电源后,模块会自动采集目标体温,然后通过ZigBee模块传输给主系统板上的ZigBee协调器,实物图如下图4.2所示:

图4.2 红外测温从机图
在进行测量的时候,按下电源开关,然后手指戴上血氧探头,几秒钟过后,即可同步成功,然后在液晶屏上面会有血氧的波形图和血氧值、心率值、体温值的显示。在TFT液晶屏上的效果图如下图4.3所示,屏幕上方左边为BMP(心率),中间为SPO(血氧饱和度),右边为TEMP(体温):
图4.3 TFT液晶屏显示
在手机APP上的显示界面如下图4.4所示,手机通过蓝牙接收到的数据在屏幕上进行显示,包括心跳、血氧、体温的具体数值,并根据前端设备的实时采集进行更新:
图4.4 实测效果图
总结与展望本课题设计的智能化家庭健康监护系统采取了硬件与软件相结合的开发方法。在整个设计的过程中需要我对单片机开发、PCB绘制调试、C/C++编程语言、JAVA语言都有一定程度的了解。与此同时,需要学会查找相关的资料文件,熟悉各个芯片的开发使用方法以及它们的电气特性等等,这些资料对于开发者来说,是非常重要的第一步。整个课题设计的过程也同时是我再次学习、巩固、加深的过程,对“温故而知新”这句话也有了更深一步的理解。我们只有在不断学习,不断巩固,不断思考,才能不断进步,掌握的知识技能才能越来越牢靠,并且在实践过程中需要我们本着实事求是的心态去做事,善于发现并解决问题,有意识培养自己解决问题的能力,为今后的学习和工作打下良好的基础。
作者在最初进行本课题的设计时遇到了很多的艰难困阻。首先是血氧饱和度的数据一直无法同步,因为单片机无法采用串口中断的方式,所以一直是采用的串口查询的方式来接收数据,这就导致时不时会丢包,而不能完全同步。其次,在单片机设计方面,没有接触过TFT液晶屏的开发,所以当采集到生理数值时,需要在液晶屏上显示出具体数值,同时还需要实时绘制血氧饱和度的波形,这一部分在程序设计上也花费了很大精力才得以解决。再就是android APP开发方面,因为作者一直都是使用C语言开发单片机程序,而完全没有接触过软件APP的开发,所以从零开始学习java语言,了解并熟悉eclipse开发环境也是难点之一。
本文在设计上有两大特点:一是采用主从一体的蓝牙传输模块进行远程的数据传输。这种无线通信方式是使用的很频繁,也深受大众喜爱的一种通信方式,其使用起来非常便捷,而且传输数据稳定可靠,同时还具有低功耗模式,适用于便携式设备。二是系统采集的多生理参数除了会在设备本身的TFT液晶屏上显示出来,还会通过蓝牙将数据发送给APP客户端,在手机上进行实时的显示。
最后,本文虽然实现了智能化家庭健康监护系统的生理参数采集、显示、无线传输功能,但仍然存在很多问题有待改进,而且在功能上还有很多是可以继续完善的。在生理参数采集部分,可以加入心电的采集、分析,在无线传输部分可以使用WIFI或其他可以接入互联网的设备,让前端系统采集的生理数据能够传输到云端服务器,与医院进行合作,使医院的主治医师能够查看我们的生理数据,从而能够在日常饮食或生活习惯上给予适当的建议,使得全社会人的身体都能够更加健康。在系统的供电部分可以设计的再微小点,不用占据很大的空间,同时也能提供足够的电量。通过上述改进措施,此智能化家庭健康监护系统将会具备更加强大的实用价值以及商业价值。
参考文献[1] 刘翔, 朱士俊, 李信春. 我国远程医疗发展现状、难点和对策分析[J]. 中国信息界, 2006(4):60-63.
[2] 吴明, 张振忠. 中国农村合作医疗发展模式的制度分析[J]. 中国卫生资源, 2000(3):104-107.
[3] 邬宽明. 单片机外围器件实用手册--数据传输接口器件分册(第2版)[M]. 北航大学出版社, 2005.
[4] 刘坤, 赵红波, 张宪栋. 51单片机C语言应用开发技术大全[M]. 人民邮电出版社, 2011.
[5] 陆垂伟, 毛雪涛, 戴翔宇,等. 远程串行数据通信技术的实现方法及其应用[J]. 计算机应用研究, 2002, 19(3):23-24.
[6] 石东海. 单片机数据通信技术从入门到精通[M]. 西安电子科技大学出版社, 2002.
[7] 高潮. TFT液晶显示驱动电路与电源优化设计方法[J]. 深圳信息职业技术学院学报, 2007, 5(2):14-18.
[8] 原羿, 苏鸿根. 基于ZigBee技术的无线网络应用研究[J]. 计算机应用与软件, 2004, 21(6):89-91.
[9] 屈景辉 李传伟. TEECHART应用技术详解--快速图表制作工具[M]. 水利水电出版社, 2008.
[10] 缪璐璐. 基于Arduino平台开发交互式产品原型的研究[D]. 上海交通大学, 2013.
[11] 惠特. Arduino技术内幕[M]. 人民邮电出版社, 2013.
[12] 李莉, 刘刚. 基于蓝牙技术的温室环境监测系统设计[J]. 农业机械学报, 2006, 37(10):97-100.
[13] 龚建伟. Visual C++/Turbo C 串口通信编程实践[M]. 电子工业出版社, 2004.
[14] 何希才. 数字移动通信技术及应用[M]. 机械工业出版社, 2003.
[15] 钟君, 蔡黎明, 于涌. 基于MLX90614的无线温度采集系统设计[J]. 传感器与微系统, 2015, 34(3):87-89.
[16] 封瑜, 葛万成. 基于ZigBee技术的无线传感器网络构建与应用[J]. 电子工程师, 2007, 33(3):21-23.
[17] 许一萍. Zigbee技术在无线传感器网络中的应用研究[D]. 复旦大学, 2008.
[18] 张利江, 郭进利, 宋亚娟. 远程医疗监护的现状与发展[J]. 新农村:黑龙江, 2011(2):138-139.
[19] 诸强, 王学民, 胡宾,等. 无线远程医疗系统[J]. 北京生物医学工程, 2004, 23(3):225-227.
[20] 张利江, 郭进利, 宋亚娟. 远程医疗监护的现状与发展[J]. 新农村:黑龙江, 2011(2):138-139.
[21] 范晓武. 基于嵌入式设备的家庭健康监护系统的设计与实现[J]. 浙江工业大学学报, 2010, 38(3):289-293.
[22] Roll J S, Froma W. Systemic training for healthcare professionals: the Chicago Center For Family Health approach.[J]. Family Process, 2005, 44(3):283-301.
[23] Heydon A, Mcdonald J. Measurement of family health teams is underdeveloped.[J]. Sedimentology, 2011, 183(14):1628-1628.
[24] 朱新建, 吴宝明, 卓豫,等. 多参数家庭健康监护实时检测的方法[J]. 中国组织工程研究与临床康复, 2007(1):121-123.
[25] 黄永健, 王伟, 谢广明,等. 物联网家庭健康监护系统[J]. 兵工自动化, 2013(11):87-90.
附录A
1. 主控板程序:
- #include <UTFT.h>
- #include <SPI.h>
- #include <SD.h>
- #include <SoftwareSerial.h>
- #include <Wire.h>
- #include <Adafruit_MLX90614.h>
-
- Adafruit_MLX90614 mlx = Adafruit_MLX90614();
- SoftwareSerial mySerial(6, 7);
-
- // Declare which fonts we will be using
- extern uint8_t SmallFont[];
- UTFT myGLCD(QD220A,A2,A1,A5,A4,A3); //初始化液晶的类
- File myFile; / /初始化SD卡的类
- extern uint8_t BigFont[];
- int data[5];
- char str[9];
- int buf[220],buf1[4];
- int y1=0; //判断是否为第一次画线
- int y2=45;
- int x=1, x2=0;
- int r=0,time=0;
- long a=0,t1=0;
-
- void setup()
- {
- myGLCD.InitLCD(); //液晶屏初始化
- myGLCD.setFont(SmallFont); //设置液晶屏上字的大小
- Serial.begin(9600); //ZigBee波特率
- Serial1.begin(9600); //调试串口
- mySerial.begin(115200); //血氧饱和度通信
- mlx.begin(); //初始化红外测温模块
-
- myGLCD.fillScr(255,255,255); //清屏
-
- if (!SD.begin(53)) { //检测SD卡是否读取成功
- return;
- }
- myFile = SD.open("SPO2.txt", FILE_WRITE);
- myGLCD.setColor(0,255,255); //设置字体颜色
- myGLCD.setBackColor(255, 0, 0); //设置背景颜色
- myGLCD.print("BMP:", 5, 1);
- myGLCD.print("SPO:", 70, 1);
- myGLCD.print("TEMP:", 130, 1);
- }
-
- void loop() {
- if (Serial1.available()){ //采用循环查询方式检测串口是否有数据
- for(int i=0;i<5;i++){ //采用for循环连续读取5个字节数据
- data[i] = Serial1.read(); //读一个字节数据
- delay(1);
- }
- }
- Serial.println(data[4]);
- if(data[3]<120&&data[3]>50){ //判断数据是否已经同步,为有效数据
- y1=data[1];
- if(a==1){ //若满屏,则开始清理历史数据,即消除部分波形
- myGLCD.setColor(255,255,255);
- if(t1==1){
- myGLCD.drawLine(1,135-buf[209],2,135-buf[1]); //第一次画波形,两点连线
- t1=0;
- }
- myGLCD.drawLine(x+1,135-buf[x],x+2,135-buf[x+1]); //两点连线,绘制波形
- }
- if(x<210){ //若没有满屏,则继续绘制波形
- myGLCD.setColor(0,255,255);
- myGLCD.drawLine(x,135-y2,x+1,135-y1);
- y2=y1;
- buf[x]=y1;
- x++;
- time++;
- }else{
- x=1;a=1;t1=1;
- }
- }
- if(time==100){
- myGLCD.setBackColor(255, 0, 0);
- String b = (String)data[3];
- myGLCD.print(b, 35, 1); //在液晶屏上显示心率的数值
- b = (String)data[4];
- myGLCD.print(b, 100, 1); //在液晶上显示血氧饱和度的数值
- b = (String)mlx.readObjectTempC();
- myGLCD.print(b, 168, 1); //在液晶上显示温度的数值
- delay(20);
- mySerial.print(data[3]); //通过串口发送将心率的数值发送给蓝牙
- mySerial.print(",");
- mySerial.print(data[4]); //将血氧饱和度的数值发送给蓝牙
- mySerial.print(",");
- mySerial.print(b); //将体温的数值发送给蓝牙
- mySerial.print(" ");
- time=0;
- }
- }
- 2. 红外测温读取数据部分代码:
- #define MLX90614_TOBJ1 0x07
-
- uint16_t read16(uint8_t a)
- {
- uint16_t ret;
- uint8_t pec;
- Wire.beginTransmission(_addr); // 开始发送数据给设备
- Wire.write(a); // 发送寄存器地址给传递参数
- Wire.endTransmission(false); // 结束数据传送
- Wire.requestFrom(_addr, (uint8_t)3);// 发送读取的n字节数据
- ret = Wire.read(); // 接受数据
- ret |= Wire.read() << 8; // 接受数据
- pec = Wire.read();
- return ret;
- }
- float readTemp(uint8_t reg)
- {
- float temp;
- temp = read16(reg);
- temp *= .02;
- temp -= 273.15;
- return temp;
- }
- double readObjectTempC(void)
- {
- return readTemp(MLX90614_TOBJ1);
- }
-
- 2. APP客户端初始化代码:
- private void init() {
- list = new ArrayList<SiriListItem>();
- mAdapter = new ChatListAdapter(this, list);
- mListView = (ListView) findViewById(R.id.list);
- mListView.setAdapter(mAdapter);
- mListView.setFastScrollEnabled(true);
- mListView.setOnItemClickListener(mDeviceClickListener);
-
- IntentFilterdiscoveryFilter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
- this.registerReceiver(mReceiver, discoveryFilter);
- // Register for broadcasts when discovery has finished
- IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- this.registerReceiver(mReceiver, foundFilter);
-
- Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
- if (pairedDevices.size() > 0) {
- for (BluetoothDevice device : pairedDevices) {
- list.add(new SiriListItem(device.getName() + "\n" + device.getAddress(), true));
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(list.size() - 1);
- }
- } else {
- list.add(new SiriListItem("没有设备已经配对", true));
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(list.size() - 1);
- }
-
- seachButton = (Button)findViewById(R.id.start_seach);
- seachButton.setOnClickListener(seachButtonClickListener);
-
- serviceButton = (Button)findViewById(R.id.start_service);
- serviceButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- Bluetooth.serviceOrCilent=ServerOrCilent.SERVICE;
- Bluetooth.mTabHost.setCurrentTab(1);
- }
- });
- }
- 3. 发现蓝牙模块:
- private OnClickListener seachButtonClickListener = new OnClickListener() {
- public void onClick(View arg0) {
- if(mBtAdapter.isDiscovering())
- {
- mBtAdapter.cancelDiscovery();
- seachButton.setText("重新搜索");
- }
- else
- { list.clear();
- mAdapter.notifyDataSetChanged();
-
- Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
- if (pairedDevices.size() > 0) {
- for (BluetoothDevice device : pairedDevices) {
- list.add(new SiriListItem(device.getName() + "\n" + device.getAddress(), true));
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(list.size() - 1);
- }
- } else {
- list.add(new SiriListItem("No devices have been paired", true));
- mAdapter.notifyDataSetChanged();
- mListView.setSelection(list.size() - 1);
- }
- /* 开始搜索 */
- mBtAdapter.startDiscovery();
- seachButton.setText("停止搜索");
- }
- }
- };
-
- 4. 连接蓝牙模块
- // 开启客户端
- private class clientThread extends Thread {
- public void run() {
- try {
- // 创建一个Socket连接:只需要服务器在注册时的UUID号
- socket = device.createRfcommSocketToServiceRecord(UUID
- .fromString("00001101-0000-1000-8000-00805F9B34FB"));
- // 连接
- Message msg2 = new Message();
- msg2.obj = "请稍候,正在连接服务器:" + Bluetooth.BlueToothAddress;
- msg2.what = 0;
- LinkDetectedHandler.sendMessage(msg2);
-
- socket.connect();
-
- Message msg = new Message();
- msg.obj = "已经连接上服务端!可以发送信息。";
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg);
- // 启动接受数据
- mreadThread = new readThread();
- mreadThread.start();
- } catch (IOException e) {
- Log.e("connect", "", e);
- Message msg = new Message();
- msg.obj = "连接服务端异常!断开连接重新试一试。";
- msg.what = 0;
- LinkDetectedHandler.sendMessage(msg);
- }
- }
- };
-
- 读取数据:
- // 读取数据
- private class readThread extends Thread {
- public void run() {
- byte[] buffer = new byte[1024];
- int bytes;
- InputStream mmInStream = null;
- try {
- mmInStream = socket.getInputStream();
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- while (true) {
- byte[] buffer1 = new byte[128];
- int count;
- try {
- count = mmInStream.read(buffer1);
- Message msg = new Message();
- msg.obj = new String(buffer1, 0, count, "UTF-8");
- msg.what = 1;
- LinkDetectedHandler.sendMessage(msg);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
- 6. 解析并显示数据:
- public void setdata(String string)
- {
- String[] s = string.split(",");
- int s_0 = 0, s_1 = 0, s_2 = 0;
-
- if (s.length == 3 && s[0] != null && !s[0].equals("")
- && s[1] != null && !s[1].equals("") && s[2] != null
- && !s[2].equals("")) {
- s_0 = Integer.parseInt(s[0].trim());
- s_1 = Integer.parseInt(s[1].trim());
- double d = Double.parseDouble(s[2]);
- s_2 = (int)d;
- }
- if (s.length == 3 && s_0 > 49 && s_0 < 121 && s_1 > 94 && s_1 < 100
- && s_2 > 20 && s_2 < 40) {
- chat_textview.setText("心跳:" + s[0] + "\n血氧:" + s[1] + "\n体温:"
- + s[2]);
- }
- }
复制代码