单片机设计基于单片机的医院输液系统设计

收藏和点赞,您的关注是我创作的动力

概要

  本课题是研究如何使自动化设备与静脉输液完美结合在一起的方法,本论文论述了如何用AT89SC51单片机以及多种传感器协同合作来实现自动化输液系统的。通过测速模块测出药液的滴速,通过红外感应模块反馈给单片机,继续向下传导信号来控制滴速保持稳定。通过液面检测传感器来反映出瓶中剩余的药液量,当到达起始时设定的警戒位置时发出警报并亮起红灯来提醒医护人员。这个系统操作简洁、上手较快、具有报警功能并且方便集中控制,在现代医疗事业具有较大意义,推动了自动化的智能医疗事业的发展, 有利于提高医护质量。
本项目总体实现了使用红外线感应模块来感应到液体的滴速,可以自行调节滴速。并可在护士站直接显示出瓶中剩余液体量与剩余时间,使护士可以实时了解输液情况。当瓶中的剩余量到达警戒值时发出警报并亮起红灯来提醒进行更换或拔除。本项目的整体设计对医院输液系统达成自动化做出巨大贡献。

关键词:51单片机;医院输液系统;输液监控系统。

一、系统方案设计与论证

1.1系统硬件设计方案

输液器控制系统大致可分为以下几部分:电机系统、液位检测、剩余时间计算、滴速测量、键盘显示。结构图如下。
在这里插入图片描述

图1.1总体结构框图

1.2点滴速度测量电路方案的选择及论证

下行速度的测量在整个设计中起着重要的作用,它不仅是系统的基础,也是系统的最终回归点,根据当前市场使用的设计方法和电子控制原理,具有以下方案:
方案一:使用反射式红外光电传感器。反射式红外传感器放在输液袋的一端。当它掉落时,接收器会利用它的反射式红外线追踪功能。但因为水滴大小以及外表形状的差异,有时会导致反射信号不稳定,上下振动会发生,从而产生强烈的干扰。
方案二:在红外线软管处测量输注速度的基本原理是防止接收管在发射和产生高电平脉冲时接收红外光束。为了提高抗干扰能力,可以使用两对红外传感器进行接收和传输。而不是像场景1中那样只使用其中一个传感器在反射模式下工作。红外传感器体积小,重量轻,易于安装在跌落箱上;同时,它不需要复杂的辅助电路,电路非常简单,性能也相对稳定。现代红外传感器生产实践中发挥了巨大作用。
因为难以通过使用反射型红外传感器和对面的红外传感器来判断水的流速,尽管水流相对于红外而言相对较弱,但它比反射性要强。与其他红外线传感器相比,它可以更敏感地感知流速。因此,这个方案很容易实现,使用第二种方法来测量液滴下落速度更简单方便。

1.4通过电机控制滴速电路的方案论证

1.4.1电机控制滴速的方案设计

方案一:通过调整滴瓶高度h。根据滴瓶高度h与滴瓶速度的关系,发动机驱动滴瓶升高或降低以改变滴瓶高度h,从而调整速度。这种方法的原理简单易行,大多数设计者都采用这种方法。因此,我们需要通过实验来粗略地测量与相应高度相对应的水滴速度,并记下它存在于单片机中,然后直接对其进行调整。在滴斗处用红外系统来测量水滴的速度。模拟示意图如图1.2。
方案二:与人工输液相同,下降速度是通过控制木材的结来控制的,这是普遍接受的,但下降速度夹的特性决定了它只适合于液体下落速度的大幅度不均匀调整,当涉及微调时很难控制,不易实现。综上所述选择方案一。

在这里插入图片描述

图1.2 输液模拟示意图

1.4.2控制用电动机及驱动的选择与比较

方案一:采用直流电机
当直流电动机起动时,失电后的惯性非常大。在停止之前它将旋转一定角度。转矩小,没有锁定功能。如果必须在一个特定位置停止,其算法很复杂。
方案二:采用步进电机
当步进电机发出脉冲信号时,速度与脉冲频率成正比。步进电机由单片机控制。控制信号是数字的,不需要数字/模拟转换。它具有快速启动/停止功能,可以快速启动或停止。延迟时间短,位置准确,精度高,运行性能强。综合考虑,选用步进电机。

