嵌入式课程设计——智能输液监控系统
1 功能需求
1.1 系统背景
随着医疗设备的更新,大多数医院已实现了智能化输液,但也存在很多医院或输液室仍靠人力,目前主要依靠呼叫系统或人工处理输液报警问题,极有可能出现因换药、拔针不及时等而引起的医疗事故。
智能输液监控系统主要应用在医院等输液场所,可减轻了医护人员的工作压力,病人以及家属不必时时刻刻盯着输液瓶,也避免了因肉眼观察不出而导致的医疗事故,及时提醒用户,降低医疗事故几率,可极大的方便病人与其家属和医护人员。
1.2 功能介绍
在输液中会出现的问题有:液滴速度过快或过慢;输液结束但没有人来拔针;出现回血情况;液滴温度过凉,流入身体不适。针对这些问题我们进行了设计。
系统主要提供以下四大功能:
1、滴度监测与调控
监测液滴速度,并显示在显示屏上。速度过快或过慢都会发出报警信息提醒用户,用户可按键调节,自动加快或减慢。
2、少液检测
当液体液面低于一定程度时,发出报警信息,提醒用户换水或拔针。
3、回血检测
靠近扎针处,若出现回血情况,迅速夹紧输液管,并发出警报信息,提醒医护人员前来处理。
4、智能加热
监测液体温度,若温度过低,自动开启加热功能,确保液体以较温和的温度流入体内。
2 硬件平台选型与设计
2.1 器件选型
主控芯片: STM32F103ZET6
红外对管、DHT11、LCD1602A显示屏、步进电机、继电器、微动开关、LED灯、蜂鸣器、电阻、电容等。
2.2 主要模块介绍
红外对管:
红外对管是红外线发射管与光敏接收管配合在一起使用时候的总称。
光敏接收管:它是一个具有光敏特征的PN结,具有单向导电性,因此工作时需加上反向电压。无光照时,有很小的饱和反向漏电流(暗电流)。此时光敏管不导通。当光照时,饱和反向漏电流马上增加,形成光电流,在一定的范围内它随入射光强度的变化而增大。
红外线接收管:功能与光敏接收管相似只是不受可见光的干扰,只对红外线有反应。外线接收头:就是在红外线接收管的基础上进行放大的信号的作用,类似与三极管的放大效果。
DHT11:
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。
LCD1602A显示屏:
它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。
用LCD显示一个字符时比较复杂,因为一个字符由6×8或8×8点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为“1”,其它的为“0”,为“1”的点亮,为“0”的不亮。这样一来就组成某个字符。但由于内带字符发生器的控制器来说,显示字符就比较简单了,可以让控制器工作在文本方式,根据在LCD上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。
步进电机:
步进电机又称为脉冲电机,是一种将电脉冲转化为角位移的执行机构,基于最基本的电磁铁原理,它是一种可以*回转的电磁铁,其动作原理是依靠气隙磁导的变化来产生电磁转矩。 当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;同时也可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。
继电器:
继电器是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
2.3 引脚划分
2.4 部分电路
红外对管接入电路
微动开关接入电路
LED灯接入电路
2.4 模块与使用
2.4.1 滴速监测与调控
模块:红外对管、LCD1602A显示屏、步进电机、微动开关、LED灯、蜂鸣器。
①采用红外对管,发射管发射红外光线,接收管接收,如果在其中间有遮挡,发射管无法接收红外光线,此时会产生电平变化。
②定时器输入捕获,计算相邻两液滴的时间差t,根据公式v=60/t+1计算出液滴速度为v 滴/秒,为减少误差,将连续采集三次相邻液滴时间差,计算平均值代入公式。
③连接LCD1602A显示屏,实现显示功能。速度过快或过慢都会进行报警,蜂鸣器响、不同颜色的灯亮起。
④用户手动按下相应按键,输液装置顶部安装电机装置,按键直接控制电机正转、反转来改变液瓶的位置,进而改变速度。
2.4.2 少液检测
模块:红外对管、蜂鸣器、LED灯、微动开关
当液面下降到一定高度时,红外对管间接收信号发生改变,会产生报警信息,蜂鸣器响起,对应的LED灯亮起。
2.4.3 回血检测
模块:红外对管、蜂鸣器、LED灯、微动开关
当出现回血情况时,红外对管间接收信号发生改变,驱动相应模块加紧液滴管,同时产生报警信息,蜂鸣器响,对应的LED灯亮起。
2.4.4 智能加热
模块:DHT11温湿度模块、继电器、LED灯、微动开关
监测温度,较低会自动驱动继电器,连接加热片开始加热,到合适的温度后自动关闭。也可手动进行加热,按下按钮即可。加热过程中,加热提示灯会亮起。
2.5 系统实物展示
3 软件系统设计与展示
3.1 软件工具
Keil uVision5(编写程序)、mcuisp(串口下载软件)、野火串口调试助手
3.2 系统设计
本系统采用模块化设计。主控模块下划分若干子模块。
系统模块图
检测模块示意图
3.3 关键代码展示
中断相关:
//按键1按下-————电机正转,液瓶下降、滴速减慢
void KEY1_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET)
{
Motorcw_angle(360,300);
Motorcw_angle(360,300);
Motorcw_angle(360,300);
//清除中断标志位
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
//按键1按下-————电机倒转,液瓶上升、滴速加快
void KEY2_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET)
{
Motorccw_angle(360,300);
Motorccw_angle(360,300);
Motorccw_angle(360,300);
//清除中断标志位
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
//关警报——蜂鸣器与警报灯、关加热
void KEY3_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY3_INT_EXTI_LINE) != RESET)
{
LED_warn(1);
BEEP(0);
LED1(1);
//清除中断标志位
EXTI_ClearITPendingBit(KEY3_INT_EXTI_LINE);
}
}
//加热中断——用户手动加热开启---->驱动继电器和 加热灯开启
void KEY4_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(KEY4_INT_EXTI_LINE) != RESET)
{
LED_heat(0);
relay_1;
//清除中断标志位
EXTI_ClearITPendingBit(KEY4_INT_EXTI_LINE);
}
}
//少液检测----警报灯亮起、蜂鸣器响
void LESS_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(LESS_INT_EXTI_LINE) != RESET)
{
LED_warn(0);
BEEP(1);
//清除中断标志位
EXTI_ClearITPendingBit(LESS_INT_EXTI_LINE);
}
}
//回血检测----警报灯亮起、蜂鸣器响
void BLOOD_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if(EXTI_GetITStatus(BLOOD_INT_EXTI_LINE) != RESET)
{
LED_warn(0);
BEEP(1);
//清除中断标志位
EXTI_ClearITPendingBit(BLOOD_INT_EXTI_LINE);
}
}
void GENERAL_TIM_INT_FUN(void)
{
// 当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断
// 这个时候我们需要把这个最长的定时周期加到捕获信号的时间里面去
if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET )
{
TIM_ICUserValueStructure.Capture_Period ++;
TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update );
}
// 上升沿捕获中断
if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET)
{
// 第一次捕获
if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )
{
// 计数器清0
TIM_SetCounter ( GENERAL_TIM, 0 );
// 自动重装载寄存器更新标志清0
TIM_ICUserValueStructure.Capture_Period = 0;
// 存捕获比较寄存器的值的变量的值清0
TIM_ICUserValueStructure.Capture_CcrValue = 0;
// 当第一次捕获到上升沿之后,就把捕获边沿配置为下降沿
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);
// 开始捕获标准置1
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
// 下降沿捕获中断
else // 第二次捕获
{
// 获取捕获比较寄存器的值,这个值就是捕获到的高电平的时间的值
TIM_ICUserValueStructure.Capture_CcrValue = GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);
// 当第二次捕获到下降沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);
// 开始捕获标志清0
TIM_ICUserValueStructure.Capture_StartFlag = 0;
// 捕获完成标志置1
TIM_ICUserValueStructure.Capture_FinishFlag = 1;
}
TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx);
}
}
液滴速度获取处理与显示相关(main.c中):
int main(void){
DHT11_Data_TypeDef DHT11_Data;
uint32_t time;
uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC+1);
u32 fre=0;
LED_GPIO_Config();
BEEP_GPIO_Config();
show_init();
DHT11_Init();
RELAY_Init();
Moto_Init();
EXTI_Key_Config();
uart_init(115200);
GENERAL_TIM_Init();
LED1(1);
while(1)
{
LCDI2C_Show_String(1,0,"speed: ");
LCDI2C_Show_String(11,0,"d/min");
if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)
{
time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) + (TIM_ICUserValueStructure.Capture_CcrValue+1);
printf ( "测得周期时间:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );
fre=60*TIM_PscCLK/time+1;
printf("频率为:%.1f\n",60.0*TIM_PscCLK/time+1);
printf("频率为:%d\n",fre);
LCDI2C_Show_Num(8,0,2,fre);
TIM_ICUserValueStructure.Capture_FinishFlag = 0;
delay_ms(10000);
//速度过快或过慢报警
if(fre<25||fre>55){
LED1(0);
BEEP(1);
}
}
LCDI2C_Show_String(2,1,"temp: ");
if( DHT11_Read_TempAndHumidity ( & DHT11_Data ) == SUCCESS)
{
LCDI2C_Show_FloatNum(8, 1,2,1,DHT11_Data.temperature);
if(DHT11_Data.temperature>=temp_door_1&&DHT11_Data.temperature<=temp_door_2)
{
relay_0;LED_heat(1);
}
else if(DHT11_Data.temperature<temp_door_1||DHT11_Data.temperature>temp_door_2)
{
relay_1;LED_heat(0);
}
}
delay_ms(500);
}
}
五、总结
这就是我做了大半个学期的课程设计,小菜鸡真的伤不起,断断续续终于在最后上交前做完了。和其他组相比,我们这个还算是常见,思路也不是很新,但毕竟是课程设计,考察的是你能不能做出来嘛!
在最后的汇报中,被老师问到了报警怎么都一样,也没办法呀,所有的中断后都用上了,确实没有多余的中断了。还有回血检测的阻断装置也没有想到好的办法解决。但是最后我们是A哦!因为我们基本上都实现了我们最初设想的功能,汇报的时候,系统也没有出bug,嘻嘻嘻!
上一篇: LeetCode 9.回文数 Java