找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 631|回复: 1
打印 上一主题 下一主题
收起左侧

51单片机L298N循迹避障功能智能小车程序设计

[复制链接]
跳转到指定楼层
楼主
该设计是在单片机小车为基础开发的循迹系统。小车由L298N电机驱动模块、红外循迹模块,由STC89C52RC控制芯片完成各模块之间的连接与控制。按键能传送相应命令,对小车移动进行灵活巧妙的控制。当系统启动后,通过按键来选择红外循迹的图形从而改变小车的移动方向。在自动模式下,能沿着红外循迹到地面黑线运动,能躲避障碍物。具体设计模块图如图1-1所示。  
制作出来的实物图如下:


电路原理图如下:


4.1 主程序设计
在软件设计中,采用了PWM 调速、信息融合技术等,编写程序时使用了C/C++语言,实现相同功能时只需要更简单的语句,循迹模块主程序为判断语句,判断光电开关的状态,如果其中一个光电传感器未接收到反射信号(黑线或障碍物吸收了红外光线),单片机使用PWM 算法调控,通过控制电流在一个周期中的占空比,立刻调整左右轮差速实现方向调控,实现转弯循迹,如果两个光电传感器同时未接收到反射信号,单片机输出电平停止直流电机的运转,实现避障停车。通过调用各个子函数实现智能小车的功能,经实践检测程序的整体可读性较好,方便移植。
4.2 电机驱动程序
本设计采用 L298N电机驱动模块。由L298N模块各个端口的逻辑关系可知,当 ENA与ENB为 1 时,通过控制 IN1、IN2、IN3、IN4 端口电平的高低来改变电机的转向。电机方向控制逻辑表如表3-1。同时单片机还可以产生PWM波,通过调节占空比的方式来控制电机的转速。
4.3 红外循迹程序
初始化结束后,接收到循迹指令,小车前方有一对红外对管,分别置于黑线两侧,红外管相对于黑线有 2mm到 4mm的距离。当两对红外管都能探测到黑线时,汽车就会一直向前行驶。当左侧传感器无法检测到黑线时,左侧电机向前旋转,右侧电机向后旋转,利用差速原理实现车辆的向右转向,直到检测到左侧的黑线后,小车继续沿直线行驶。同样,当无法在右侧检测到黑线时,右电机向左旋转,左电机向右旋转,实现车辆的向左转向,直到在右侧检测到黑线,小车继续直线行驶。循迹流程如图3-1所示。
4.4 按键扫描程序
只要使用单片机,按键检测基本上是一定要实现的功能。按键检测要好用,最重要的是实时和去抖。初学者往往会在主循环调用按键检测程序(实时)并利用延时去抖(准确)。这种在主循环内延时的做法对整个程序非常不友好,也非常不高效。因此我们将其做成一个按键检测的模块化程序,方便调用和调试