二、输液系统各模块的硬件设计

主要介绍了电机模块、电源模块、声音报警模块以及步进电机的工作原理,详细介绍了如何串联各部分工作单位进行工作,使该项目完整运行。主要结构框图如图2.1所示。
在这里插入图片描述

图2.1 结构框图
病床端结构框图如图2.2所示。
在这里插入图片描述

图2.2病床端框图

护士站端机构框图如图2.3所示。
在这里插入图片描述

图2.3护士站端结构框图

三、软件设计

实物

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

附录1 原理图

在这里插入图片描述

附录2 源程序清单

#include "lcd1602.h"  
#include "eepom52.h"
#include "nrf24l01.h"  

sbit buzzer  = P1^7;//蜂鸣器	
 
sbit key1 = P2^1;	 
sbit key2 = P2^0;	 
sbit key3 = P2^2;


sbit Reduc  = P2^1;	 //减
sbit Add = P2^0;	 //加
sbit Mode = P2^2;	 //设置

static int step_index;  //步进索引数,值为0-7
static bit turn;  //步进电机转动方向
static bit stop_flag;  //步进电机停止标志

sbit S1=P1^0;
sbit S2=P1^1;
sbit S3=P1^2;
sbit S4=P1^3;

void gorun(void)
{
  	if (stop_flag==1)
  	{
    	S1 = 0;
    	S2 = 0;
    	S3 = 0;
    	S4 = 0;
    	return;
  	}
  	switch(step_index)
  	{
  		case 0: //0
    		S1 = 1;
    		S2 = 0;
    		S3 = 0;
    		S4 = 0;
    	break;
  		case 1: //0、1
    		S1 = 1;
    		S2 = 1;
    		S3 = 0;
    		S4 = 0;
    	break;
  		case 2: //1
    		S1 = 0;
    		S2 = 1;
    		S3 = 0;
    		S4 = 0;
    	break;
  		case 3: //1、2
    		S1 = 0;
    		S2 = 1;
    		S3 = 1;
    		S4 = 0;
    	break;
  		case 4:  //2
    		S1 = 0;
    		S2 = 0;
    		S3 = 1;
    		S4 = 0;
    	break;
  		case 5: //2、3
    		S1 = 0;
    		S2 = 0;
    		S3 = 1;
    		S4 = 1;
    	break;
  		case 6: //3
    		S1 = 0;
    		S2 = 0;
    		S3 = 0;
    		S4 = 1;
    	break;
  		case 7: //3、0
    		S1 = 1;
    		S2 = 0;
    		S3 = 0;
    		S4 = 1;
		break;
  	}
  	if (turn==0)
  	{
    	step_index++;
    	if(step_index>7)
      		step_index=0;
  	}
  	else
  	{
    	step_index--;
    	if(step_index<0)
      		step_index=7;
  	}  
}

