当前位置:   article > 正文

51单片机课设——避障小车_51单片机小车超声波避障

51单片机小车超声波避障

51单片机课设——避障小车

一、项目基本信息

课程名称单片微机原理及应用
项目主要 内容摘要超声波避障小车 通过避障小车的设计,掌握设计、调试单片机应用系统的方法。任务涉及的知识点包括汇编(C51)程序语言、MCS-51单片机I/O应用、人机接口应用技术等。 要求所设计的避障小车完成以下功能: (1)小车可以前进、后退,左转和右转; (2)能够对小车运动方向上的障碍物进行躲避动作。

二、项目组成员情况

三、项目设计任务书

本项目有两种模式,一种是小车避障模式,一种是红外遥控模式,避障模式是通过HC-SR04来确定前方有无障碍物,HC-SR04检测到一定距离返回单片机,当小于某个值时,单片机会给舵机发送命令朝右转,舵机右转后继续扫描,若右方仍有障碍物时小车就会自动左转并将自动将舵机转回正前方。小车遥控模式则是通过38KHZ红外模块接受信息并解码(38KHZ红外遥控模块可以通过按下按键自动发射一段特定的频段,我们可以通过特定的解码方式来判断按下的按键),然后通过51单片机控制小车的运动。下图是小车的侧视图和俯瞰图

本项目是基于超声波模块的避障小车,除此之外我们还添加了红外遥控模块和oled作为附加功能,本项目对于cpu我们取用51的最小系统板,过程中共采用一个定时器和一个外部中断,其中PWM波的控制和38KHZ红外模块的解码在同一个定时器重断中,HC-SR04则在主程序中直接运行,外部中断0则被用于超声波模块的信号采集。下面将对硬件部分及部分软件进行叙述。

1,最小系统板

对于51单片机只需在XTAL1和XYAL2之间加一个晶振,并在晶振两端各加一个电容与地相接即可,单片机内部有反相器,加上电容与晶振即可起振,复位电路未焊接,主要是通过开关电源进行复位,然后通过TTL转USB模块连接单片机的串行口进行烧录程序。

2,L298N

L298N是专用驱动集成电路,可以增大输出电流,增强输出功率。其输出电流为2A,最高电流4A,最高工作电压50V,其输入端可以与单片机直接相联,从而很方便地受单片机控制。当驱动直流电机时,可以直接控制步进电机,并可以实现电机正转与反转并通过对ENA和ENB引脚输入PWM波来控制电机的速度,实现此功能只需改变输入端的逻辑电平。

​ L298可驱动2个电动机,OUT1,OUT2和OUT3,OUT4之间可分别接电动机,本实验装置我们选用驱动一台电动机。5,7,10,12脚接输入控制电平,控制电机的正反转。EnA,EnB接控制使能端,控制电机的停转。下图是L298N的使用逻辑表及其外形图。

3,舵机及HC-SR04模块

对于舵机,只需给它一个合适的PWM波,便可实现对其旋转角度的控制,其主要有三个引脚,别为VCC,GND和下面主要详细叙述超声波测距。

超声波测距原理:超声波测距是通过不断检测超声波发射后遇到障碍物所反射的回波, 从而测出发射和接收回波的时间差Δt , 然后求出距离S 。在速度v 已知的情况下,距离S 的计算,公式如下:S = vΔt/ 2在空气中,常温下超声波的传播速度是334 米/秒,但其传播速度V 易受空气中温度、湿度、压强等因素的影响,其中受温度的影响较大,如温度每升高1 ℃, 声速增加约0. 6 米/ 秒。因此在测距精度要求很高的情况下, 应通过温度补偿的方法对传播速度加以校正。已知现场环境温度T 时, 超声波传播速度V 的计算公式如下:

V = 331. 5+0.607T

这样, 只要测得超声波发射和接收回波的时间差Δt 以及现场环境温度T,就可以精确计算出发射点到障碍物之间的距离。

HC-SR04超声波测距模块简介:HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。HC-SR04超声波测距模块实物图如下:

HC-SR04超声波测距模块工作原理:

1、采用IO 触发测距,给控制端至少10us 的高电平信号;

2、模块自动发送8个40khz 的方波,自动检测是否有信号返回;

3、有信号返回,通过IO 输出高电平,高电平持续时间就是超声波从发射到返回时间.测试距离=(高电平时间*声速(340M/S))/2,其时序图如下:

4,38KHZ 红外模块

发射器采用红外发光二级管发射红外光波;接收器由红外接收二极管、三极管或硅光电池组成,它们将发射器发射的红外光接收转换为相应的电信号。主要采用NEC协议来解出按了什么键。

