主要内容
设计并制作智能送药小车,模拟完成在医院药房与病房间药品的送取作业。院区结构示意如图1所示。院区走廊两侧的墙体由黑实线表示。走廊地面上画有居中的红实线,并放置标识病房号的黑色数字可移动纸张。药房和近端病房号(1、2号)如图1所示位置固定不变,中部病房和远端病房号(3-8号)测试时随机设定。
如上图所示,(1)稳压供电模块:用于将双节锂电池18650的 7.4~8.4V输入电压转换为其他四个模块可用的5V工作电压,在调试过程中,发现第一路的LM7805稳压电路输出功率不足给整个小车供电,所以增加一路由稳压芯片LM2596搭成的DC-DC稳压模块给51最小系统模块和检测红线灰度传感器模块供电,而第一路的LM7805稳压电路单独只给电机PWM驱动模块供电。(2)按键及数码管模块:共两个按键(key_s2及key_s3)及一个共阴数码管,数码管显示将要送达的病房编号,两个按键则是用于病房数+1及确定是否要送达此编号的病房。(3)检测红线的灰度传感器模块:该传感器为5路光敏灰度传感器,其中灯亮为检测到地面(白色),对应引脚输出为1,而灯灭为检测到红线或黑线,对应引脚输出为0。(4)电机PWM驱动模块:采用L293D驱动芯片用于驱动直流减速电机的转动。(5)51最小系统模块:用于检测灰度传感器的五路引脚电平变化,及通过灰度传感器的五路引脚电平变化,进而控制直流减速电机。
如上图所示,程序的设计中,(1)循迹程序设计:通过模块化思想将每种小车运动模型模块化,分为循直线函数、左转函数、右转函数、直线后退函数、旋转函数、停止函数。通过每个病房的路线中,含有的特定标志可以映射为特定的五路灰度传感器的引脚电平,进而我们可以通过程序实时检测五路传感器特定电平状态的变化来控制电机的运动状态,以此来实现小车到达特定病房的循迹。简而言之就是通过特定病房线路的特定标志来控制小车循迹。(2)小车速度程序设计思想:小车的速度则是通过单片机的定时器来控制电机占空比进而实现控制小车的转速。(3)确定病房程序设计:按键key_s2每按一次单片机将检测到低电平,定义变量Room_num 将+1(Room_num将0~9循环+1),数码管则会实时显示Room_num的值,而按键key_s3为确定键,只有当key_s3按下后,单片机才会继续往下执行循迹病房的程序,简而言之,就是按键key_s2让病房数+1,按键key_s3为确定是否要循迹该病房,数码管实时显示病房号,上述就是设计每个病房循迹的思想。
car.h文件 |
#ifndef __CAR_H__
#define _CAR_H__
/*电机驱动IO定义*/
sbit IN1 = P1^2; //为1 左电机反转
sbit IN2 = P1^3; //为1 左电机正转
sbit IN3 = P1^6; //为1 右电机正转
sbit IN4 = P1^7; //为1 右电机反转
sbit EN1 = P1^4; //为1 左电机使能
sbit EN2 = P1^5; //为1 右电机使能
/*循迹小车IO口定义*/
sbit R_led2 = P3^6;// 右寻迹灯2 为0没有识别到红线 为1识别到红线
sbit R_led1 = P3^5;//右寻迹灯1 为0没有识别到红线 为1识别到红线
sbit M_led0 = P3^4;//中间寻迹灯0 为0没有识别到红线 为1识别到红线
sbit L_led1 = P3^3;//左寻迹灯1 为0没有识别到红线 为1识别到红线
sbit L_led2 = P3^2;//左寻迹灯2 为0没有识别到红线 为1识别到红线
/*按键定义*/
sbit key_s2 = P3^0;//+1
sbit key_s3 = P3^1;//确定键
sbit beep = P2^3;//蜂鸣器
sbit LE1 = P2^7;//数码管位选
sbit LE2 = P2^6;//数码管段选
#define left_motor_en EN1 = 1 //左电机使能
#define right_motor_en EN2 = 1 //右电机使能
#define left_motor_dis EN1 = 0 //左电机不使能
#define right_motor_dis EN2 = 0 //右电机不使能
#define left_motor_stops IN1 = 0, IN2 = 0//左电机停止
#define right_motor_stops IN3 = 0, IN4 = 0//右电机停止
#define left_motor_go IN1 = 0, IN2 = 1//左电机正传
#define left_motor_back IN1 = 1, IN2 = 0//左电机反转
#define right_motor_go IN3 = 1, IN4 = 0//右电机正传
#define right_motor_back IN3 = 0, IN4 = 1//右电机反转
typedef unsigned char uchar;
typedef unsigned int uint;
#endif
motor.c文件 |
#include
#include
/*毫秒级延时*/
void delay(uint z)
{
uint x,y;
for(x = z; x > 0; x--)
for(y = 114; y > 0 ; y--);
}
/*小车前进*/
void forward()
{
left_motor_go; //左电机前进
right_motor_go; //右电机前进
}
/*小车左转*/
void left_run()
{
left_motor_stops; //左电机停止
right_motor_go; //右电机前进
}
/*小车右转*/
void right_run()
{
right_motor_stops;//右电机停止
left_motor_go; //左电机前进
}
/*小车后退*/
void backward()
{
left_motor_back; //左电机后退
right_motor_back; //右电机后退
}
/*小车停止*/
void stop()
{
right_motor_stops;
left_motor_stops;
}
/*转向*/
void turn_roud()
{
left_motor_go;
right_motor_back;
}
/*直走*/
void go_straight()
{
if(L_led1==0 && M_led0 ==1 && R_led1==0 )//识别红线直行
{
forward();
}
else
{
if(L_led1 == 1 && R_led1 == 0)//小车右边出线,左转修正 1是红 0是白
{
left_run();//左转
}
if(L_led1 == 0 && R_led1 == 1)//小车左边出线,右转修正
{
right_run();//右转
}
if(L_led2 == 1 && L_led1 == 0 && R_led2 ==0) //小车右边出线,左转修正
{
left_run();//左转
}
if(L_led1 == 0 && R_led1 == 0 && R_led2==1)//小车左边出线,右转修正
{
right_run();//右转
}
}
}
void chesi()
{
stop();
while(1);
}
main.c文件 |
/* 说明:
(灯亮白0) (灯灭红1)
*/
#include
#include
extern void delay(uint z);
extern void forward();
extern void left_run();
extern void right_run();
extern void backward();
extern void stop();
extern void turn_roud();
extern void go_straight();
extern void chesi();
void key_exa();
void congif_T0();
uchar PWM_T = 0; //周期
uchar PWM_left_val = 110;//左电机占空比值 取值范围 95
uchar PWM_right_val = 110;//右电机占空比值取值范围 95
//共阴数码管(熄灭、1~9)表
uchar code leddata[]={0x00, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
uchar T1_H = 0xB8;
uchar T1_L = 0x00;
uchar Room_num = 0;
uchar EN_room = 0;
uchar flag_go = 0;
uchar flag_back = 0;
void congif_T0()
{
EA = 1;
TMOD = 0x02;
TH0 = 183;
TL0 = 183; //电机T = T1*256 = 20ms;
TR0 = 1;
ET0 = 1;
P0 = leddata[Room_num];
}
void key_exa()
{
while(1)
{
if(key_s2 == 0)
{
delay(20);
if(key_s2 == 0)
{
Room_num++;
if(Room_num > 9)
{
Room_num = 1;
}
while(key_s2 == 0);
}
}
if(key_s3 == 0)
{
delay(20);
if(key_s3 == 0)
{
EN_room++;
while(key_s3 == 0);
break;
}
}
}
}
void main()
{
LE1 = 1;
P0 = 0xfe;
LE1 = 0;
LE2 = 1;
congif_T0();
key_exa();
while(1)
{
if( Room_num == 1 && EN_room == 1)
{
// PWM_left_val = 108;
// PWM_right_val = 108;
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((L_led1 == 1 && M_led0 == 0 && R_led1 == 1)||(L_led1 == 1 && M_led0 == 0 && R_led1 == 1 && R_led2 == 1))
{
stop();
delay(1000);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(50);
// chesi();
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2 )
{
stop();
delay(1000);
while(1);
}
}
}
}
}
}
}
}
//房2
if( Room_num == 2 && EN_room == 1)
{
// PWM_left_val = 105;
// PWM_right_val = 105;
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((L_led1 == 1 && M_led0 == 0 && R_led1 == 1)||(L_led1 == 1 && M_led0 == 0 && R_led1 == 1 && R_led2 == 1))
{
stop();
delay(1000);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(50);
// chesi();
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2 )
{
stop();
delay(1000);
while(1);
}
}
}
}
}
}
}
}
//房3
if( Room_num == 3 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 2)
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(1000);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(40);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2 )
{
flag_back++;
stop();
delay(500);
}
if(flag_back==2)
{
stop();
while(1);
}
}
}
}
}
}
}
}
//房4
if( Room_num == 4 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 2)
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(1000);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2 )
{
flag_back++;
stop();
delay(500);
}
if(flag_back==2)
{
stop();
while(1);
}
}
}
}
}
}
}
}
//房5
if( Room_num == 5 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 3)
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
backward();
delay(40);
stop();
delay(500);
while((uchar)R_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(500);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if( (uchar)R_led1 + (uchar)R_led2 >= 2 )
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if( (uchar)R_led1 + (uchar)R_led2 >= 2 )
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2)
{
flag_back++;
stop();
delay(500);
}
if(flag_back == 3)
{
stop();
while(1);
}
}
}
}
}
}
}
}
}
}
}
}
//房6
if( Room_num == 6 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 3)
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
backward();
delay(40);
stop();
delay(500);
while((uchar)R_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(500);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if( (uchar)L_led1 + (uchar)L_led2 >= 2 )
{
backward();
delay(40);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if( (uchar)L_led1 + (uchar)L_led2 >= 2 )
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2)
{
flag_back++;
stop();
delay(500);
}
if(flag_back == 3)
{
stop();
while(1);
}
}
}
}
}
}
}
}
}
}
}
}
//房7
if( Room_num == 7 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 3)
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
backward();
delay(40);
stop();
delay(500);
while((uchar)R_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(500);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if( (uchar)L_led1 + (uchar)L_led2 >= 2 )
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if( (uchar)R_led1 + (uchar)R_led2 >= 2 )
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2)
{
flag_back++;
stop();
delay(500);
}
if(flag_back == 3)
{
stop();
while(1);
}
}
}
}
}
}
}
}
}
}
}
}
//房8
if( Room_num == 8 && EN_room == 1)
{
go_straight();
if((uchar)L_led2 + (uchar)R_led2 >= 2)
{
flag_go++;
backward();
delay(50);
stop();
delay(500);
}
if(flag_go == 3)
{
backward();
delay(50);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
backward();
delay(40);
stop();
delay(500);
while((uchar)R_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led2 + (uchar)L_led1+ (uchar)R_led1 + (uchar)R_led2 >= 2)
{
stop();
delay(500);
backward();
delay(200);
while((uchar)R_led2 != 1)
{
turn_roud();
}
while(1)
{
go_straight();
if( (uchar)R_led1 + (uchar)R_led2 >= 2 )
{
backward();
delay(40);
right_run();
delay(300);
while((uchar)L_led1 != 1)
{
right_run();
}
while(1)
{
go_straight();
if( (uchar)L_led1 + (uchar)L_led2 >= 2 )
{
backward();
delay(50);
left_run();
delay(300);
while((uchar)L_led1 != 1)
{
left_run();
}
while(1)
{
go_straight();
if((uchar)L_led1 + (uchar)R_led1 >= 2)
{
flag_back++;
stop();
delay(500);
}
if(flag_back == 3)
{
stop();
while(1);
}
}
}
}
}
}
}
}
}
}
}
}
}
}
void intter0() interrupt 1
{
PWM_T++;
if(PWM_T <= PWM_left_val)
{
left_motor_en;
}else{left_motor_dis;}
if(PWM_T <= PWM_right_val)
{
right_motor_en;
}else{ right_motor_dis;}
P0 = leddata[Room_num];
}
代码方面的话,看懂一个病房的原理,就可以同理得出其他病房。
在本次电子综合实践中前前后后忙了差不多半个月时间,合起来也就五六天左右,因为想把绩点刷高的原因,车也不是自己画板子设计,也没准备用32做(主要32还不是很熟练),匆匆忙忙用清翔的51小车做,收获上觉得也不是很多,也就觉得做这车挺好玩的。
遇到的困难也不是很多,也就小车底板的供电不足,一开始一直以为自己的代码逻辑上有毛病,导致两天左右都在调代码,最后通过同学指导了一下发现了问题所在,后通过再添加一个供电稳压模块很好的解决了这个问题,题主最后也拿到了优。
最后挂上一句我喜欢的名言,“不耻最后,即使慢,驰而不息,纵会落后,纵令失败,但一定可以达到它所向往的地方“.----迅哥儿