uint time10ms=0,time1s=0;
uint v=0;
uint dishu=0;
/**********************
** 速度检测处理部分
***********************/
void int0_init(void)
{
	IT0=1;	    //下降沿触发
	EX0=1;		//中断标志位置1
	EA=1;		//打开总中断
}
void int0() interrupt 0
{	
	EX0=0;
	TR1=1;
	if(time10ms>50)
	{
		dishu++;		
		v=60000/time10ms;
		if(v>2000)v=0;
		time10ms=0; 
	}	
	EX0=1;	
}
void Timer1_init(void)
{
	TMOD&=0X0F;
	TMOD|=0X10;     //定时器0工作于方式1
	TH1=(65536-10000)/256;   //定时器T0高8位重新赋初值
	TL1=(65536-10000)%256;   //定时器T0低8位重新赋初值       //10MS
	ET1=1;          //打开定时器0
	TR1=0;          //启动定时器0
	EA=1;           //开总中断
}
void Time1(void) interrupt 3   
{	  
	TH1=(65536-10000)/256;   //定时器T0高8位重新赋初值
	TL1=(65536-10000)%256;   //定时器T0低8位重新赋初值       
	time10ms++;
	time1s++;
	if(time10ms>800){v=time10ms=0;TR1=0;}
}
void main(void)
{	
	bit abfsds=0;
	uchar bingchuanghao=1;
	bit wtwt=0;
	uint bs=0,ds=0;
	uchar yw2=0;

	bit wq=0,we=0,wq1=0,we1=0;
	uint time=0,gs;
	uint as=0,vl=500,lh=3000;
	uchar TxBuf[12];//无线模块发射数组
	uint L=0;
	uchar ws1=1,ws2=1;
	uchar disp1[16]={"v:00.00ml/min 01"};
	uchar disp2[16]={"L:000.00ml 500ml"};

	uchar Mode_project=1,Mode_flag=1,Mode_count=0;//设置变量

	uint buzzer_flag=0,buzzer_count=0,buzzer_time=45;//蜂鸣器报警变量

	//buzzer=0;
	
	int0_init();//外部中断初始化
  	Timer1_init();//定时器初始化

	LCD_Init();//LCD初始化
	//检测无线模块是否存在
	MOSI=0;
	while(NRF24L01_Check())
	{
		WriteChar(1,0,16,"  NO  NRF24L01  ");				 
		delayms(500);
		WriteChar(1,0,16,"                ");				 
		delayms(500); 
	}
	init_NRF24L01();//无线模块初始化

	dishu=0;

	/***开机把数据从单片机内部eepom中读出来***/
	if(byte_read(0x2050)!=1)
	{		
		SectorErase(0x2000);
		byte_write(0x2000,vl/255);
		byte_write(0x2001,vl%255);

		byte_write(0x2002,lh/255);
		byte_write(0x2003,lh%255);

		byte_write(0x2004,bingchuanghao);

		byte_write(0x2050,1);		
	}
	if(byte_read(0x2050)==1)
	{
		vl=byte_read(0x2000)*255+byte_read(0x2001);
		lh=byte_read(0x2002)*255+byte_read(0x2003);
		bingchuanghao=byte_read(0x2004);
	}

 	while(1)
 	{	 
		//切换总量
		if(!key1 && !wq1)
		{
			wq1=1;
			we1=~we1;
			if(!we1)//500
			{			
				ws2=1;
				dishu=0;
				disp2[11]='5';
				disp2[12]='0';	
			}
			else//250
			{
				ws2=2;
				dishu=0;
				disp2[11]='2';
				disp2[12]='5';	
			}
		}
		if(key1 && wq1)
		{
			wq1=0;
		}


		/****10秒没有液滴报警****/
		if(v>100 && !bs)
		{
			bs=1;	
		}
		if(bs && v==0)
		{
			if(++ds>300)yw2=1;
		}
		if(bs && v!=0){ds=0;yw2=0;}

		//夹死管子
		if(yw2 && !wtwt)
		{
			wtwt=1;
			
			buzzer=1;
			
			turn = 0;//反转
			stop_flag=0;
			gs=2000;
			while(gs--)
			{
				gorun();			
				delay11us(100);
			}
			stop_flag=1;
			gorun();
		}
		//松开管子
		if(!yw2 && wtwt)
		{
			wtwt=0;
			
			buzzer=1;
			
			turn = 1;//正转
			stop_flag=0;
			gs=2000;
			while(gs--)
			{
				gorun();			
				delay11us(100);
			}
			stop_flag=1;
			gorun();
		}
		//手动报警
		if(!key2 && !wq)
		{
			wq=1;
			we=~we;
		}
		
		if(key2 && wq)
		{
			wq=0;
		}
			
		

		//步进电机自动调节
		if(v>=0 && v<100)
		{
			stop_flag=1;
			gorun();
		}
		else 
		{
			if(++time>200)
			{
				time=0;
				if((v>vl-200)&&(v<vl+200))
				{
					stop_flag=1;
					gorun();	
					
					abfsds=1;//速度正常范围标志位置1
				}
				else if(v>vl+200)
				{
					turn = 0;//反转
					stop_flag=0;
					gs=100;
					while(gs--)
					{
						gorun();			
						delay11us(100);
					}
					stop_flag=1;
					gorun();
				}
				else if(v<vl-200)
				{
					turn = 1;//正转
					stop_flag=0;
					gs=100;
					while(gs--)
					{
						gorun();			
						delay11us(100);
					}
					stop_flag=1;
					gorun();	
				}
			}
		}

		disp1[14]=bingchuanghao/10%10+0x30;
		disp1[15]=bingchuanghao%10+0x30;


		disp1[2]=v/1000%10+0x30;
		disp1[3]=v/100%10+0x30;
		disp1[5]=v/10%10+0x30;
		disp1[6]=v%10+0x30;

		if(ws1==1)L=dishu*10/1.0;
//		else if(ws1==2)L=dishu*10/1.5;
//		else if(ws1==3)L=dishu*10/2.0;

		if(ws2==1)L=50000-L;
		else if(ws2==2)L=25000-L;
//		else if(ws2==3)L=10000-L;

		disp2[2]=L/10000%10+0x30;
		disp2[3]=L/1000%10+0x30;
		disp2[4]=L/100%10+0x30;
		disp2[6]=L/10%10+0x30;		
		disp2[7]=L%10+0x30;
	
		/****无线发送****/
		TxBuf[2]=v/255;
		TxBuf[3]=v%255;
		TxBuf[4]=L/255;
		TxBuf[5]=L%255;
		TxBuf[6]=ws2;
		TxBuf[7]=1;//从机地址
		TxBuf[8]=buzzer_flag;
		TxBuf[9]=bingchuanghao;
		//无线发射		
		nRF24L01_TxPacket(TxBuf);
		delayms(10);
		/****剩余量少于设定值或10秒没有检测到液滴或手动报警或速度不在上下限范围内报警****/
		if((L<lh || we || yw2)||(abfsds && (v<vl-300)||(v>vl+300)))
		{
			buzzer_flag=1;
		}
		else
		{
			buzzer_flag=0;
			buzzer=1;
		}		
		/*******蜂鸣器报警********/
		buzzer_count++;if(buzzer_count>buzzer_time*10)buzzer_count=buzzer_time+1;
		if(buzzer_count%buzzer_time==0 && buzzer_flag)
		{
			buzzer=~buzzer;//蜂鸣器取反发出声音报警
			if(!buzzer)LCD_Init();
		}

		//按下设置键,进入设置页面
		if(Mode==0 && Mode_flag)
		{	 
			buzzer=1;
			as=0;
			WriteCOMDATA(0x0F,0);
			delayms(100);			
			if(Mode==0)
			{	
				while(Mode==0);			
				Mode_flag=0;
				Mode_project=1;
				//设置页面显示内容
				WriteChar(1,0,16,"Lh:000.0 ml    01");				 
				WriteChar(2,0,16,"  v:00.00ml/min ");


				WriteCOMDATA(0x83,0);
				WriteCOMDATA(lh/10000%10+0x30,1);
				WriteCOMDATA(lh/1000%10+0x30,1);
				WriteCOMDATA(lh/10%10+0x30,1);
				WriteCOMDATA('.',1);
				WriteCOMDATA(lh/10%10+0x30,1);				
				//WriteCOMDATA(lh%10+0x30,1);


				WriteCOMDATA(0x8E,0);
				WriteCOMDATA(bingchuanghao/10%10+0x30,1);
				WriteCOMDATA(bingchuanghao%10+0x30,1);

				WriteCOMDATA(0xC4,0);
				WriteCOMDATA(vl/1000%10+0x30,1);
				WriteCOMDATA(vl/100%10+0x30,1);
				WriteCOMDATA('.',1);
				WriteCOMDATA(vl/10%10+0x30,1);				
				WriteCOMDATA(vl%10+0x30,1);
				while(Mode==0);
				while(1)		  
				{	
					switch(Mode_project)
					{	
						case 1:
							WriteCOMDATA(0x83,0);
							WriteCOMDATA(lh/10000%10+0x30,1);
							WriteCOMDATA(lh/1000%10+0x30,1);
							WriteCOMDATA(lh/100%10+0x30,1);
							WriteCOMDATA('.',1);
							WriteCOMDATA(lh/10%10+0x30,1);				
							//WriteCOMDATA(lh%10+0x30,1);
							WriteCOMDATA(0x87,0);
						break;
						case 2:
							WriteCOMDATA(0x8E,0);
							WriteCOMDATA(bingchuanghao/10%10+0x30,1);				
							WriteCOMDATA(bingchuanghao%10+0x30,1);
							WriteCOMDATA(0x8F,0);
						break;			                                						
						case 3:
							WriteCOMDATA(0xC4,0);
							WriteCOMDATA(vl/1000%10+0x30,1);
							WriteCOMDATA(vl/100%10+0x30,1);
							WriteCOMDATA('.',1);
							WriteCOMDATA(vl/10%10+0x30,1);							
							WriteCOMDATA(vl%10+0x30,1);
							WriteCOMDATA(0xC8,0);
						break;						
					}
					delayms(400);
					//按下加键,对设定目标加
					if(Add==0)
					{
						delayms(400);
						switch(Mode_project)
						{
							case 1:lh+=50;break;
							case 2:bingchuanghao+=1;if(bingchuanghao>=99)bingchuanghao=99;break;
							case 3:vl+=1;break;							
						}		
					}
					//按下减键,对设定目标减
					if(Reduc==0)
					{
						delayms(400);
						switch(Mode_project)
						{
							case 1:lh-=50;break;
							case 2:bingchuanghao-=1;if(bingchuanghao<=1)bingchuanghao=1;break;
							case 3:vl-=1;break;															
						}		
					}
					//短按设置键,切换设定目标,长按设置键2S,则退出设置页面
					if(Mode==0)
					{
						delayms(600);
						while(Mode==0)
						{
							delayms(600);
							Mode_count++;
							if(Mode_count>6)
							{
								WriteCOMDATA(0x0C,0);
								delayms(100);
								WriteChar(1,0,16,disp1);  //第一行显示内容
								WriteChar(2,0,16,disp2); //第二行显示内容
							}
						}
						if(Mode_count>6)
						{
							Mode_count=0;

							SectorErase(0x2000);
							byte_write(0x2000,vl/255);
							byte_write(0x2001,vl%255);
							byte_write(0x2002,lh/255);
							byte_write(0x2003,lh%255);
							byte_write(0x2004,bingchuanghao);
							byte_write(0x2050,1);
							break;
						}
						else Mode_count=0; 
						Mode_project++;
						if(Mode_project>3)Mode_project=1;
					}
				}	
			}
		}					
		/********液晶显示********/		   			 
		WriteChar(1,0,16,disp1);
		WriteChar(2,0,16,disp2);
		if(Mode_flag==0){Mode_count++;if(Mode_count>20){Mode_count=0;Mode_flag=1;}}
 	}
} 