​ 红外遥控器采用的NEC 载波频率为 38Khz,数据帧格式主要是引导码 +识别码 + 识别码反码 + 键值 + 键值反码 + 结束码的格式,其中引导码为9ms 高电平 + 4.5ms 低电平的频段,识别码中0码为0.56 ms 高电平 + 0.56 ms 低电平格式,1 码 为 0.56ms 高电平 + 1.68 ms 低电平的格式,结束码则是0.56ms 的高电平形式,总体发送格式如下图:

对于这种模式,遥控解码就只需要获取每个波形高低电平时长,就可以知道收到的数据是1还是0,最后读取整个数据即可。由于51单片机只能设置下降沿捕获,故我们可以根据其中各位高低电平的总体时长来解码,解码具体过程如下:

获取每个波形高低电平时长利用定时器去获取,初始化时,将定时器通道配置为下降沿捕获,当捕获到一个下降沿时,计数器等清0,即得到捕获一位码值的时间,然后如果码值大于(码值为0的总时间+码值为1的总时间)/则判定为高电平,否则判定为低电平。

的重复码则判断当收到重复码时,如果溢出中断标志>9时,就代表重复码收完了。

4,OLED模块

我们的oled模块是IIC接口,引脚分别为VCC,GND,SCL,SDA,是基于I2C通讯应用的模块。

通常情况下,一个完整的I2C通信过程包括:开始条件,地址传送,数据传送,停止条件等4个部分。

主机在 SCL 线上输出串行时钟信号,数据在 SDA 线上进行传输,每传输一个字节(最高位 MSB 开始传输)后面跟随一个应答位,一个 SCL 时钟脉冲传输一个数据位。

当总线上的主机都不驱动总线,总线进入空闲状态, SCL 和 SDA 都为高电平。总线空闲状态下总线上设备都可以通过发送开始条件启动通信。

当 SCL 线为高时,SDA 线上出现由高到低的信号,表明总线上产生了起始信号。 SDA 线上出现由低到高的信号,表明总线上产生了停止信号,如下图所示:

而后根据类似的电平变化进行通讯传输地址、数据和应答信号。

对于oled的字模取用可以通过下载相应的字库或字模取用软件来进行使用。

五、项目设计内容

5.1主控代码

5.1.1引脚预览

/*********************************************************************

sbit OC1_PWM = P1^4;  左 

sbit OC2_PWM = P1^5;  右     

sbit Ain1_R = P2^0; //rear   sbit Trig = P1^0;  //超声波测距模块 

sbit Ain2_R = P2^1;       sbit Echo = P1^1;  

sbit Bin1_R = P2^2; 

sbit Bin2_R = P2^3;         

 

sbit OC3_PWM = P1^7; 右      sbit Engine_PWM = P1^3; //舵机  

sbit OC4_PWM = P1^6; 左 

sbit Ain1_F = P2^4; //front 

sbit Ain2_F = P2^5;         sbit OLED_SCL=P0^0; //OLED显示                 

sbit Bin1_F = P2^6;         sbit OLED_SDIN=P0^1; 

sbit Bin2_F = P2^7; 

 

**********************************************************************/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

5.1.2超声波避障主控

void Run(void)  