单片机源程序如下:
  1. #include <REGX52.H>
  2. #include "LCD1602.h"
  3. #include "Delay.h"
  4. #include "Timer0.h"
  5. #include "CCDR.h"
  6. #include "Key.h"
  7. sbit MotorA=P1^4;
  8. sbit MotorB=P1^5;

  9. sbit A01=P1^0;
  10. sbit A02=P1^1;
  11. sbit B01=P1^2;
  12. sbit B02=P1^3;

  13. unsigned char Sr=1;////半径(无限制)
  14. unsigned char Rr=10;////半径(1~80)

  15. unsigned char Counter,CompareA,CompareB;        //计数值和比较值,用于输出PWM
  16. unsigned char KeyNum,m,
  17.         SpeedA=13,
  18.   SpeedB=10;


  19. void cwA(int a)///正
  20. {
  21.                 A01=0;
  22.     A02=1;
  23.     CompareA=a;
  24. }
  25. void ccwA(int a)///反
  26. {
  27.                 A01=1;
  28.     A02=0;
  29.     CompareA=a;
  30. }
  31.        
  32. void cwB(int b)///反
  33. {
  34.                 B01=1;
  35.     B02=0;
  36.     CompareB=b;
  37. }
  38. void ccwB(int b)///正
  39. {
  40.                 B01=0;
  41.     B02=1;
  42.     CompareB=b;
  43. }

  44. void qian(void)
  45. {
  46.          cwA(SpeedA);
  47.          cwB(SpeedB);
  48. }
  49. void hou (void)
  50. {
  51.          ccwA(SpeedA);
  52.          ccwB(SpeedB);
  53. }
  54. void you(void)
  55. {
  56.         cwA(SpeedA);
  57.         ccwB(SpeedB);
  58. }
  59. void zuo(void)
  60. {
  61.         ccwA(SpeedA);
  62.         cwB(SpeedB);
  63. }
  64. void square()
  65. {
  66.         qian();
  67.         time(Sr);
  68.   zuo();
  69.         Delay(600);

  70. }
  71. void round()
  72. {
  73.          cwA(SpeedA);
  74.          cwB(SpeedB+Rr);
  75. }




  76. void main()
  77. {
  78.                 Timer0_Init();
  79. //          LCD_Init();                                                //LCD初始化
  80. //          LCD_ShowChar(1,1,'A');                        //在1行1列显示字符A
  81. //          LCD_ShowString(1,3,"Hello");        //在1行3列显示字符串Hello
  82. //        LCD_ShowNum(1,9,66,2);                        //在1行9列显示数字66,长度为2
  83. //        LCD_ShowSignedNum(1,12,-88,2);        //在1行12列显示有符号数字-88,长度为2
  84. //        LCD_ShowHexNum(2,1,0xA5,2);                //在2行1列显示十六进制数字0xA5,长度为2
  85. //        LCD_ShowBinNum(2,4,0xA5,8);                //在2行4列显示二进制数字0xA5,长度为8
  86. //        LCD_ShowChar(2,13,0xDF);                //在2行13列显示编码为0xDF的字符
  87. //        LCD_ShowChar(2,14,'C');                        //在2行14列显示字符C
  88.         while(1)
  89.         {
  90.                 KeyNum=Key();
  91.                 if(KeyNum==1)
  92.                 {
  93.       m=0;
  94.                 }               
  95.                 if(KeyNum==2)
  96.                 {
  97.       m=1;
  98.                 }
  99.                 if(m==1)
  100.                 {
  101. //                 LCD_ShowString(1,3,"square");                        //在1行1列显示字符A
  102.      square();
  103.                 }
  104.                 if(m==0)
  105.                 {
  106. //                        LCD_ShowString(1,3,"round");                        //在1行1列显示字符A
  107.             round();
  108.                 }

  109.         }
  110. }
  111. void Timer0_Routine() interrupt 1
  112. {
  113.         TL0 = 0x9C;                //设置定时初值
  114.         TH0 = 0xFF;                //设置定时初值
  115.         Counter++;
  116.         Counter%=100;        //计数值变化范围限制在0~99
  117.         if(Counter<CompareA)        //计数值小于比较值
  118.         {
  119.                 MotorA=1;                //输出1
  120.         }
  121.         else                                //计数值大于比较值
  122.         {
  123.                 MotorA=0;                //输出0
  124.         }
  125.         if(Counter<CompareB)        //计数值小于比较值
  126.         {
  127.                 MotorB=1;                //输出1
  128.         }
  129.         else                                //计数值大于比较值
  130.         {
  131.                 MotorB=0;                //输出0
  132.         }
  133. }

复制代码
原理图PCB: 无
仿真: 无
代码: 51单片机电子绘图小车.7z (1.57 MB, 下载次数: 15)

视频.7z

5.85 MB, 下载次数: 4, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:1107914 发表于 2024-1-4 10:07 | 只看该作者
求 怎么把里面显示日期的代码改成显示学号的啊...静态显示就行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表