• 循迹模式-差速转弯


    循迹模式—差速转弯

    为什么要差速转弯?

    普通循迹模式下,小车转弯是让一个轮子停止,另一个轮子转动,强行带动停下的轮子前进,所以会造成转弯时“一拐一拐的”,显得不平滑;

    如果使转弯时外侧轮子速度快,里侧轮子速度慢,在两个轮子的速度差下进行转弯,便会现得平滑很多

    程序

    实现差速转弯,主要用到了左右轮PWM调速的功能,把小车PWM调速-左右轮差速调速的定时器初始化和中断处理拿过来使用

    程序文件:

    1.main.c:主要是对两个红外循迹模块的输出引脚电平进行判断,接着调用电机驱动使小车左右转弯

    2.Motor.c:小车前进、后退、左转、右转和停止的函数,被定时器的PWM调速中断处理调用

    3.Delay.c:延时函数

    4.Timer.c:定时器0和定时器1初始化,以及中断PWM

    在这里插入图片描述

    Timer.c:

    #include 
    #include "Motor.h"
    #include "Delay.h"
    
    unsigned char CountLeft;
    unsigned char SpeedLeft;
    
    unsigned char CountRight;
    unsigned char SpeedRight;
    
    /**
      * @brief 定时器0初始化函数,左轮PWM控制
      * @param 无
      * @retval 无
      */
    void Timer0Init(void)		//0.5毫秒@11.0592MHz
    {
    	TMOD &= 0xF0;
    	TMOD |= 0x01;	//设置定时器模式
    	TL0 = 0x33;		//设置定时初值
    	TH0 = 0xFE;		//设置定时初值
    	TF0 = 0;		//清除TF0标志
    	TR0 = 1;		//定时器0开始计时
    	EA = 1;			//开启总中断
    	ET0 = 1;		//开启定时器0中断
    }
    
    //Timer0中断处理函数,每隔0.5毫秒进入一次中断
    void Timer0_Rountine() interrupt 1
    {
    	CountLeft++;
    	TL0 = 0x33;
    	TH0 = 0xFE;
    	if(CountLeft < SpeedLeft)
    	{
    		//左轮前进
    		GoForwardLeft();
    	}
    	else
    	{
    		//左轮停止
    		StopLeft();
    	}
    	if(CountLeft == 40)	//周期长一点,小车调速会更顺滑点
    	{
    		CountLeft = 0;
    	}
    }
    
    /**
      * @brief 定时器1初始化,右轮PWM调速
      * @param 无
      * @retval无
      */
    void Timer1Init(void)		//0.5毫秒@11.0592MHz
    {
    	TMOD &= 0x0F;
    	TMOD |= 0x10;	//设置定时器模式
    	TL1 = 0x33;		//设置定时初值
    	TH1 = 0xFE;		//设置定时初值
    	TF1 = 0;		//清除TF1标志
    	TR1 = 1;		//定时器1开始计时
    	EA = 1;			//开启总中断
    	ET1 = 1;		//开启定时器1中断
    }
    
    
    //Timer1中断处理函数,每隔0.5毫秒进入一次中断
    void Timer1_Rountine() interrupt 3
    {
    	CountRight++;
    	TL1 = 0x33;
    	TH1 = 0xFE;
    	if(CountRight < SpeedRight)
    	{
    		//右轮前进
    		GoForwardRight();
    	}
    	else
    	{
    		//右轮停止
    		StopRight();
    	}
    	if(CountRight == 40)	//20ms
    	{
    		CountRight = 0;
    	}
    }
    
    • 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

    main.c

    如果测试过程中发现小车走直线会偏移,说明左右轮的速度不一样,可以用PWM稍微调整下

    需要注意的是在两个传感器都不反射的情况下,也就是启动的过程中把小车从地面拿起来了,红外没反射回来,如果使用之前的Stop函数,则会出现电流声,这样是个bug,要改为将比较值置0才解决这个问题

    #include 
    #include "Motor.h"
    #include "Delay.h"
    #include "Timer.h"
    
    /*
    循迹功能-差速
    在简单的循迹功能基础上,为了让转弯平滑,左右轮可用PWM差速转弯
    1.增加Timer.c,初始化定时器0和定时器1,中断函数中分别对左右轮作PWM调速
    */
    
    //左右红外传感器的信号引脚
    sbit LeftSersor = P2^7;
    sbit RightSersor = P2^6;
    
    extern unsigned char SpeedLeft;
    extern unsigned char SpeedRight;
    
    void main()
    {
    	Timer0Init(); 
    	Timer1Init();
    	while(1)
    	{
    		//两个都反射,都亮灯
    		if(LeftSersor == 0 && RightSersor == 0)
    		{
    			SpeedLeft = 40;
    			SpeedRight = 37;	//前进时右轮会快一点,导致不能走直线,PWM调速调低点
    		}
    		//左边反射,右边没反射,左亮
    		if(LeftSersor == 0 && RightSersor == 1)
    		{
    			SpeedLeft = 35;		//转弯时如果两个轮的差速不够大,那小车会跑出跑道
    			SpeedRight = 10;
    		}
    		//右边反射,左边没反射,右亮
    		if(LeftSersor == 1 && RightSersor == 0)
    		{
    			SpeedLeft = 10;
    			SpeedRight = 35;
    		}
    		//两个都不反射,都灭灯
    		if(LeftSersor == 1 && RightSersor == 1)
    		{
    			/*如果停止写Stop函数的话,运行会异常,因为都不反射的时候停止,
    			但此时定时器是在工作的,当中断处理函数那边执行时,左右轮想转动,
    			但main函数又让其停止,小车就会有滋滋的电流响声,改用比较值
    			SpeeLeft、SpeedRight置0操作则消除这个现象*/
    			
    			SpeedLeft = 0;
    			SpeedRight = 0;
    		}
    	}
    }
    
    • 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
  • 相关阅读:
    [安洵杯 2019]easy_web
    [深度学习][pytorch]pytorch实现一个简单得线性回归模型并训练
    【Golang】使用go mod vendor的情况
    “2022锦江行”,维也纳国际酒店、丽柏酒店惊艳同台,中高端酒店再出标杆示范
    8.2_[Java 方法]-深入带参 数组/对象 作为参数的方法以及 值传递/引用传递 的区别
    Python-基于Django的新生入学管理系统
    【软考-中级】系统集成项目管理工程师-人力资源管理历年案例
    核心实验10_hybrid(实现access和trunk功能)_ENSP
    Windows入口点函数
    以自主技术跃进的综合冲压的顶级制造商
  • 原文地址:https://blog.csdn.net/weixin_46251230/article/details/126319121