{ 

  OLED_ShowNum(0,0,Distance,3,16); 

  if(Angle == 3 && Distance >= 30) //舵机90度且测距大于30 

  { 

​    GoStraight(7,1);//直走 

​    Hcsr04_Init(); 

​    GetDistance(); 

​    OLED_ShowNum(0,0,Distance,3,16);     

  } 

  else if(Angle == 3 && Distance < 30)//舵机90度且测距小于30 

  { 

​    Stop();    //停止 

​    SetAngle(0); 

​    Delay(500); 

​    Hcsr04_Init(); 

​    GetDistance(); 

​    OLED_ShowNum(0,0,Distance,3,16); 

​    if(Angle == 1 && Distance < 30)//舵机0度且测距小于30 

​    { 

​      Rotation(0,1,10,1);  //右轮快 左转  

​    } 

​    else 

​    { 

​      Rotation(10,1,0,1);  //左轮快 右转 

​    } 

​    SetAngle(90); //舵机90度 
      
​    Delay(500);      

  } 

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

5.1.3红外主控代码

  while(1)//mode模式变量 Moving遥控标志变量

  {''''''' 

​    else if(mode==1) //如果是遥控模式 {if(Moving==0) //停止 {Stop();}else if(Moving==1)//前进 {GoStraight(10,1);}else if(Moving==2)//后退 {GoStraight(10,0);}else if(Moving==3)//左转 {Rotation(0,1,10,1);}else if(Moving==4)//右转 {Rotation(10,1,0,1);}} 

  }


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

5.2硬件外设

5.2.1超声波模块(定时器0)

void Hcsr04_Init(void);//发射超声波 

void GetDistance(void);//根据接收到的超声波算出距离

void Time0_Init(void);//定时器0初始化  (记录有效回收电平时长)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5.2.2 PWM输出(使用定时器1)

void PWM_Timer1Init(void); //定时器1 初始化 

void SetAngle(unsigned char Value); //舵机PWM控制 

void SetCompare(unsigned char Y_Position, unsigned char OC1,unsigned char OC2);  

 

void timer1_isr(void) interrupt 3 //0.5ms ½øÒ»´ÎÖÐ¶Ï 

{ 

  TL1 = 0x34;         

  TH1 = 0xFE;          

   

  //steer PWM 用于控制舵机 占空比由Angle调节 

   if(counter_num < Angle) 

​    Engine_PWM = 1; 

  else 

​    Engine_PWM = 0; 

   

  //OC1 PWM 用于控制电机 

  if(counter_num < OC1_Compare) 

​    OC1_PWM = 1; 

  else 

​    OC1_PWM = 0; 

   

  //OC2 PWM 

  if(counter_num < OC2_Compare) 

​    OC2_PWM = 1; 

  else 

​    OC2_PWM = 0;   

   

  //OC2 PWM 

  if(counter_num < OC3_Compare) 

​    OC3_PWM = 1; 

  else 

​    OC3_PWM = 0;   

   

  //OC2 PWM 

  if(counter_num < OC4_Compare) 

​    OC4_PWM = 1; 

  else 

​    OC4_PWM = 0; 

   

  //define Period_falg 40 

  counter_num++; 

  if(counter_num == Period_falg) 

  { 

​    counter_num = 0; 

  } 

  irtime=irtime+2; //用于红外的解码 

//   OLED_ShowNum(0,5,irtime,3,16); 

}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97

5.2.3 舵机模块

unsigned char angle_flag[6]={1,2,3,4,5}; 

void SetAngle(unsigned char Value) 

{ 

  switch(Value) 

  {case 0:Angle = angle_flag[0];break;case 45:Angle = angle_flag[1];break;case 90:Angle = angle_flag[2];break;case 135:Angle = angle_flag[3];break;case 180:Angle = angle_flag[4];break;default: break; 

  } 

} 

//0°------1   45°-------2 

//90°------3   135°------4  180°-------5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

5.2.4 红外遥控模块(使用了外部中断0 和定时器1)

void EX0init(void);//外部中断0初始化 (用于读取每一位的时间) 

void Irpro(void); //将32位电平解码 并将数据放在IRcord[]中 

void Ir_work(void);//根据解码值执行相应的程序 

void receive(void);//判断是否解码成功,如果成功执行Ir_work()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5.2.5 OLED模块

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);//显示字符 

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);//显示数字 

void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);//显示字符串
  • 1
  • 2
  • 3
  • 4
  • 5

5.2.6电机

/*****************************

设置轮子的方向——向前、向后

******************************/

void SetWheelDir(uchar Y_Position, uchar X, uchar In1, uchar In2); 
  • 1

/*****************************

限制轮子的速度0-40

******************************/

void SpeedLimit(char Speed); 

void GoStraight(char Speed, char dir);//dir=1直走  dir=0后退 
  • 1
  • 2
  • 3

/*****************************

Speed_A左轮速度 Dir_A左轮方向

Speed_B右轮速度 Dir_B右轮方向

******************************/

void Rotation(char Speed_A, char Dir_A, char Speed_B, char Dir_B); 

void Stop(void);//停止

  • 1
  • 2
  • 3
  • 4

******************/

void SetWheelDir(uchar Y_Position, uchar X, uchar In1, uchar In2); 
  • 1

/*****************************

限制轮子的速度0-40

******************************/

void SpeedLimit(char Speed); 

void GoStraight(char Speed, char dir);//dir=1直走  dir=0后退 
  • 1
  • 2
  • 3

/*****************************

Speed_A左轮速度 Dir_A左轮方向

Speed_B右轮速度 Dir_B右轮方向

******************************/

void Rotation(char Speed_A, char Dir_A, char Speed_B, char Dir_B); 

void Stop(void);//停止

  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/470779
推荐阅读
相关标签
  

闽ICP备14008679号