四、 结论

该系统已完成了液滴桶上液滴速度的检测,并设计了可动态显示液滴速度的液晶显示装置。液滴速度可以通过改变高度来控制。可通过键盘设置和显示喝酒速度。设定范围为50-90,误差在规定范围内。当高度达到报警值时,可发出报警信号,并可手动触发报警模式。
通过模拟结果可得出能够满足的要求有以下几点:
(1)相显示液滴滴速、剩余输液时间;
(2)对输液速度可以自动控制;
(3)将病床端与护士站端相连接,使输液情况可以及时传输到护士站端,便于护士观察。
(4)当剩余的输液时间达到一定时间(5分钟)时,可以通过相应的设备触发自动警报或输液情况。
此设计还完全分析并确定了输液系统设计的关键和难点,通过理论分析、论证判定这些辩证思想达到最佳设计方案。

五、 文章目录

目 录

摘 要 Ⅰ
Abstract Ⅱ
引 言 1
1系统方案设计与论证 3
1.1系统硬件结构总体设计方案 3
1.2点滴速度测量电路方案的选择与论证 3
1.3液面检测电路方案的选择与论证 4
1.4通过电机控制滴速电路的方案与论证 4
1.5显示器接口电路方案选择与论证 5
1.6键盘接口电路方案选择与论证 6
1.7单片机型号的选择与论证 6
2输液系统各模块的硬件设计 9
2.1控制电机模块设计 10
2.2数据采集模块 11
2.3电源模块 13
2.4声音报警模块 13
2.5复位电路 13
2.6显示模块 14
2.7键控模块 16
2.8通信模块设计 17
3系统软件及框图设计 19
3.1滴速检测子程序 20
3.2电机控制子程序 21
3.3显示子程序 23
3.4键盘子程序 24
4系统调试及项目焊接 26
4.1设计实现过程 26
4.2电路焊接 26
4.3实物调节 27
4.4系统测试及结果误差分析 28
结 论 30
参考文献 31
附录1原理图 33
附录2源程序代码 34
致 谢 45

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值