精华内容
下载资源
问答
  • 循迹小车

    千次阅读 多人点赞 2019-08-19 17:19:32
    循迹小车,顾名思义就是沿着已定的线路跑的小车,循迹小车在可以代替人工进行固定地点的搬运、传递信息等… 一个循迹小车主要有以下几个模块组成: 电机驱动模块 PWM调速模块 红外循迹模块 剩下的就是在主函数中...

    循迹小车,顾名思义就是沿着已定的线路跑的小车,循迹小车在可以代替人工进行固定地点的搬运、传递信息等…

    一个循迹小车主要有以下几个模块组成:

    • 电机驱动模块
    • PWM调速模块
    • 红外循迹模块

    剩下的就是在主函数中对这几个模块进行相互配合,让小车能够在红外寻迹模块的反馈下,通过PWM模块的调速,使电机驱动, 寻迹小车的大体运作过程就是这样,接下来详细说明一下几个模块的配合。

    电机驱动模块

    电机驱动模块是L293D,只要将相应接口使用杜邦线连接在单片机上,再由程序控制相应接口的电平高低,就可以控制俩个电机的转动,实现小车前进、后退、左转、右转等动作。
    如下是电机驱动模块头文件,利用六根杜邦线连接电机与单片机,控制相应引脚的电平输出就可以控制电机的转动。

    sbit L_back = P1^2; //为1 左电机反转
    sbit L_advance = P1^3; //为1 左电机正转
    sbit R_advance = P1^6; //为1 右电机正转
    sbit R_back = P1^7; //为1 右电机反转
    sbit L_en = P1^4; //为1 左电机使能
    sbit R_en = P1^5; //为1 右电机使能
    
    #define Left_forward()   	 L_back=0,L_advance=1
    #define Left_back()      	 L_back=1,L_advance=0
    #define Left_stop()     	 L_back=0,L_advance=0
    #define Left_en()            L_en=1
    #define Right_forward()      R_back=0,R_advance=1
    #define Right_back()      	 R_back=1,R_advance=0
    #define Right_stop()      	 R_back=0,R_advance=0
    #define Right_en()       	 R_en=1
    

    下面是具体实现小车前进、后退、左转、右转的函数:

    /* 小车前进:左右电机同时前进 */
    void Forward(void)
    {
    	Left_forward();
    	Right_forward();	
    }
    
    /* 小车后退:左右电机同时倒转 */
    void Back(void)
    {
    	Left_back();
    	Right_back();
    }
    
    /* 小车左转:右电机前进,左电机不转 */
    void Left_motor_go(void)
    {
    	Left_stop();
    	Right_forward();	
    }
    
    /* 小车右转:左电机前进,右电机不转 */
    void Right_motor_go(void)
    {
    	Right_stop();
    	Left_forward();	
    }
    
    

    然后就是再程序中直接调用这些,小车的驱动函数即可。

    PWM调速模块

    关于PWM调速的内容之前的博客中已经做了详细的介绍,链接:PWM调速
    在此程序中对电机调速至关重要,因为如果电机产生的扭矩不够的话,小车可能停止不前,如果电机转速过快的话,小车可能失去控制

    定时器的配置如示:
        TMOD |= 0x02;//8位自动重装模块
    	TH0 = 220;
    	TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
    	TR0 = 1;//启动定时器0
    	ET0 = 1;//允许定时器0中断
    	EA	= 1;//总中断允许
    	
    /* 定义全局变量作为PWM的参数 */
    unsigned char pwm_t,pwm_k=70;	
    
    /* 在中断里进行PWM调速 */
    void timer0() interrupt 1
    {
    	pwm_t++;
    	if(255 == pwm_t)
    	{
    		L_en=1;
    		R_en=1;
    		pwm_t=0;
    	}	
    	if(pwm_t == pwm_k)
    	{
    		L_en=0;
    		R_en=0;
    	}
    }
    
    

    解释一下pwm_t和pwm_k的含义(简称t、k):t是计数,计满255(从0开始)为一个周期,k大小代表占空比大小,256/t就是占空比,k越大电机转速越快,但k小于70时电机难以维持正常转动。

    红外循迹模块

    首先了解一下红外循迹的原理:
    红外循迹是通过判断黑白线来完成的,利用了红外光的反光特性,当红外光遇到黑色不反光物体时,反射回的红外光大大减少,同理,当红外光遇到白色反光物体时,反射会的红外光较多。红外循迹的传感器就是利用这个特性,判断反射回红外光的多少来判断,小车下面是黑线还是地面。从而反馈给程序,程序会依据返回的数据进行调整小车的下一步行动。
    利用杜邦线连接相应的引脚,使传感器将信息传回单片机:

    sbit Left_led = P3^3;//左寻迹信号 为0 没有识别到黑线 为1识别到黑线
    sbit Right_led = P3^2;//右寻迹信号	为0 没有识别到黑线 为1识别到黑线
    

    (左右各有一个红外传感器)
    要使小车沿着黑线走,只要小车偏离黑线红外传感器就会传回1,所以在程序中要不断的检测红外传感器的状态。当小车在黑线路线上时,就直走;当小车向左偏时,让小车右转;当小车向右偏时,让小车左转;当小车踩到黑线上时,让小车后退。 实现代码如下:

    while(1)
    	{
    		if((1==Left_led)&&(1==Right_led))
    		{
    			Back();
    			Forward();
    		}
    		if((0==Left_led)&&(1==Right_led))
    		{
    			Right_motor_go();
    		}
    		if((1==Left_led)&&(0==Right_led))
    		{
    			Left_motor_go();
    		}
    		if((0==Left_led)&&(0==Right_led))
    		{
    			Forward();
    		}
    
    	}
    

    最后附上主函数:

    int main(void)
    {
    	TMOD |= 0x02;//8位自动重装模块
    	TH0 = 220;
    	TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
    	TR0 = 1;//启动定时器0
    	ET0 = 1;//允许定时器0中断
    	EA	= 1;//总中断允许
    	while(1)
    	{
    		if((1==Left_led)&&(1==Right_led))
    		{
    			Back();
    			Forward();
    
    		}
    		if((0==Left_led)&&(1==Right_led))
    		{
    			Right_motor_go();
    
    		}
    		if((1==Left_led)&&(0==Right_led))
    		{
    			Left_motor_go();
    
    		}
    		if((0==Left_led)&&(0==Right_led))
    		{
    			Forward();
    
    		}
    
    	}
    }
    

    代码亲测可以运行
    有需要的朋友可以联系博主
    qq:2723808286
    有完整的循迹小车、红外遥控、各种传感的模块

    展开全文
  • 基于51单片机四路循迹小车

    万次阅读 多人点赞 2018-11-14 13:54:59
    这学期开设的51单片机课程的课程设计即将验收,今天开始正式着手做循迹小车~

    这学期开设的51单片机课程的课程设计即将验收,今天开始正式着手做循迹小车~

    一. 任务要求

    在这里插入图片描述
    在这里插入图片描述

    二. 系统原理

    本系统以设计题目的要求为目的,采用STC89C52单片机为控制核心,利用红外传感器检测轨道,控制电动小汽车的自动循迹,快慢速行驶。

    这里的轨道是指汽车沿着白色地板上的黑线行驶。由于黑线与白地板的反射系数不同,可以根据接收到的反射光的强度来判断“道路”。常用的方法是红外检测。

    红外检测方法,即在汽车行驶过程中,利用红外光在具有不同颜色的物体表面的不同反射特性,不断向地面发射红外光。当红外光与白纸地板相遇时,会发生漫反射,反射光被安装在车内的接收器接收,如果遇到黑线,就会变成红色。外部光被吸收,车内的接收器不能接收红外线。单片机根据是否接收到反射的红外光来确定黑线的位置和汽车的行驶路线。

    三. 整体方案

    1. 控制模块

    小车的核心控制部件采用STC公司生产的8位单片机STC89C52。它是一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统51单片机不具备的功能。STC89C52有3个16 位定时器/计数器,2个外部中断,1个串口中断。

    最小系统

    51单片机的具体引脚功能不细说,不了解的可自行百度。直接上最小系统电路图(自己画的,凑合着看)。顺便说一句,在我看来一个没有指示灯的电路是最烦的电路<(`^´)> 我的复位一定要有灯才行!

    在这里插入图片描述
    三部分:
    ①电源电路:给单片机提供5V的电源
    ②时钟电路:外接11.0592M石英晶振。
    ③复位电路:确保单片机是从一个确定的初始状态开始。

    焊接时注意P0口要接上拉电阻,否则不能用,一般都用排阻做上拉电阻(当然如果能自己画板子就更好了)。

    去除AD网格线

    记一下怎么去除AD网格线,如图步骤,最后去掉Visible前面的对勾即可,别忘记最后点OK:
    在这里插入图片描述

    2. 电机驱动模块

    我使用的是最经典的LM298N电机驱动:

    我太喜欢用298了。不仅可以接至12v(即拥有更强的驱动能力),而且有过电流保护功能,当出现电机卡死时,可以保护电路和电机等。且自带7805降压模块可直接给单片机供电~~
    实物图:
    在这里插入图片描述
    驱动与各部分的连接简介:
    输出A、B:分别接到左右马达上,通过使能A、使能B来控制电机正常工作(接高电平为正常工作);
    单片机IO控制输入(即IN1-IN4):用来控制马达正反转。接单片机引脚,通过在程序中给引脚高低电平实现正转或反转(详见下边输入输出关系表);
    12V输入:接电池盒正极;
    5V输入:接单片机VCC,给单片机供电;
    电源地(即GND):把电池盒负极和单片机的GND一起接入。
    在这里插入图片描述
    电路图:
    在这里插入图片描述
    输入输出关系(使能ENA、ENB均为1的状态下):

    In1In2运转状态
    10正转
    01反转
    11刹停
    00停止

    3. 电源模块

    我自己使用的是两节18500锂电池供电。如果觉得两节电池不够,三节12V又太大,也可以在中间加一个7809稳压管把电压降到9V再接入驱动:
    在这里插入图片描述

    4. 循迹模块

    光电循迹是由四对红外收发管组成,通过检测接收到的反射光强,判断黑白线。

    当模块探测灯检测到黑线时指示灯熄灭,同时 OUT端口持续输出高电平信号,反之未检测到黑线的探测灯应常亮,OUT端口输出低电平。该模块检测距离 2~60cm,检测角度 35 ° ,检测距离可以通过电位器进行调节,顺时针调电位器,灵敏度增加;逆时针调电位器,灵敏度减少。
    在这里插入图片描述
    原理图由红外对管和电压比较器两部分组成,红外对管输出的模拟电压通过电压比较器转换成数字电平输出到单片机。

    主控板的电路图:
    在这里插入图片描述
    小板电路图:
    在这里插入图片描述
    注意连接的时候:VCC-VCC、GND-GND、IN-OUT。

    比较器LM339
    在这里插入图片描述

    5. 超声波测距模块

    实物图:
    在这里插入图片描述
    电路图:
    在这里插入图片描述
    工作原理
      (1)采用IO口TRIG触发测距,给至少10us的高电平信号;
      (2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
      (3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。
      测试距离=(高电平时间*声速(340M/S))/2;

    四. 车体实物图

    在这里插入图片描述

    五. 软件实现

    #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;
    }
    
    展开全文
  • 智能循迹小车报告

    2017-12-13 08:46:15
    本实验完成采用红外反射式传感器的自循迹小车的设计和实现。采用与白色地面色差很大的黑色路线引导小车按照既定路线前进。 本设计采用单片机STC89C52作为小车检测、控制、时间显示核心,以实验室给定的车架为车体,...
  • 提出一种感应式循迹小车的设计方法,用金属铝箔胶带代替黑色轨道线,在小车上设置多只金属感应传感器,基于感应的方法来检测铝箔胶带路线的位置,把检测的结果送单片机处理,再由单片机输出相应控制信号驱动小车运行...
  • 基于arduino的循迹小车(含有PID算法)

    万次阅读 多人点赞 2018-08-11 20:39:36
    循迹小车一般分为两方面:一方面是简单的闭环赛道只有直道和弯道,另一方面是毕设类型的包括一些元素:90度弯道、十字道路、S形弯道等。 1、CSDN下载: 含有PID:...

           循迹小车一般分为两方面:一方面是简单的闭环赛道只有直道和弯道,另一方面是毕设类型的包括一些元素:90度弯道、十字道路、S形弯道等。

     

    1、CSDN下载:

    含有PID:https://download.csdn.net/download/qq_38351824/11107048

    没有PID:https://download.csdn.net/download/qq_38351824/11107175

    2、可以关注点赞并在下方评论,我给你邮箱发过去。

    3、关注微信公众号下载:

         ① 关注微信公众号:Tech云  

         ②

     

           本篇博客试根据下图来进行书写的,如果大家有什么新的元素,也可以在下方评论,我进行更新。

    作者:sumjess

     

    注意本篇博客循迹模块使用了5个

    一、简单的闭环赛道

    随意画了一个

    (1)逻辑部分:

       

    所以程序的写法也很简单,就是检测到哪种情况对应着哪种反应。这一过程可以用switch也可以用if来实现这一过程。下文用if来演示。

    (2)各程序片段

    总的循环:

    void loop()
    {
         read_sensor_values();  //获取5个循迹模块的数值情况
         calc_pid();            //pid计算出转向的pwm值
         motor_control();       //电机转动
    }

    第一部分:检测部分程序片段

    void read_sensor_values()
    {
      sensor[0] = digitalRead(leftA_track_PIN);
      sensor[1] = digitalRead(leftB_track_PIN);
      sensor[2] = digitalRead(middle_track_PIN);
      sensor[3] = digitalRead(righA_track_PIN);
      sensor[4] = digitalRead(righB_track_PIN);
      
      if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 1)) {
          error = 2;//          0 0 0 0 1
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1) && (sensor[4] == 0)) {
          error = 1;//          0 0 0 1 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = 0;//          0 0 1 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -1;//         0 1 0 0 0
        } else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -2;//         1 0 0 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          if (error == -2) {//  0 0 0 0 0
            error = -3;
          }else{
            error = 3;
          }
        }
      }

    解释:

    <1>  将读取到的五个循迹模块的数据存入数组sensor:

      sensor[0] = digitalRead(leftA_track_PIN);      左边第一个循迹模块
      sensor[1] = digitalRead(leftB_track_PIN);      左边第二个循迹模块
      sensor[2] = digitalRead(middle_track_PIN);   中间的循迹模块
      sensor[3] = digitalRead(righA_track_PIN);     右边第二个循迹模块
      sensor[4] = digitalRead(righB_track_PIN);     右边第一个循迹模块

    <2>  检测到哪种情况对应着哪种反应:

    if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 1)) {
          error = 2;//          0 0 0 0 1
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1) && (sensor[4] == 0)) {
          error = 1;//          0 0 0 1 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = 0;//          0 0 1 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -1;//         0 1 0 0 0
        } else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -2;//         1 0 0 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          if (error == -2) {//  0 0 0 0 0
            error = -3;
          }else{
            error = 3;
          }
        }

    前面几个就不解释了完全按照前面excel写的,最后一个是所有传感器均没有检测到黑线的情况,下面具体解释一下:

    else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {

     检测到为0000的情况
          if (error == -2) {// //如果上一次 error == -2

    意味着上一次是1000,也就是意味着这次可能车在左面第一个传感器和第二个传感器之间或者是在左边第一个传感器的左边,无论是上面的哪种情况,车都需要大左转
            error = -3;
          }else{

    否则就是相反的情况,都需要大右转
            error = 3;
          }
        }

    第二部分:计算PID(计算转向大小)

    void calc_pid()
    {
      P = error;
      I = I + error;
      D = error - previous_error;
     
      PID_value = (Kp * P) + (Ki * I) + (Kd * D);
     
      previous_error = error;
    }

    利用上一部分得到的error计算车的偏离情况,车偏离赛道的情况从而来调整下一次给出的PWM进而快速转正车身。

    这一部分的kp、ki、kd需要不断地调试,从而得出最佳解。

     

    第三部分:电机转向

    //速度设定范围(-255,255)
    void motorsWrite(int speedL, int speedR)
    {
      if (speedR > 0) {
        analogWrite(leftA_PIN, speedR);
        analogWrite(leftB_PIN, 0);
      } else {
        analogWrite(leftA_PIN, 0);
        analogWrite(leftB_PIN, -speedR);
      }
     
      if (speedL > 0) {
        analogWrite(righA_PIN, speedL);
        analogWrite(righB_PIN, 0);
      } else {
        analogWrite(righA_PIN, 0);
        analogWrite(righB_PIN, -speedL);
      }
    }
    //速度设定范围(-100,100)
    void motorsWritePct(int speedLpct, int speedRpct) {
      //speedLpct, speedRpct ranges from -100 to 100
      motorsWrite(speedLpct * 2.55, speedRpct * 2.55);
    }
    void motor_control()
    {
      int left_motor_speed = initial_motor_speed - PID_value;
      int right_motor_speed = initial_motor_speed + PID_value;
      
      if(left_motor_speed < -255){
        left_motor_speed = -255;
      }
      if(left_motor_speed > 255){
        left_motor_speed = 255;
      }
      motorsWrite(left_motor_speed,right_motor_speed);
    } 

    第一个函数是在检查更改正负值,来保证PWM都是正的,即轮子不会倒转。

    第二个函数是在利用一次函数,将输入范围变成0-100

    第三个函数是在控制范围,ardunio的PWM范围是在正负255,此函数是在做一个限制·

     

    二、在上面的基础上添加元素

     

    (1)逻辑部分:

    (2)各程序片段

     

    除了read_sensor_values() 各程序片段与之前都一样,read_sensor_values() 只是添加了一部分,情况如下:

    void read_sensor_values()
    {
      sensor[0] = digitalRead(leftA_track_PIN);
      sensor[1] = digitalRead(leftB_track_PIN);
      sensor[2] = digitalRead(middle_track_PIN);
      sensor[3] = digitalRead(righA_track_PIN);
      sensor[4] = digitalRead(righB_track_PIN);
      
          if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 1)) {
          decide = 1;//十字路口 1 1 1 1 1   直行
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 0)) {
          decide = 1;//十字路口 0 1 1 1 0   直行
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 1)) {
          decide = 2;//90度路口 0 0 1 1 1    右转90度
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 0)) {
          decide = 2;//90度路口 0 0 1 1 0    右转90度 
        } else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//90度路口 1 1 1 0 0    左转90度 
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//90度路口 0 1 1 0 0    左转90度 
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//向上锐角 0 1 1 0 0    向上锐角 
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 1)) {
          error = 2;//          0 0 0 0 1
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1) && (sensor[4] == 0)) {
          error = 1;//          0 0 0 1 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = 0;//          0 0 1 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -1;//         0 1 0 0 0
        } else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          error = -2;//         1 0 0 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
          if (error == -2) {//  0 0 0 0 0
            error = -3;
          }else{
            error = 3;
          }
        }
     
    }

    各个条件都是按照前面excel写的

    附全套程序

    //电机使用:5-6-9-10
    //循迹模块使用:2-3-7-8-11
    
    //-------------------------------------------------------------------//
    //*******************************************************************//
    ///
    //小车部分/
    ///
    
    //           电机设置             //
    #define leftA_PIN 5
    #define leftB_PIN 6
    #define righA_PIN 9
    #define righB_PIN 10
    
    float Kp = 10, Ki = 0.5, Kd = 0;                    //pid弯道参数参数 
    float error = 0, P = 0, I = 0, D = 0, PID_value = 0;//pid直道参数 
    float decide = 0;                                   //元素判断
    float previous_error = 0, previous_I = 0;           //误差值 
    int sensor[5] = {0, 0, 0, 0, 0};                    //
    5个传感器数值的数组 
    static int initial_motor_speed = 60;                //初始速度 
     
    void read_sensor_values(void);                      //读取初值 
    void calc_pid(void);                                //计算pid 
    void motor_control(void);                           //电机控制 
    
    void motor_pinint( );     //引脚初始化
    void _stop();             //停车
    ///
    //*******************************************************************//
    //-------------------------------------------------------------------//
    
    //-------------------------------------------------------------------//
    //*******************************************************************//
    ///
    循迹部分///
    ///
    
    //             循迹模块设置               //
    #define leftA_track_PIN 3
    #define leftB_track_PIN 4
    #define middle_track_PIN 12
    #define righA_track_PIN 7
    #define righB_track_PIN 13
    
    
    //----------------------------------算法部分-----------------------------
    ---//
    void obstacle( );      //避障小车算法
                           //循迹小车算法/*  read_sensor_values(); calc_pid(
    ); motor_control();  */     
    //--------------------------------------------------------------------------//
    
    void setup()
    {
      Serial.begin(9600); //串口波特率115200(PC端使用)
      track_pinint( );     //循迹引脚初始化
      motor_pinint();        //电机引脚初始化
    
    }
    void loop()
    {
        read_sensor_values();         //循迹小车
        calc_pid();
        motor_control();
    }
    
    /*循迹模块引脚初始化*/
    void track_pinint( )
    { 
      pinMode (leftA_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (leftB_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (middle_track_PIN, INPUT);//设置引脚为输入引脚
      pinMode (righA_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (righB_track_PIN, INPUT); //设置引脚为输入引脚
    }
    
    /*电机引脚初始化*/
    void motor_pinint( )
    {
      pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚
      }
    
    /**************************************************
    stop子函数—停止子函数
    函数功能:控制车停止
    **************************************************/
    void _stop()
    {
      analogWrite(leftA_PIN,0);      
      analogWrite(leftB_PIN,0);         //左轮静止不动
      analogWrite(righA_PIN,0);      
      analogWrite(righB_PIN,0);         //右轮静止不动
    }
    //速度设定范围(-255,255)
    void motorsWrite(int speedL, int speedR)
    {
      if (speedR > 0) {
        analogWrite(leftA_PIN, speedR);
        analogWrite(leftB_PIN, 0);
      } else {
        analogWrite(leftA_PIN, 0);
        analogWrite(leftB_PIN, -speedR);
      }
     
      if (speedL > 0) {
        analogWrite(righA_PIN, speedL);
        analogWrite(righB_PIN, 0);
      } else {
        analogWrite(righA_PIN, 0);
        analogWrite(righB_PIN, -speedL);
      }
    }
    //速度设定范围(-100,100)
    void motorsWritePct(int speedLpct, int speedRpct) {
      //speedLpct, speedRpct ranges from -100 to 100
      motorsWrite(speedLpct * 2.55, speedRpct * 2.55);
    }
    void motorsStop() 
    {
      analogWrite(leftA_PIN,0);      
      analogWrite(leftB_PIN,0);         //左轮静止不动
      analogWrite(righA_PIN,0);      
      analogWrite(righB_PIN,0);         //右轮静止不动
    }
     
    void read_sensor_values()
    {
      sensor[0] = digitalRead(leftA_track_PIN);
      sensor[1] = digitalRead(leftB_track_PIN);
      sensor[2] = digitalRead(middle_track_PIN);
      sensor[3] = digitalRead(righA_track_PIN);
      sensor[4] = digitalRead(righB_track_PIN);
      
        if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3
    ] == 1) && (sensor[4] == 1)) {
          decide = 1;//十字路口 1 1 1 1 1   直行
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (
    sensor[3] == 1) && (sensor[4] == 0)) {
          decide = 1;//十字路口 0 1 1 1 0   直行
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (
    sensor[3] == 1) && (sensor[4] == 1)) {
          decide = 2;//90度路口 0 0 1 1 1    右转90度
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (
    sensor[3] == 1) && (sensor[4] == 0)) {
          decide = 2;//90度路口 0 0 1 1 0    右转90度 
        } else if ((sensor[0] == 1) && (sensor[1] == 1) && (sensor[2] == 1) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//90度路口 1 1 1 0 0    左转90度 
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//90度路口 0 1 1 0 0    左转90度 
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          decide = 3;//向上锐角 0 1 1 0 0    向上锐角 
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (
    sensor[3] == 0) && (sensor[4] == 1)) {
          error = 2;//          0 0 0 0 1
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (
    sensor[3] == 1) && (sensor[4] == 0)) {
          error = 1;//          0 0 0 1 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          error = 0;//          0 0 1 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          error = -1;//         0 1 0 0 0
        } else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          error = -2;//         1 0 0 0 0
        } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (
    sensor[3] == 0) && (sensor[4] == 0)) {
          if (error == -2) {//  0 0 0 0 0
            error = -3;
          }else{
            error = 3;
          }
        }
    }
    void calc_pid()
    {
      P = error;
      I = I + error;
      D = error - previous_error;
     
      PID_value = (Kp * P) + (Ki * I) + (Kd * D);
     
      previous_error = error;
    }
    void motor_control()
    {
      int left_motor_speed = initial_motor_speed - PID_value;
      int right_motor_speed = initial_motor_speed + PID_value;
      
      if(left_motor_speed < -255){
        left_motor_speed = -255;
      }
      if(left_motor_speed > 255){
        left_motor_speed = 255;
      }
      motorsWrite(left_motor_speed,right_motor_speed);
     
      Serial.print("move_A: ");
      Serial.print(left_motor_speed, OCT);
      Serial.print(" move_B: ");
      Serial.print(right_motor_speed, OCT);
      Serial.print(" error: ");
      Serial.print(error, OCT);
      Serial.print(" P: ");
      Serial.print(Kp, OCT);
      Serial.print(" PID_value: ");
      Serial.print(PID_value, OCT);
      Serial.println();
    } 
    
    

    附加:不含PID的代码

    #define leftA_PIN 5
    #define leftB_PIN 6
    #define righA_PIN 9
    #define righB_PIN 10
    
    #define leftA_track_PIN 3
    #define leftB_track_PIN 4
    #define middle_track_PIN 12
    #define righA_track_PIN 7
    #define righB_track_PIN 13
    
    void motor_pinint( );                               //引脚初始化
    void _stop();                                       //停车
    void forward();  
    void turnSRight();                                 //小右转
    void turnSLeft();                                  //小左转
    void turnRight();                                  //右转
    void turnLeft();                                   //左转
    void nine(); 
    void ten() ;
    int error = 0;
    int sensor[5] = {0, 0, 0, 0, 0};                    //5个传感器数值的数组 
    int read_sensor_values(void);                      //读取初值 
    
    void setup() {
      Serial.begin(9600); //串口波特率9600(PC端使用)
      track_pinint( );    //循迹引脚初始化
      motor_pinint();     //电机引脚初始化
    }
    
    void loop() {
      static int b=0;
      b=read_sensor_values();         //循迹小车
      switch (b){              //读取初值  
         case 0:  forward(); Serial.println(1); break; //直行
         case -1: turnSRight();Serial.println(2); break; //小左
         case -2: turnRight();Serial.println(3);break; //大左 
         case 1:  turnSLeft(); Serial.println(4); break; //小右
         case 2:  turnLeft();Serial.println(5); break; //大右    
         case 3:  _stop();Serial.println(6); break; //停
    //     case -3: turnLeft(); Serial.println(7);break; //大左
    //     case 4:  forward();  Serial.println(9);break; //直行   
         case 5:   nine() ;  Serial.println(9);break; //右转90度
         case 6:    ten();   Serial.println(9);break; 
         default: _stop();Serial.println(8);break; 
      }
    
    }
    
    /*循迹模块引脚初始化*/
    void track_pinint( )
    { 
      pinMode (leftA_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (leftB_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (middle_track_PIN, INPUT);//设置引脚为输入引脚
      pinMode (righA_track_PIN, INPUT); //设置引脚为输入引脚
      pinMode (righB_track_PIN, INPUT); //设置引脚为输入引脚
    }
    
    /*电机引脚初始化*/
    void motor_pinint( )
    {
      pinMode (leftA_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (leftB_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (righA_PIN, OUTPUT); //设置引脚为输出引脚
      pinMode (righB_PIN, OUTPUT); //设置引脚为输出引脚
      }
    
    /**************************************************
    stop子函数—停止子函数
    函数功能:控制车停止
    **************************************************/
    void _stop()
    {
       analogWrite(leftA_PIN,0);      
      analogWrite(leftB_PIN,0);         //左轮静止不动
      analogWrite(righA_PIN,0);      
      analogWrite(righB_PIN,0);         //右轮静止不动
    }
    int read_sensor_values()
    {
      sensor[0] = digitalRead(leftA_track_PIN);
      sensor[1] = digitalRead(leftB_track_PIN);
      sensor[2] = digitalRead(middle_track_PIN);
      sensor[3] = digitalRead(righA_track_PIN);
      sensor[4] = digitalRead(righB_track_PIN);
      //1为遇到黑线
    //   if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 1)) {
    //      error = 2;//          00001
    //    } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1) && (sensor[4] == 0)) {
    //      error = 1;//          00010
    //    } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
    //      error = 0;//          00100
    //    } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
    //      error = -1;//         01000
    //    } else if ((sensor[0] == 0) && (sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0) && (sensor[4] == 0)) {
    //      error = -1;//         01100
    //    }  else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1) && (sensor[4] == 0)) {
    //      error = 1;//          00110
    //    } else if ((sensor[0] == 1) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
    //      error = -2;//         10000
    //    } else if ((sensor[0] == 0) && (sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0) && (sensor[4] == 0)) {
    //      if (error == -2) {//  00000
    //        error = 4;//-3;
    //      }else{
    //        error = 4;//3;
    //      }
    //    }
    //    else error = -error;  
     //000-001-010-011-100-101-110-111
               if ((sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 0)) {
          error = 0;//          000  停
        } else if ((sensor[1] == 0) && (sensor[2] == 0) && (sensor[3] == 1)) {
          error = -2;//          001  右转
        } else if ((sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 0)) {
          error = 0;//          010  直行
        } else if ((sensor[1] == 0) && (sensor[2] == 1) && (sensor[3] == 1)) {
          error = -1;//         011  右转
        } else if ((sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 0)) {
          error = 2;//         100  左转
        }  else if ((sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 0)) {
          error = 1;//         110  左转
        } else if ((sensor[1] == 1) && (sensor[2] == 1) && (sensor[3] == 1)) {
          error = 0;//          111  直行
        } /*else if ((sensor[1] == 1) && (sensor[2] == 0) && (sensor[3] == 1)) {
          error = 1;//          101
        }*/
        if (sensor[4] == 1)  error=5;
        if (sensor[0] == 1)  error=6;
        for(int i=1;i<4;i++)
        Serial.print(sensor[i]);
        Serial.println( );
        return error;
    }
    /********************** ****************************
    forward子函数——前进子函数
    函数功能:控制车前进
    **************************************************/
     void forward()
    {
      analogWrite(leftA_PIN,60);      
      analogWrite(leftB_PIN,0);         //左轮前进60
      analogWrite(righA_PIN,60);      
      analogWrite(righB_PIN,0);         //右轮前进
    }
    /**************************************************
    turnLeft子函数——大左转子函数
    函数功能:控制车大左转
    **************************************************/
    void turnLeft() 
    {
      analogWrite(leftA_PIN,40);      
      analogWrite(leftB_PIN,0);         //左轮前进20
      analogWrite(righA_PIN,140);      
      analogWrite(righB_PIN,0);         //右轮前进70
    }
    /**************************************************
    turnRight子函数——小右转子函数
    函数功能:控制车大右转弯
    **************************************************/
    void turnRight()
    {
      analogWrite(leftA_PIN,140);      
      analogWrite(leftB_PIN,0);         //左轮前进
      analogWrite(righA_PIN,40);      
      analogWrite(righB_PIN,0);         //右轮前进
    }
    /**************************************************
    turnLeft子函数——大左转子函数
    函数功能:控制车小左转
    **************************************************/
    void turnSLeft()
    {
      analogWrite(leftA_PIN,60);      
      analogWrite(leftB_PIN,0);         //左轮前进20
      analogWrite(righA_PIN,110);      
      analogWrite(righB_PIN,0);         //右轮前进30
    }
    /**************************************************
    turnRight子函数——小右转子函数
    函数功能:控制车小右转弯
    **************************************************/
    void turnSRight()
    {
      analogWrite(leftA_PIN,110);      
      analogWrite(leftB_PIN,0);         //左轮前进
      analogWrite(righA_PIN,60);      
      analogWrite(righB_PIN,0);         //右轮前进
    }
    void nine() 
    {
      analogWrite(leftA_PIN,140);      
      analogWrite(leftB_PIN,0);         //左轮前进20
      analogWrite(righA_PIN,0);      
      analogWrite(righB_PIN,0);         //右轮前进70
    }
    void ten() 
    {
      analogWrite(leftA_PIN,0);      
      analogWrite(leftB_PIN,0);         //左轮前进20
      analogWrite(righA_PIN,140);      
      analogWrite(righB_PIN,0);         //右轮前进70
    }

     

    展开全文
  • 基于51单片机的循迹小车,才采用模拟PWM信号进行各路的速度控制,使用光对管进行路线的检测。
  • 基于红外的简单循迹小车程序
  • 实现红外循迹系统,使用STM32单片机作为驱动系统的控制核心﹔采用红外信号传感作为小车的地面路线检测模块来识别地上路线信息与前方障碍物的位置;采用LG9110驱动芯片控制驱动模块,智能小车的驱动部分使用直流减速...
  • 智能循迹小车C程序

    2013-07-28 10:06:36
    51单片机控制小车智能循迹,只要保证在白色地面或皮质上用黑色胶带粘贴出路线路径宽度微大于相邻检测管间距,这样小车便可在其上循迹运行~~~
  • 51循迹小车

    2021-08-29 09:03:54
    目标:使智能小车沿如图路线行走 一,所需零件 1,车体,车轮 2,51单片机 3,驱动模块:LM298N 该模块可以同时给单片机和电机供电 ...

    目标:使智能小车沿如图路线行走

    一,所需零件                                                                                                                                     1,车体,车轮

     

     

     2,51单片机

     

     

    3,驱动模块:LM298N 

     该模块可以同时给单片机和电机供电                                                                                                 驱动各部分的简介:输出A,B分别接左右马达,放大电流使马达工作,                                             单片机IO控制输入(即IN1-IN4):接单片机IO口,由单片机的程序控制电机正反转,PWM控制车速。                    

    4,稳压模块 

                                                                                                                                                            稳定电压到8伏,防止由于电压不稳定或超高造零件损坏。                                                                5,循迹模块                                                                                                                                             光点循迹由四对红外收发管组成,通过检测接收到的反射光强,判断黑白线。当模块检测到黑线时指示灯熄灭,同时OUT口持续输出高电平信号,未检测到黑线的检测灯正常,OUT端输出低电平。检测灵敏度可以通过电位器调节。                                                                         

    6,电源模块

     

     

    7,核心程序

    #include"reg52.h"
    
    typedef unsigned char u8;
    typedef unsigned int u16;
    
    #define uchar unsigned char
    #define unit unsigned int
    	/*********定义电机方向*********/
    #define left_qian IN1=0;IN2=1     //左边电机前进
    #define left_hou IN1=1;IN2=0      //左边后退
    #define right_qian IN3=0;IN4=1    //右边前进
    #define right_hou IN3=1;IN4=0     //右边后退
    #define stop IN1=1;IN2=1;IN3=1;IN4=1
    /****循迹传感器端口定义****/
    /****传感器位置****/
    /*左2   左1      右1   右2*/
    /* P27  P25      P24   P26*/
    
    sbit IN1=P0^0;
    sbit IN2=P0^1;
    sbit IN3=P0^2;
    sbit IN4=P0^3;
    
    sbit left_2=P2^4;  //左大信号     
    sbit left_1=P2^5;  //左小信号
    sbit righ_1=P2^6;  //右小信号
    sbit righ_2=P2^7;  //右大信号
    
    /*      电机驱动模块端口定义      */
    
    sbit ENA=P0^4;    //左使能        
    //sbit EN1=P0^1;    //左方向1
    //sbit EN2=P0^2;    //左方向2
    sbit ENB=P0^5;    //右使能
    //sbit EN3=P0^7;    //右方向1
    //sbit EN4=P0^6;    //右方向2
    
    uchar zkb_l=0;    //左电机占空比
    uchar zkb_r=0;    //右电机占空比
    uchar t=0;        //定时器中断计数器
    
    
     void Timer0Init()
      {
      TMOD=0X05;
      TH0=0;
      TL0=0;
      ET0=1;//打开计数器0中断
      EA=1;
      TR0=1;
      }
        void Timer0()  interrupt   1
    {
      static u16 i;
      i=0;
      while(i<4)
      {
      if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==1)&&(i<=3))
      {
      i++;
      }
      if(i=4)
      {
      	zkb_l=50;
    		zkb_r=70;
    		left_hou;
    		right_qian;
      }
      }
      }
    
    void init_time0()
    {
    	TMOD=0x01;
    	TH1=(65536-100)/256;
    	TL1=(65536-100)%256;
    	ET1=1;
    	TR1=1;
    }
    
    void delay (u16 i)
    {
      while(i--);
    }
    
    void tim0() interrupt 3
    {
    	TH1=0xff;
    	TL1=0x9c;
    	if(t<zkb_l)ENA=1;
    	else ENA=0;
    	if(t<zkb_r)ENB=1;
    	else ENB=0;
    	t++;
    	if(t>100)t=0;
    }
    
    void xunji()
    {
      
    	if((left_2==1)&&(left_1==0)&&(righ_1==0)&&(righ_2==0))
    	{
    		zkb_l=80;
    		zkb_r=100;
    		left_hou;
    		right_qian;       
    	}
    	else if((left_2==1)&&(left_1==1)&&(righ_1==0)&&(righ_2==0))
    	{
    	  delay(2000);
    	  if((left_2==1)&&(left_1==1)&&(righ_1==0)&&(righ_2==0))
    		zkb_l=100;
    		zkb_r=100;
    		left_hou;
    		right_qian;
    		delay(38666);
    	}
    	else if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==0))
    	{
    	  delay(2000);
    	  if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==0))
    		zkb_l=100;
    		zkb_r=100;
    		left_hou;
    		right_qian;
    		delay(38666);
    	}
    	else if((left_2==0)&&(left_1==1)&&(righ_1==0)&&(righ_2==0))
    	{
    		zkb_l=50;
    		zkb_r=30;
    		left_qian;
    		right_qian;         
    	}
    	else if((left_2==0)&&(left_1==0)&&(righ_1==0)&&(righ_2==0))
    	{
    		zkb_l=40;
    		zkb_r=40;
    		left_qian;
    		right_qian;          
    	}
    	else if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==1))
    	{
    		stop;         
    	}
    	else if((left_2==0)&&(left_1==0)&&(righ_1==1)&&(righ_2==0))
    	{
    		zkb_l=50;
    		zkb_r=30;
    		left_qian;
    		right_qian;         
    	}
    	else if((left_2==0)&&(left_1==0)&&(righ_1==1)&&(righ_2==1))
    	{
    	  delay(2000);
    	  if((left_2==0)&&(left_1==0)&&(righ_1==1)&&(righ_2==1))
    		zkb_l=100;
    		zkb_r=100;
    		left_qian;
    		right_hou;
    		delay(38666);
    	}
    	else if((left_2==0)&&(left_1==1)&&(righ_1==1)&&(righ_2==1))
    	{
    	  delay(2000);
    	  if((left_2==0)&&(left_1==1)&&(righ_1==1)&&(righ_2==1))
    		zkb_l=100;
    		zkb_r=100;
    		left_qian;
    		right_hou;
    		delay(38666);
    	}
    	else if((left_2==0)&&(left_1==0)&&(righ_1==0)&&(righ_2==1))
    	{
    		zkb_l=100;
    		zkb_r=80;
    		left_qian;
    		right_hou;
    	}
    	  	else if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==1))
    	{
    		zkb_l=50;
    		zkb_r=50;
    		left_qian;
    		right_qian;         
    	}
    }
    
    void main()     
    {
       Timer0Init();
      init_time0();
    	EA=1;
    	while(1)
    	{
    	  xunji();
    	}
    }

    需要注意的是,小车需要在第四个干扰处转弯需要用到计数器中断,程序为

    void Timer0Init()
      {
      TMOD=0X05;
      TH0=0;
      TL0=0;
      ET0=1;//打开计数器0中断
      EA=1;
      TR0=1;
      }
        void Timer0()  interrupt   1
    {
      static u16 i;
      i=0;
      while(i<4)
      {
      if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==1)&&(i<=3))
      {
      i++;
      }
      if(i=4)
      {
      	zkb_l=50;
    		zkb_r=70;
    		left_hou;
    		right_qian;
      }
      }
      }

    上桥的一段路光敏是无法检测黑白的,需要其他程序控制小车行走

    	else if((left_2==1)&&(left_1==1)&&(righ_1==1)&&(righ_2==1))
    	{
    		zkb_l=50;
    		zkb_r=50;
    		left_qian;
    		right_qian;         
    	}

     

     

     

    展开全文
  • Arduino控制八路循迹小车实现自动循迹和投放物块以及到达终点OLED屏显示【Arduino controls 8-way tracking car to realize automatic tracking, object placement and OLED screen display of the destination】 ...
  • 机器人 自动循迹小车

    2008-08-28 11:58:48
    小车按指定路线运行,自动区分直线轨道和弯路轨道,在指定弯路处拐弯,实现灵活前进、转弯、倒退等功能,在轨道上划出设定的地图。
  • 一款自动循迹小车的设计方案

    千次阅读 2019-10-02 01:03:44
    一款自动循迹小车的设计方案 自动循迹小车是比较热门地电子竞赛,有许多设计方案。 在网上找到一个设计实验报告,对自动循迹小车的设计方案介绍的比较详细,转载如下: 项目分工: 1、领料、焊接、板子的成型...
  • 【电赛优秀作品集】自动循迹小车制作方案

    万次阅读 多人点赞 2018-08-29 11:12:36
    简单来说自动循迹小车就是集光,机,电于一体的简易智能小车。参赛者通过论证,比较,实验之后,制作出了简易小车的循迹电路系统,整个系统基于普通玩具小车的机械结构,并利用了小车的底盘,前后轮电机及其自动复原...
  • pid循迹小车制作(一代小车beyond)———基于arduino 完成任务: 1.循迹,走到终点(不一定走完全程)。 2.在终点处mpu旋转45° 3.最后超声波循迹到障碍物前10cm处。 硬件配置: 1.arduino uno 2.电机选用tb6612 3....
  • 利用 STM32单片机和oV7725摄像头实现小车的智能循迹。使用摄像头对路况信息进行收集,利用STM32进行处理数据,然后进行二值化处理,利用算法获得前进路线,可以实现左转和右转并且有指示灯对应亮起,实现循迹
  • Arduino循迹小车(三路红外)

    万次阅读 多人点赞 2019-03-17 11:22:43
    利用红外线传感器让小车在规定路线上行进 1. 所需材料 小车车架及车轮(可以用sw建模然后利用3D打印机打印,也可以在网上直接购买小车地板,用纸板最廉价O(∩_∩)O哈哈~) 该图为3D打印效果 Arduino开发板及...
  • 根据具体环境,可建立一个起点、多个终点的路线记忆库,并将各个路线记忆分别保存在Linux下的不同文件中,智能小车通过读取文件中内容实现循迹功能。4 系统软件设计系统软件设计分为3个层次:应用层、操作系统层和...
  • 注:51版本已经隆重推出了,感兴趣的同学请看:基于51版本迷宫循迹小车电路(原理图+源代码+用户手册) 实现不规则路线循迹,利用PID。 3PI智能车(STM32版)完整小车视频: 更多精彩关注:www.x-tab.cn 附件内容包括: ...
  • 最近项目小车自动循迹路线原码,C++编写原码附上 需要。
  • 小车循迹的原理 这里的循迹是指小车在白色地板上循黑线行走,通常采取的方法是红外探测法。 红外探测法,即利用红外线在不同颜色的物体表面具有不同的反射性质的特点,在小车行驶过程中不断地向地面发射红外光,当...
  • 文章目录题目要求一、硬件设计二、理论分析与计算三、电路与程序设计四、测试方案与测试结果五、项目展示 ...提取码:c7zz 取走记得点赞啊!...要求小车能沿着指定路线在坡道上自动循迹骑线行驶。小车必须独立
  • 循迹小车也算是很经典的单片机开发项目了,作为入门项目正合适。这一篇随笔大概写循迹小车的组成部分,之后的随笔就根据这些组成部分来写知识储备,最后写项目实现。 循迹小车组成部分可以做一个分类,分为:传感器...
  • 红外遥控器控制小车小车自带超声波避障,遥控器可以打开循迹,打开循迹后自己循迹走。没打开循迹就红外遥控器控制小车走。 按键如下 1 进入或者退出循迹功能,循迹模式下对小车操作无效 2 前进 5 左转 6 停止 7 右...
  • 神经网络视觉循迹小车

    千次阅读 多人点赞 2017-04-11 10:04:42
    大四狗下学期想学习机器学习、深度学习等相关知识,于是毕设想做些神经网络相关的东西,因为本科期间参加过大学生智能车竞赛,于是想利用小车,通过神经网络,实现自主学习,完成在规定赛道上的行驶。现在在这里,...
  • 智能循迹小车的制作是近年来电子设计的热点,它是一个集环境感知、规划决策,自动行驶等功能于一体的综合系统,具有实时显示时间、速度、里程、自动循迹、寻光、避障、可控行驶速度、远程传输图像等功能,在科学勘探...
  • 本设计是基于单片机通过光电传感器检测小车的状态和用遥控发送指令,控制小车路线的系统。硬件部分:本系统通过单片机I/O口实现各模块的通信,主要包括主控模块、光电开关模块、遥控模块、电机驱动模块。软件部分:...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 200
精华内容 80
关键字:

循迹小车路线