单片机课程设计论文病床输液监控系统设计的制作.doc
医院病床输液监控系统摘 要该设计是以单片机MEGA16为核心,以键盘,碰触开关及红外光电开关为输入系统,以液晶、声光报警电路及步进电机为输出系统的智能化输液控制及监控系统。键盘系统为独立式按键系统,红外光电开关的功能为检测点滴的滴下。步进电机具有转速可控功率大及输入脉冲不变时可保持大力矩等优点,这样就可以自如控制吊瓶的上、下缓移可以达到智能控制的目的。点滴速度可用键盘来设定,同时输液结束或发生异常情况能发出报警信号。以上面所述装置为一个从站,主站和从站之间采用自定义串口通信协议,建立了一个由主站控制128个从站的有线监控系统。关键字 : 光电开关 MEGA16 步进电机 串口通行AbstractThe design is based on SCM MEGA16 core to keyboard, touch switches and infrared photoelectric switch for the input system to LCD, sound and light alarm circuit and the stepper motor output system of intelligent infusion for the control and monitoring system. Keyboard keys for the stand-alone systems, infrared photoelectric switch function for the detection of the drip . Stepper motor control with speed and input pulse power of a large change can be maintained when the advantages of high torque, so that you can freely control the bottle on a string of upper and lower slow shift to achieve intelligent control. Keyboard can be used to set the bit rate, while the end of infusion or abnormal conditions to an alarm signal. To the above mentioned device as a slave, between master and slave serial communication protocol with a custom set up a master control station of the cable 128 from the monitoring system. Keywords : Optical switch MEGA16 stepping motor USART目录一、系统方案11.1 点滴速度的测量11.2 点滴速度的控制11.3 控制用电动机及驱动的选择与比较11.4 系统总体方案2二、理论分析与设计22.1 点滴速度检测电路原理分析22.2 键盘控制及显示电路设计32.3 越限报警电路42.4 电机控制电路电路设计42.5 主从机通信电路设计5三、 电路与程序设计53.1 整机详细电路图见附录153.2 工作流程5四、测试方案与测试结果74.1 系统测试数据74.2 主机从机功能测试74.3 测试结果分析7五、总结:7六 、参考文献7附录1:整机详细电路图8附录2:主要控制程序919一、系统方案1.1 点滴速度的测量方案一 :采用电感式传感器测量点滴速度在输液器的漏斗外围绕线圈作为敏感元件。当液滴滴下是电感量发生变化,通过LC振荡电路后输出变化的频率值,经过F/V变换电路及电压比较后输出TTL电平信号来检测点滴速度。此方案测量精度比较高,但是外围电路比较复杂。方案二:采用反射式红外光电传感器在输液器的漏斗一端放置反射式红外传感器,当液滴下落时,利用其对红外线的反射能力,接收端检测到信号。但是由于水滴的表面不规则且较小,反射信号强弱,且不稳定反射式要求液滴下落时要和传感器保持精确的夹角,当输液器上下移动时会产生晃动,从而产生较强的干扰。方案三:采用槽式红外光电开关采用槽式红外对射式光电开关,集成度高,体积小,功能齐全,电线引出式,电源内藏式具备继电器大功率输出,具备交直流通用型,电压范围宽,抗震性能好,液滴检测非常稳定,对于对精度要求较高的医疗器械来讲,非常合适此方案成本低,经过实验可发现槽式式红外光电开关能比较灵敏地测出水滴。利用测量相邻点滴下落的时间间隔即可确定点滴速度。 综合考虑选用方案三槽式红外光电开关。1.2 点滴速度的控制 由题目可知,控制液滴下落速度主要有两种方法:方案一 : 通过步进电机和滑轮系统控制储液瓶的高度,来达到控制液滴流速的目的;方案二: 通过控制滴速夹的松紧程度来控制液滴流速。第一项方案实现较为简便,通过步进电机可方便地实现对储液瓶高度的调节,从而达到控制液滴流速的目的。第二项方案控制滴速夹移动的距离很小,但是滴速夹的松紧调节过程中,移动距离,移动阻力等参数难于计算,用机电系统实现起来较为困难。经过综合比较,我们决定选择第一项的方案。1.3 控制用电动机及驱动的选择与比较方案一:采用直流电机由于直流电机上电即转动,掉电后惯性较大,停机时还会转动一定角度后才可停下来。转矩小、无抱死功能,如果要求准确停在一个位置,其闭环算法较复杂。方案二:采用步进电机步进电机是一种用电脉冲进行控制,将电脉冲信号转换成相应角位移或线位移的电动机。步进电机每输入一个脉冲信号,转子就转动一个角度或前进一步,其输出的角位移或线位移与输入的脉冲数成正比,转速与脉冲频率成正比。用单片机控制步进电机,控制信号为数字信号,不再需要数模转换,具有快速启停能力,可在一刹那间实现启动或停止,且步距角降低小,延时短,定位准确,精度高,可操作性强。综合考虑,选用步进电机作为电机驱动控制电路。1.4 系统总体方案系统实现框图如图1: 越限声光报警 键盘控制 液晶显示 触碰开关 从站(单片机) 通信接口电路 主站(单片机) 点滴红外测速 电机驱动动 步进电机图1 医院病床输液监控系统系统框图 用G63-E303槽式红外光电开关检测液滴速度,由MEGA16单片机控制液晶5110显示速度,并控制电机驱动L298,控制步进电机的正反转,从而改变输液瓶的高度,控制点滴的速度,单片机再根据反馈的速度调整输液瓶的高度,闭环反馈准确地控制点滴速度。主机和从机之间利用UART通信方式,采用自定义的串口通信协议,实现主从之间的数据交流。采用触碰开关来检测异常情况,控制蜂鸣器鸣叫和LED闪烁。二、理论分析与设计2.1 点滴速度检测电路原理分析图2 G63-E303槽式红外光电开关内部原理图G6-E303槽式红外光电开关槽式光电开关传感器,发光器能发出红外光或可见光,在无阻情况下光接收器能接收到光,三极管2SC1008导通,OUT端被拉低,OUT输出低电平,LED不亮;当有液滴从槽中落下通过时,光被遮挡,三极管截止,OUT端输出高电平VCC,LED亮。用MEGA16的外部中断采集电平变化时下降沿,来实现对液滴的计数。 液滴下落的速度= X滴/分钟。2.2 键盘控制及显示电路设计键盘控制和显示电路我们采用液晶显示和独立按键。我们采用了一款Nokia型号为N5110的液晶显示器,该液晶显示器不同于LCD1602,它本身有没有字库,所以需要我们另外做字库,但是,它与LCD1602相比还是有优越性的,它可以很方便地描绘图画,因为它没有字库,每一幅画面都是人为描出来的,所以显示图画比LCD1602要方便地多。在这块板上N5110是采用模拟SPI通信。键盘控制我们采用了4乘4按键采用坐标查询的方式来识别按键,这是4乘4按键的基本原理图。其中P0、P1、P2、P3为输出端口,P4、P5、P6、P7为输入端口。当P0、P1、P2、P3都为高电平的时候,无论哪个按键被按下了,都与按键没被按下的状态相同,P4、P5、P6、P7端口的输入信号都为高电平。当P0为低电平,P1、P2、P3都为高电平时,若1号按键被按下,那么,P4口相当于和P0口直接相连,于是,P4口就读入低电平,而其他三个口读入为高电平。若2号按键被按下,同理,P5口就读入低电平,其他三个端口读入为高电平。其他的5、6、7、8、9、0、A、B、C、D、E、F按键被按下时都没有反应。这样就达到了识别1、2、3、4号按键的功能了,当P1输出低电平,P0、P2、P3端口为高电平时,同理,可以识别5、6、7、8号按键了。按照这种方式,我们就可以通过8个引脚逐列地扫描按键,达到识别16个按键的功能,而不需要像独立按键那样需要16个引脚,大大地节约了单片机的端口资源。 图3 扫描键盘工作原理图4 通用矩阵键盘原理图2.3 越限报警电路越限报警电路采用触碰开关和干簧管进行检测,把触碰开关安装在规定位置(即分别在输液管顶部距滑轮5cm处和漏斗由于越限报警距受液瓶顶部5cm处),当输液瓶移动到警戒位置时,触碰开关会触发单片机MEG16的PB1口的电平为低电平,PB1口采集到低电平后,立即控制PA6口,使蜂鸣器鸣叫;同时控制PA7口,点亮报警灯。电路原理图如图5图5 越限报警电路图 干簧管是一种磁敏的特殊开关。它的两个触点由特殊材料制成,被封装在真空 的玻璃管里。只要用磁铁接近它,干簧管两个节点就会吸合在一起,使电路导通。因此可以作为传感器用,用于计数,限位等等。将其装在距离受液瓶5cm处,并在漏斗背面安装小磁铁,当漏斗距受液瓶顶部小于5CM时,干簧管两个节点就会吸合在一起,从机检测到低电平,并向主机报告异常状况。主机检测到后蜂鸣器报警,LED闪烁。 2.4 电机控制电路电路设计 L298N 为SGS-THOMSON Microelectronics 所出产的双全桥步进电机专用驱动芯片( Dual Full-Bridge Driver ) ,内部包含4信道逻辑驱动电路,是一种二相 和四相步进电机的专用驱动器,可同时驱动2个二相或1个四相步进电机,内含二个H-Bridge 的高电压、大电流双全桥式驱动器,接收标准 TTL逻辑准位信号,可驱动46V、2A以下的步进电机,且可以直接透过电源来调节输出电压;此芯片可直接由单片机的IO端口来提供模拟时序信号, 但 OUTl、OUT2 和OUT3、OUT4 之间分别接2 个步进电机;input1input4 输入控制电位来控制电机的正反转;Enable 则控制电机停转。图6 L298驱动电机原理图2.5 主从机通信电路设计 通信模式选用AVR单片机的内部串口通行模块USART,USART全称是“通用同步和异步串行接收器和转发器”它能够进行全双工操作,即拥有独立的串行接收和转发器,能够同时进行接收和发送。它的工作方式又分为同步和异步,同步即为从机将XCK端口作为外部输入时钟信号,主机将XCK端口作为外部时钟输出引脚,从而把主从机的数据传输同步起来。异步为主从机各自设置相同的波特率(每秒发送数据的比特数,单位为bps或Kbps),通过默认的频率发送和接收数据。它除了要设置工作方式以外还要设置波特率、数据位、校验位、停止位等细节,所以无论是哪种方式,它对时序的要求都很高,写程序时必须十分注意每点的设置,如果有一点不同,通信就会出问题。三、 电路与程序设计3.1 整机详细电路图见附录1 3.2 工作流程 主机流程图 初始化UART接受中断检查是否有按键被按下数据接受LCD显示 NY 函数操作从机流程图 UART接受中断 初始化 定时 外部中断函数测速检查按键是否被按下 调速函数NY 呼叫主机UART发送数据给主机图7 程序流程图四、测试方案与测试结果4.1 系统测试数据表1 液滴速度检测测试速据单片机检测速度(滴/分) 实际速度(滴/分)5050535160597575表2 液滴速度调整测试原始值(滴/分)预置值(滴/分)调整后低速(滴/分)稳定时间(秒)521101071338712011914010575771374.2 主机从机功能测试将电路连接好,上电测试,从机将点滴的速度送入主机,并在主机中显示从机的速度和机号,此功能正常。4.3 测试结果分析从以上测试结果可以看出,本系统已基本完成题目中的各项要求并在此基础上有所发挥,其中点滴速度的测量比较精确,在全量程内其误差小于2(滴/分)。设置点滴速度功能中,控制精度在全量程范围内误差在5%以内,但是还是有一定的误差,经分析主要是由以下原因造成的: 1 由于瓶中的水不断减少,造成水滴的下落速度不均匀。 2 在动态控制时,由于瓶处于运动状态,其上升、下降运动不可避免的会产生加速度,导致水滴下落时速度不稳定。 3 算法本身不可能是完全精确的,必然存在舍入误差等,这些误差会影响测量结果。五、总结:本系统完成了在滴斗处检测点滴速度,并制作了一个液晶显示装置,能动态显示点滴速度(滴/分)。通过改变高度控制点滴速度,点滴速度可用键盘设定并显示,设定范围为50120(滴/分),误差在要求范围内。当高度到达警戒值时能发出报警信号,并可以手动解除报警状态。每个从站都可以和主站通信。主站可以工作在定点和巡回检测两种方式下,可以显示从站传输来的从站号和点滴速度,并设定从站的点滴速度。六 、参考文献1 伍亮.红外线检测物体单向运动计数器.设计师笔记,1997(6)17-18.2 贾智平,石冰. 微机原理与接口技术. 中国水利水电出版社,1999.3 江海波深入浅出AVR单片机:从ATmega48/88/168开始.中国电力出版社,2008.06.4康华光.电子技术基础(模拟部分).高等教育出版社,2006.01.5杨路明.C语言程序设计教程.北京邮电大学出版社,2005.12月.附录1:整机详细电路图附录2:主要控制程序主机程序#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include "N5110.h"#define uchar unsigned char#define F_CPU 8000000#define BAUDRATE 9600int flag,Num;static int Uart_Flag=0;uchar Data3;int V_Speed=50;int Flag=0;void USART_init(void)UCSRB=0X00;UCSRC=(1<<UCSZ1)|(1<<UCSZ0);UBRRL=(F_CPU/16/BAUDRATE-1)%256;UBRRH=(F_CPU/16/BAUDRATE-1)/256;UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); void USART_send(uchar data)while(!(UCSRA&(1<<UDRE);UDR=data;while(!(UCSRA&(1<<TXC);void timer0_init(void)TCCR0|=(1<<CS00)|(1<<CS02);/1024分频,普通模式TIMSK|=0X01;TCNT0=0X63;/20ms 1次中断void port_init(void)DDRB = 0X0f;PORTB = 0XFF;DDRD|=0x02;PORTD=0xff;DDRA = 0xf0;PORTA = 0x80;int key_scan(void)int i,j,a,b;for(i=0;i<4;i+)PORTB = (1<<i);_delay_us(100);a = PINB&0XF0;if(a!=0xf0)switch(a)case 0xe0: b=4*i+1;break;case 0xd0: b=4*i+2;break;case 0xb0: b=4*i+3;break;case 0x70: b=4*i+4;break;default : b=0; break;_delay_ms(1500);return b;return 0;void Data_Send(void)USART_send(0xff);_delay_ms(10);USART_send(Num);_delay_ms(10);USART_send(V_Speed);_delay_ms(10);int main(void)int i,j,key;port_init();N5110_init();USART_init();sei();while(1)key=key_scan();switch(key)case 0x01: Num = 0x01;Flag = 0;break;case 0x02: Num = 0x02;Flag = 0;break;case 0x03: V_Speed += 5;Flag = 0;break; /速度上升case 0x04: V_Speed -= 5;Flag = 0;break; /速度下降case 0x05: Data_Send();Flag = 0;break;case 0x06: Num = 0x00;Data_Send();Flag = 0;N5110_clear_screen();break; /未选择任何从机,从机可呼叫主机case 0x07: Flag = 1;break;case 0x08: N5110_add_xy(0,5);N5110_led_ASCALLS(" ");PORTA &=(1<<6);PORTA |=(1<<7);break;if(Flag = 1)Num = 0x01;V_Speed = 0x00;Data_Send();for(i=0;i<100;i+)_delay_ms(100);Num = 0x02;V_Speed = 0x00;Data_Send();for(i=0;i<100;i+)_delay_ms(100);ISR (USART_RXC_vect)DataUart_Flag=UDR;if(DataUart_Flag=0xff)Uart_Flag=0;elseUart_Flag+;if(Uart_Flag>=3)if(Data1=0x03)N5110_add_xy(0,5);N5110_led_int(Data0);N5110_led_ASCALLS(" CALL!");PORTA |=(1<<6);PORTA &=(1<<7);elseN5110_add_xy(0,0);N5110_led_ASCALLS("Num:");N5110_led_int(Data0);N5110_led_ASCALLS(" ");N5110_add_xy(0,1);N5110_led_ASCALLS("State:");if(Data1=0x00)N5110_led_ASCALLS("Good!");N5110_led_ASCALLS(" ");else if(Data1=0x01)N5110_led_ASCALLS("Up!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);else if(Data1=0x02)N5110_led_ASCALLS("Down!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);N5110_add_xy(0,2);N5110_led_ASCALLS("V_Speed:");N5110_led_int(V_Speed);N5110_led_ASCALLS(" ");N5110_add_xy(0,3);N5110_led_ASCALLS("Speed:");if(Data2<10)N5110_led_ASCALLS("Done!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);elseN5110_led_int(Data2);N5110_led_ASCALLS(" ");从机程序#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include "N5110.h"#define uchar unsigned char#define F_CPU 8000000#define BAUDRATE 9600int flag,Num;static int Uart_Flag=0;uchar Data3;int V_Speed=50;int Flag=0;void USART_init(void)UCSRB=0X00;UCSRC=(1<<UCSZ1)|(1<<UCSZ0);UBRRL=(F_CPU/16/BAUDRATE-1)%256;UBRRH=(F_CPU/16/BAUDRATE-1)/256;UCSRB=(1<<RXEN)|(1<<TXEN)|(1<<RXCIE); void USART_send(uchar data)while(!(UCSRA&(1<<UDRE);UDR=data;while(!(UCSRA&(1<<TXC);void timer0_init(void)TCCR0|=(1<<CS00)|(1<<CS02);/1024分频,普通模式TIMSK|=0X01;TCNT0=0X63;/20ms 1次中断void port_init(void)DDRB = 0X0f;PORTB = 0XFF;DDRD|=0x02;PORTD=0xff;DDRA = 0xf0;PORTA = 0x80;int key_scan(void)int i,j,a,b;for(i=0;i<4;i+)PORTB = (1<<i);_delay_us(100);a = PINB&0XF0;if(a!=0xf0)switch(a)case 0xe0: b=4*i+1;break;case 0xd0: b=4*i+2;break;case 0xb0: b=4*i+3;break;case 0x70: b=4*i+4;break;default : b=0; break;_delay_ms(1500);return b;return 0;void Data_Send(void)USART_send(0xff);_delay_ms(10);USART_send(Num);_delay_ms(10);USART_send(V_Speed);_delay_ms(10);int main(void)int i,j,key;port_init();N5110_init();USART_init();sei();while(1)key=key_scan();switch(key)case 0x01: Num = 0x01;Flag = 0;break;case 0x02: Num = 0x02;Flag = 0;break;case 0x03: V_Speed += 5;Flag = 0;break; /速度上升case 0x04: V_Speed -= 5;Flag = 0;break; /速度下降case 0x05: Data_Send();Flag = 0;break;case0x06:Num=0x00;Data_Send();Flag=0;N5110_clear_screen();break;/未选择任何从机,从机可呼叫主机case 0x07: Flag = 1;break;case0x08:N5110_add_xy(0,5);N5110_led_ASCALLS(" ");PORTA &=(1<<6);PORTA |=(1<<7);break; if(Flag = 1)Num = 0x01;V_Speed = 0x00;Data_Send();for(i=0;i<100;i+)_delay_ms(100);Num = 0x02;V_Speed = 0x00;Data_Send();for(i=0;i<100;i+)_delay_ms(100);ISR (USART_RXC_vect)DataUart_Flag=UDR;if(DataUart_Flag=0xff)Uart_Flag=0;elseUart_Flag+;if(Uart_Flag>=3)if(Data1=0x03)N5110_add_xy(0,5);N5110_led_int(Data0);N5110_led_ASCALLS(" CALL!");PORTA |=(1<<6);PORTA &=(1<<7);elseN5110_add_xy(0,0);N5110_led_ASCALLS("Num:");N5110_led_int(Data0);N5110_led_ASCALLS(" ");N5110_add_xy(0,1);N5110_led_ASCALLS("State:");if(Data1=0x00)N5110_led_ASCALLS("Good!");N5110_led_ASCALLS(" ");else if(Data1=0x01) N5110_led_ASCALLS("Up!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);else if(Data1=0x02)N5110_led_ASCALLS("Down!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);N5110_add_xy(0,2);N5110_led_ASCALLS("V_Speed:");N5110_led_int(V_Speed);N5110_led_ASCALLS(" ");N5110_add_xy(0,3);N5110_led_ASCALLS("Speed:");if(Data2<10)N5110_led_ASCALLS("Done!");N5110_led_ASCALLS(" ");PORTA |=(1<<6);PORTA &=(1<<7);elseN5110_led_int(Data2);N5110_led_ASCALLS(" ");