基于51单片机的巡线机器人
目录:
1.总体介绍
2.机件部分
2.1底盘制作
2.2底盘布局
3.电控部分
3.1主控芯片
3.2电路驱动
3.3功能模块
4代码部分
1.总体介绍
小车所需实体部件:主控芯片AT89C51,万向轮,两个橡胶车胎,小车底盘,L298N电机驱动板模块,两个直流电机(马达),杜邦线,红外传感器模块,最小系统板,电池,电池盒,安装主板的小零件若干。
底盘采用了市面上常见的亚力克板小车底盘,通过小零件组装小车轮胎马达,万向轮,放置电池盒,把主控芯片装于合适位置,安上L298N电路驱动模块把单片机信号转换为电机可以接受的信号从而控制电机转速。为实现循迹功能,我们也要购买红外传感器模块。最后通过将写好代码录入单片机里实现小车功能。加购最小系统板,这样可以避免焊接的问题
驱动与各部分的连接简介:
输出A、B:分别接到左右马达上,通过使能A、使能B来控制电机正常工作(接高电平为正常工作);
单片机IO控制输入(即IN1-IN4):用来控制马达正反转。接单片机引脚,通过在程序中给引脚高低电平实现正转或反转;
12V输入:接电池盒正极;
5V输入:接单片机VCC,给单片机供电;
电源地(即GND):把电池盒负极和单片机的GND一起接入。
总体外观:
电路原理:
2.机件部分
对于基本的51循迹小车,机件
部分主要是底盘部分,可以简单分为两部分:底盘制作、底盘布局。
2.1底盘制作
因为底盘并不是制作51循迹小车的关键,且新手缺乏相关知识与工具,配套组装零件也难于制作,所以就没有自己制作底盘,淘宝上选购省时省力。
轮子选择:
目前巡线小车常用有四轮和三轮两种,四轮小车,前轮为舵机转向,后两轮为驱动轮 。三轮小车,前轮为万向轮或牛眼轮,后两轮为驱动轮 在实践的过程中,转向角度需求可能较大。,这种情况下三轮小车前轮为从动轮的更占优势,转向更为方便,而舵机前轮后轮驱动的车型转向就无法像三轮一般丝滑,略显笨重,虽然也可以实现。
小车多种多样,如有两个电机的四驱小车适合爬坡、走沙石路等,但是过弯容易卡死。后轮有两个电机的三轮小车,过弯灵活但是重心不稳,两个电机的四轮后驱小车,过弯灵活且稳定。
本次实验小车采用三轮,前万向轮后橡胶轮,优点是信号采样时间短,性能良好,在低速时稳定性高,不易窜道,算法简单,控制灵活。
电机选择:
TT马达是一种新型的电机,,一种特殊的直线电机,也称为推进式直线电机或推进式线性电机。是一种可以将电能直接转化为线性运动的电动机。它的工作原理是基于磁场的变化来实现电机的转动。TT马达的名称来源于其两个主要部分:转子和定子。转子是电机的旋转部分,而定子是电机的静止部分。TT马达的转子和定子之间有一个空气间隙,这个间隙是电机的关键部分。
TT马达的工作原理是基于磁场的变化来实现电机的转动。当电流通过定子线圈时,它会产生一个磁场。这个磁场会吸引转子上的磁铁,使其旋转。当转子旋转时,它会改变磁场的方向,这会导致定子线圈中的电流方向发生变化。这个变化会导致磁场的方向发生变化,从而使转子继续旋转。基于洛伦兹力和法拉第电磁感应定律,当电流通过TT电机的线圈时,会在线圈周围产生一个磁场,而当线圈在磁场中运动时,磁场会在线圈内产生电动势。
直流减速电机可以提供更大的转矩和更低的转速,这对于小车的运动控制更加有利。另外,直流减速电机也更加稳定,能够保证小车的行驶速度和转向精度。
直流电机的转速较高,转矩较小,如果直接使用直流电机作为小车的驱动电机,需要使用减速器来降低转速并增加转矩。但在降低转速的同时,也增加了电机的输出转矩,这有利于小车的稳定行驶和转向。
直流减速电机也更加可靠,它们使用的零部件相对较少,结构简单,易于维护和修理。直流减速电机的控制也相对简单,易于实现自动化控制。
TT马达,即齿轮减速电机,是在普通直流电机的基础上,加上配套齿轮减速箱,齿轮减速箱的作用是,提供较低的转速,较大的力矩。TT马达的优点:组装简单,扩展性能强,价格低廉;缺点:输出功率小,转速小,效率低,。
综合考虑,直流减速电机是智能小车常用的驱动电机,而TT马达电机能很好胜任小车驱动。
2.2底盘布局
底盘布局简而言之就是各种器件的分布情况。对于循迹小车而言主要就是红外探头的分布情况,其余零器件只要保证接线时自己不混乱就行。
红外探头的放置需要靠前。如果红外探头放在小车车身中间,遇到拐角时,小车转弯便会不灵活,半个车身越过弯道才会开始执行转弯命令,
放在后面更不用说。同时根据其工作原理,红外探头的位置需要接近地面,避免阳光直射,便于其更加稳定、灵敏的接受信号、判断黑线。
位置分布需要看情况。对于多个红外探头,如果仅需实现循迹功能,可以直接并排间隔或不间隔放置。探头的数量多可以保证循迹的精确度。
(不是越多越好)如果要制作的小车有其他任务与地图限制,则需要调整部分红外探头位置。
3.电路控制部分
51循迹小车的电控部分主要可以分为三部分——主控芯片、电路驱动、功能模块。
3.1主控芯片
本小车采取AT89C51作为主控芯片,为图便捷购买最小系统板。焊接技术有基础可以自己购买相关物品焊板子。
单片机是一种集成电路芯片,包括处理器、存储器和各种输入/输出接口。它能够通过自身的编程,将数据运算与处理能力集成到芯片中,控制外围电路和设备的操作,通常应用于自动控制、嵌入式系统、智能家居、机器人、无人机、汽车电子等各种领域。
选择单片机要根据自己的需求和学习目的来确定,下面就对51单片机、Arduino和STM32这几种小车常用主控芯片进行简单的介绍,便于进行合理的选择。
51单片机,也称作8051单片机,是一种基于哈佛结构的微控制器,由英特尔公司在1980年推出。它以其简单易用、性价比高的特点,在工业控制、自动化、智能家居、安防监控等领域得到了广泛应用。
51单片机采用CISC指令集,运行频率较低,一般为12MHz以下,但是由于其精简的指令集和优秀的编译器支持,可以达到较高的效率。它具有4K64K的Flash存储器、128B2KB的RAM存储器、2~5个定时器/计数器、2个串行口、一个并行口和中断控制器等基本模块。
在51单片机的学习过程中,需要掌握汇编语言和C语言等相关知识,以及常用的外设接口和编程技巧。常见的开发环境包括Keil C51和SDCC等,其中Keil C51是一款非常常用的51单片机编程环境,它提供了完整的编译、调试、下载等功能,并且支持多种单片机型号。
总体来说,51单片机是一种比较传统的单片机,虽然功能有限,但是具有使用广泛和资料丰富等优点,特别适合初学者进行学习和实践。如果你对硬件感兴趣,并且想深入了解单片机的工作原理和底层实现,那么学习51单片机可能是不错的选择。
Arduino是一种基于开源软硬件的单板微控制器,主要用于制作简单的互动式电子项目。它采用了简单易学的编程语言和开发环境,使得初学者和爱好者可以快速地开发自己的电子项目。
Arduino主板采用了ATmega系列单片机,这些单片机具有丰富的外设和通用IO口,使得它们可以轻松地连接各种传感器、执行器和外围设备。此外,Arduino主板还带有USB接口,可以直接与计算机通信,方便程序烧录和数据传输。
Arduino的编程语言是基于C/C++语言的,但是简化了许多语法,使得编程变得更加易学易用。开发环境可以在Windows、Mac OS X和Linux等操作系统下运行,并且支持多种Arduino板型,具有直观的图形化用户界面,可以通过拖拽和编程方式快速构建和测试自己的项目。
Arduino的开源性质使得其具有丰富的社区资源和开发库,有数百个开源项目和成千上万的用户共享库可供使用。因此,Arduino适合那些想要快速地搭建原型并进行实验、学习和创新的电子爱好者和初学者。
总体来说,Arduino具有简单易学、兼容性好、资源丰富和成本低廉等优点。如果你对电子和编程感兴趣,并且想快速搭建自己的电子项目,那么学习Arduino可能是不错的选择。
STM32是由意法半导体(STMicroelectronics)推出的一款基于ARM Cortex-M内核的32位微控制器,具有高性能、低功耗、高集成度和广泛的应用领域。STM32微控制器系列包含了多个系列,每个系列有多个不同的型号和封装,可以满足不同应用场景的需求。
STM32系列微控制器提供了丰富的外设和接口,如ADC、DAC、PWM、定时器、串口、CAN、USB等,同时还支持多种通信协议,如SPI、I2C、UART等。STM32的外设和接口非常灵活,可以方便地与各种传感器、执行器和外围设备进行通信和控制。
STM32的编程语言是C语言和汇编语言,用户可以使用Keil、IAR等集成开发环境进行编程和调试。同时,STM32也提供了ST-LINK等调试工具和软件,支持在线调试和仿真,可以帮助用户快速定位和解决问题。
STM32的优点在于高性能、低功耗、高集成度、丰富的外设和接口、广泛的应用领域以及可靠的质量和稳定性等方面。因此,它广泛应用于工业自动化、医疗设备、安防监控、智能家居、四轴飞行器、机器人等领域。
总体来说,STM32适合具有一定的电子和编程基础的工程师、学生和爱好者学习和应用。如果你需要进行复杂的控制和通信任务,需要更高的性能和可靠性,那么学习STM32可能是不错的选择。
综上所述,根据个人对工作原理了解有一定需求,希望使用芯片有更多别的小制作,另外曾使用过keil,proteus绘制C51原理图比较熟悉,51单片机使用广泛参考资料丰富,成本也偏低,故选择51单片机。
系统板:
购买的系统板,需要观察一下板子上的晶振是否稳定,这对后续的程序有影响
3.2电路驱动
单片机信号是无法直接驱动电机的,因此我们需要一块电路驱动模块来作为中转站,将单片机发出的信号转换为电机可以接受的信号。在此,我们选用L298N驱动,它不仅可以接至12v(即拥有更强的驱动能力),而且有过电流保护功能,当出现电机卡死时,可以保护电路和电机等。且自带7805降压模块可直接给单片机供电。
选用如图所示的正常的二路L298N电路驱动模块就可以了.
关于如何使用L298N控制电机转速等问题:
由于我们的循迹小车是不能直接转动轮胎方向的,所以我们要使小车两边轮胎的差速来达到转弯的目的。现在来讨论差速能够实现的转弯情况。
1.如果两边轮胎差速不大,且朝同一个方向转,这样只能实现小幅度的转动,可以用于小车的复位等情况。
2.如果两边轮胎旋转差速大,甚至一边正转、一边倒转,这样就能够实现90°的转弯,大转弯一般用于过直角弯。
制造差速就是调整电机的转速。可以改变通过电机的电流、或者施加于电机上的电压来使电机转速改变。电流的改变与电压的改变使一样的,在这里我们选择改变电压,也就是改变单片机发出的信号。如果单片机发出信号是稳定的、不断的,如图4-1所示,就会使一定时间内电机都有恒定电压,全速前进。那么想要调整电机转速,我们就只需要调整单片机一定周期内发出信号的时间,如图4-2让其没有电压的时间增长,就可以减慢转速。由于单片机能够定义周期都很短暂,所以人眼是不能够看到电机一转一停的情况,只能看到宏观表现——电机转速改变。更加学术的表达就是PWM信号调节直流电机转速。
PWM脉冲是一种脉冲宽度调制技术,通过调节脉冲的高低电平时间比例来控制电路的平均电平值,来对输出的波形进行控制,获得模拟参数,其中有几个比较重要的参数分别是频率、占空比和精度,频率等于周期频率除以1,这个信号的周期必须极短,频率需要很快;占空比是指高电平在整个周期内占的时间,精度指占空比变化的步距。单片机IO口输出的是数字信号,即输出高低电平,PWM通过改变IO口输出的占空比使用模拟电压信号。PWM在电子设备中的应用非常广泛,如电源控制、调光调速、电机驱动等。
通过PWM脉冲控制电机转速是一种最常用的方法。电机转速是指电机旋转运动所需的时间,一般指电机额定功率下的转速,能以转数/时间或者秒/圈等形式表示。控制电机转速的方法有很多种,如改变电压大小、改变电机极数、改变负载等。
单片机通过PWM脉冲控制电机转速的原理是:使用单片机内部定时器产生一定频率的脉冲,根据脉冲的占空比控制电机的平均电压大小,从而实现对电机的旋转速度进行控制。具体来说,单片机通过计算占空比,即高电平脉冲的占用时间或低电平脉冲的占用时间,来控制PWM脉冲的周期和高电平脉冲的持续时间,从而控制电机转速。
例如,设定一个占空比为70%的PWM脉冲,单片机将产生若干个高电平脉冲,持续时间为70%的周期,即高电平持续时间为100微秒,周期为142.85微秒。这样,电机在不改变电源电压的前提下,转速降低到原来的70%。
总之,单片机通过PWM脉冲控制电机转速,可以实现精准、高效、智能化的电机控制,被广泛应用于数控机床、电动车、机器人、家用电器等领域。
PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码
图1 一个周期内稳定输出电压
图2 改变一个周期内输出电压时间
那么如何改变一个周期内单片机输出产生电压信号的时间呢。如图3所示,我们可以设置一个定时自增的数和一个固定的数。当定时自增的数大于固定数时,不产生信号或者产生信号。小于时则相反就可以达到图2的效果。
图3 改变输出时间的方法
对于有输出信号的部分占一个周期的时间,我们称之为占空比。调节pwm信号来调节直流电机转速,就是调节pwm信号中一个周期内输出电压的多少,也就是调节占空比。下面就来定义一下各个电机的占空比和自增的数(这里的pwmxx)。同时配置好图3所示的函数,这里仅放了一个电机的调节函数,其余电机同理即可。
unsigned char zkbL1 = 0;
unsigned char zkbR1 = 0;
unsigned char zkbL2 = 0;
unsigned char zkbR2 = 0;
unsigned char zkbD1 = 0;
unsigned char pwmL1 = 0;
unsigned char pwmR1 = 0;
unsigned char pwmL2 = 0;
unsigned char pwmR2 = 0;
//调占空比调速
void Pwm_L1 (void)//左前电机调速
{
pwmL1%=20;
if(pwmL1<=zkbL1)
{
L_EnL1 = 1;
}else
{
L_EnL1 = 0;
}
}
void Timer0Init(void) //10us@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xF7; //设置定时初始值
TH0 = 0xFF; //设置定时初始值
TF0 = 0; //清除TF0标志
ET0 = 1;
EA = 1;
TR0 = 1; //定时器0开始计时
}
//定时器中断服务产生pwm信号
void Timer0() interrupt 1
{
TR0 = 0;//关闭定时器
TH0 = 0xF7;//初始化便于后续计时
TL0 = 0xFF;//初始化便于后续计时
pwmL1++;
pwmR1++;
Pwm_L1;
Pwm_R1;
TR0 = 1;//开启定时器
}
有了这些,我们可以开始编写完整的运动函数。上面的代码都可以放在同一个.h文件中。在编写主要循迹代码时记得引用该头文件就行。
3.3功能模块
本小车主要实现巡线功能,采用红外传感器。
自动巡线小车常用的传感器主要包括红外传感器、超声波传感器、灰度传感器等。
超声波传感器是将超声波信号转换成其它能量信号(通常是电信号)的传感器。超声波是振动频率高于20kHz的机械波,传感器发射超声波脉冲,当遇到被测物时,该超声波脉冲会被反射回来,传感器接收到反射波并通过计算该脉冲波的传播时间,就可计算出传感器和被测物之间的距离。
超声波传感器结构简单,制造方便,穿透力强,不容易受环境的干扰。某些应用精度更高,穿透性强,灵敏度高。
但超声波传感器主要用于检测障碍物,本小车功能偏向巡线,故不合适。
一、 灰度传感器和红外传感器的原理
灰度传感器(又称反光度传感器)能够感知亮度变化,一般会将黑色和白色两种颜色作为对比,根据不同反光度的灰度条判断车体运动方向。
红外传感器则是通过反射红外光线来感知运动方向。
二.灰度传感器和红外传感器的优缺点
灰度传感器适用于直线运动,灵敏度高,检测范围广,对环境光线干扰较小。但是,它容易受路面颜色和光线影响,精度不高,需要定期校准。而红外传感器能够适应路面颜色变化,精度高,可以用于弯道和复杂路线的运动。但是,受环境光影响较大,需要用障蔽罩进行屏蔽。
三、灰度传感器和红外传感器的应用场景
灰度传感器适用于简单循迹场景,如直线行驶、左右转弯等;而红外传感器适用于复杂循迹场景,如八字形循迹、环形循迹、斜线循迹等。
四、小车循迹方案选择
选择什么样的传感器方案,要根据物体运动的复杂度和要求精度决定。如果只是进行简单的直线和左右转弯,灰度传感器是个不错的选择。而如果循迹路线比较复杂,需要精细控制,那么红外传感器是不二之选。本小车希望实现较复杂的循迹路线,红外循迹精度高,成本低廉,是不二之选。
巡线的原理:
巡线机器人(LFR)跟随一条线,为了跟随一条线,机器人必须首先检测这条线。现在的问题是如何在LFR中实现线路检测机制。我们都知道,光在白色表面上的反射最大,在黑色表面上最小,因为黑色表面吸收的光量最大。因此,我们将使用光的这种特性来检测线。为了检测光,可以使用LDR(光相关电阻)或红外传感器。对于这个项目,我们将使用红外传感器,因为它的精度更高。为了检测线,我们使用两个红外传感器,一个放置在机器人的左侧,另一个位于机器人的右侧,如下图所示。然后,我们将机器人放在线上,使线位于两个传感器的中间。
红外传感器由两个元件组成,发射器和接收器。发射器基本上是一个红外LED,它产生信号,红外接收器是一个光电二极管,它感测发射器产生的信号。红外传感器在物体上发射红外光,击中黑色部分的光被吸收,从而产生低输出,但击中白色部分的光反射回发射器,然后由红外接收器检测到,从而提供模拟输出。使用所述原理,我们通过驱动连接到电机的轮子来控制机器人的运动,电机由微控制器控制。
巡线器机器人如何导航?
一个典型的巡线机器人有两组电机,我们称它们为左电机和右电机。两个电机分别根据从左侧和右侧传感器接收到的信号旋转。机器人需要执行 4 组运动,包括向前移动、向左转、向右转和停止。下面对这些案例进行了描述。
红外传感器由两个元件组成,发射器和接收器。发射器基本上是一个红外LED,它产生信号,红外接收器是一个光电二极管,它感测发射器产生的信号。红外传感器在物体上发射红外光,击中黑色部分的光被吸收,从而产生低输出,但击中白色部分的光反射回发射器,然后由红外接收器检测到,从而提供模拟输出。使用所述原理,我们通过驱动连接到电机的轮子来控制机器人的运动,电机由微控制器控制。
巡线器机器人如何导航?
一个典型的巡线机器人有两组电机,我们称它们为左电机和右电机。两个电机分别根据从左侧和右侧传感器接收到的信号旋转。机器人需要执行 4 组运动,包括向前移动、向左转、向右转和停止。下面对这些案例进行了描述。
向前移动:
在这种情况下,当两个传感器都在白色表面上并且线位于两个传感器之间时,机器人应该向前移动,即两个电机都应该旋转,使机器人向前移动(实际上两个电机都应该以相反的方向旋转,因为电机是反向安装。但为了简单起见,我们将电机称为向前旋转。
左转:
在这种情况下,左侧传感器位于暗线顶部,而右侧传感器位于白色部分,因此左侧传感器检测到黑线并向微控制器发出信号。由于信号来自左侧传感器,因此机器人应转向左侧方向。因此,左电机向后旋转,右电机向前旋转。因此,机器人转向左侧。
右转:
这种情况类似于左情况,但在这种情况下,只有右传感器检测到线,这意味着机器人应该向正确的方向转动。为了使机器人朝右方向转动,左电机向前旋转,右电机向后旋转,结果机器人转向右方向。
停止:
在这种情况下,两个传感器都位于线顶部,它们可以同时检测黑线,微控制器被馈送以将这种情况视为停止过程。因此,两个电机都停止了,这导致机器人停止移动。
红外探头工作原理:红外探测器由两部分——发射器(红外发光二级管)与接收器(红外光电二极管)组成。在其工作时,
由发射器向外发出一定波长的红外光,经物体表面反射后由接收器接收。当物体表面类似黑体时,便会使发射器发出的红外光无法发射会接收器,
接收器本质是红外光电二极管,失去了光,电流会发生变化,由此产生信号。
黑色外表的是接受端,透明的是发射端。接收端需要抵抗外界光线的干扰,所以采用黑色外表。而发射端采用透明外表是为了更好的向各个方向发射红外光。
4.代码部分
我们可以开始编写主要的循迹代码了。
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit ENA = P2^0; //右点机使能
sbit IN1 = P2^1; //为0右轮反转
sbit IN2 = P2^2; //为0右轮正转
sbit IN3 = P2^3; //为0左轮正转
sbit IN4 = P2^4; //为0左轮反转
sbit ENB = P2^5; //左电机使能
sbit left1 = P1^3;
sbit left2 = P1^2;
sbit right1 = P1^1;
sbit right2 = P1^0;
u8 PWMCnt1 = 0;
u8 PWMCnt2 = 0;
u8 cntPWM1 = 0;
u8 cntPWM2 = 0;
void Timer0Init();
void XunJi();
void main()
{
Timer0Init();
while(1)
{
XunJi();
}
}
// i = 1时, 大概延时10us
//void delay(u16 i)
//{
// while (i--);
//}
void Timer0Init()
{
TH0 = 0xFF;
TL0 = 0xA3;
TMOD &= 0xF0;
TMOD |= 0x01;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void TurnRight1() //右转
{
IN1 = 0; //右轮反转
IN2 = 1;
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 70;
cntPWM2 = 55;
}
void TurnRight2() //右转
{
IN1 = 0; //右轮反转
IN2 = 1;
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 50;
cntPWM2 = 40;
}
void TurnLeft1() //左转
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 1;
IN4 = 0; //左轮反转
cntPWM1 = 55;
cntPWM2 = 70;
}
void TurnLeft2() //左转
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 1;
IN4 = 0; //左轮反转
cntPWM1 = 40;
cntPWM2 = 50;
}
void Forward() //前进
{
IN1 = 1;
IN2 = 0; //右轮正转
IN3 = 0; //左轮正转
IN4 = 1;
cntPWM1 = 40;
cntPWM2 = 40;
}
//void Backward() //后退
//{
// IN1 = 0; //右轮反转
// IN2 = 1;
//
// IN3 = 1;
// IN4 = 0; //左轮反转
// cntPWM1 = 30;
// cntPWM2 = 30;
//}
void Stop() /停止
{
IN1 = 0;
IN2 = 0;
IN3 = 0;
IN4 = 0;
}
void XunJi()
{
unsigned char flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //0 0 0 0
flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //0 0 0 1
flag = 1;
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //0 0 1 0
flag = 0;
if((left1 == 0)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //0 0 1 1
flag = 1;
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //0 1 0 0
flag = 0;
if((left1 == 0)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //0 1 0 1
flag = 4;
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //0 1 1 0
flag = 0;
if((left1 == 0)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //0 1 1 1
flag = 1;
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 0)) //1 0 0 0
flag = 3;
if((left1 == 1)&&(left2 == 0)&&(right1 == 0)&&(right2 == 1)) //1 0 0 1
flag = 0;
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 0)) //1 0 1 0
flag = 2;
// ?
if((left1 == 1)&&(left2 == 0)&&(right1 == 1)&&(right2 == 1)) //1 0 1 1
flag = 0;
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 0)) //1 1 0 0
flag = 3;
//?
if((left1 == 1)&&(left2 == 1)&&(right1 == 0)&&(right2 == 1)) //1 1 0 1
flag = 0;
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 0)) //1 1 1 0
flag = 3;
if((left1 == 1)&&(left2 == 1)&&(right1 == 1)&&(right2 == 1)) //1 1 1 1
flag = 5;
switch(flag)
{
case 0:Forward();break;
case 1:TurnRight1();break;
case 2:TurnRight2();break;
case 3:TurnLeft1();break;
case 4:TurnLeft2();break;
default:Stop();break;
}
}
void InterruptTime0() interrupt 1
{
PWMCnt1++;
PWMCnt2++;
if(PWMCnt1 >= 200)
{
PWMCnt1 = 0;
}
if(PWMCnt1 <= cntPWM1)
{
ENA = 1;
}
else
{
ENA = 0;
}
if(PWMCnt2 >= 200)
{
PWMCnt2 = 0;
}
if(PWMCnt2 <= cntPWM2)
{
ENB = 1;
}
else
{
ENB = 0;
}
TH0 = (65536 - 50)/256;
TL0 = (65536 - 50)%256;
}