资讯详情

基于STC8G2K64S4单片机控制小车循迹(直流电机和步进电机)

基于STC8G2K64S44单片机控制汽车跟踪

#前言

本文介绍了硬件和软件的使用STC8G2K64S4单片机控制舵机的方法,以步进电机和直流电机为例

之前说过怎么用STC8G2K64S4单片机控制步进电机和直流电机。这一次,这两台电机用于控制汽车结合跟踪模块实现跟踪,这也是学习51台单片机过程中非常基本的例程

硬件方面

步进电机和直流电机可以参考我写的两篇文章,基于STC8G2K64S步进电机控制单片机基于STC8G2K64S4单片机控制直流电机,这里就不多介绍了

光敏传感器是完成汽车跟踪任务必不可少的。我在这里用的是单一的数字量因此,当传感器检测到黑色时,输出1

黑色    i=1; 白色    i=0;

当检测红色、黄色和蓝色时,需要调整电位器来控制输出。电位器的准确性也非常重要,以避免以后的错误判断。光敏传感器的高度也有一定的影响,只要在其高度范围内。高度范围一般在宝藏购买以下商品细节

软件方面

这里也可以参考两种电机控制方法基于STC8G2K64S步进电机控制单片机基于STC8G2K64S4单片机控制直流电机两篇文章

我使用了双路跟踪,即两个光敏传感器。对我来说这样足以循迹也相对稳定,如果觉得不稳定的话也可以用四路。双路跟踪原理是,当两个光敏同时检测到黑色时,汽车向前移动;当左侧检测到白色时,意味着汽车向左移动,需要左轮加速或右轮减速;当右侧检测到白色时,意味着汽车向右移动,需要右轮加速或左轮减速

if G1==1&&G2==1    GO if G1==0&&G2==1    turn right if G1==1&&G2==0    turn left

在设计程序的时候,因为地纸是方形的,所以我写的是按格数行走,给多少变量走几个格。格子是通过行驶方向两侧的光敏传感器实现的。当两侧传感器检测到黑线时,格数加一个

#步进电机

正常驾驶代码:

#include "headfile.h"  //sbit P36        //定义P左后电机使能端36 //sbit P06        //定义P右前电机使能端06  //sbit P07        //定义P07为右前电机pwm输出端 //sbit P37        //定义P37为左后电机pwm输出端 //sbit P33        //定义P33左侧光敏 //sbit P32        //定义P32为右侧光敏  void init_all() {  pwm_init(PWM0_P07, 0, 0);  pwm_init(PWM1_P37, 0, 0); }  void go()        {   P36=1;  P06=0;        ///两个电机方向    while(1)  {    if(P33==1&&P32==1)   {    pwm_freq(PWM0_P07, 5000, 5000);        ///右前电机正常速度    pwm_freq(PWM3_P37, 5000, 5000);        ///左后电机正常速度   }       if(P33==1&&P32==0)   {    pwm_freq(PWM0_P07, 5000, 5000);        ///右前电机正常速度    pwm_freq(PWM3_P37, 4000, 5000);        //左后电机减速   }       if(P33==0&&P32==1)   {    pwm_freq(PWM0_P07, 4000, 5000);        //右前电机减速    pwm_freq(PWM3_P37, 5000, 5000);        ///左后电机正常速度   }     } }  void main() {  DisableGlobalIRQ();  //关闭总中断    board_init();   ///初始化内部寄存器,不要删除此代码。  init_all();    EnableGlobalIRQ(); //打开总中断       while(1)  {         go();             } }     

记格数驾驶代码:

#include "headfile.h"  unsigned int i,j;  //sbit P36        //定义P左后电机使能端36 //sbit P06        //定义P右前电机使能端06         //sbit P07        //定义P07为右前电机pwm输出端 //sbit P37        //定义P37为左后电机pwm输出端 //sbit P20        //定义P20用光敏检测黑线记数 //sbit P33        //定义P33左侧光敏 //sbit P32        //定义P32为右侧光敏  void init_all() {  pwm_init(PWM0_P07, 0, 0);  pwm_init(PWM3_P37, 0, 0); }  void go_forward(i)       //定义变量i为格数 {   j=0;  P36=1;  P06=0;        ///两个电机方向    while(1)  {   if(P20==1&&j!=i)        ///两侧光敏检测黑线并计数   {    j  ;        pwm_freq(PWM0_P07, 4000, 5000);        //右前电机低速    pwm_freq(PWM3_P37, 4000, 5000);        //左后电机低速       pca_delay_ms(500);        //延迟穿过黑线    }      if(P33==1&&P32==1)   {    pwm_freq(PWM0_P07, 5000, 5000);        ///右前电机正常速度    pwm_freq(PWM3_P37, 5000, 5000);        ///左后电机正常速度   }       if(P33==1&&P32==0)   {    pwm_freq(PWM0_P07, 5000, 5000);        ///右前电机正常速度    pwm_freq(PWM3_P37, 4000, 5000);        //左后电机减速   }       if(P33==0&&P32==1)   {    pwm_freq(PWM0_P07, 4000, 5000);        //右前电机减速    pwm_freq(PWM3_P37, 5000, 5000);        ///左后电机正常速度   }       if(P20==1&&i==j) break;        //当检测到黑线并记录格数时,退出循环  }  pwm_freq(PWM0_P07, 0, 0);        //右前电机停止  pwm_freq(PWM3_P37, 0, 0);        //左后电机停止 }  void main() {  DisableGlobalIRQ();  //关闭总中断    board_init();   ///初始化内部寄存器,不要删除此代码。  init_all();    EnableGlobalIRQ(); //打开总中断       while(1)  {         go_forward(2);        //向前两格     } }     

#直流电机

正常驾驶代码:

#include "headfile.h"          //sbit P15,P16    //定义P15 P16右前电机方向的能量端 //sbit P35,P36    //定义P35 P左后电机方向36使能端 //sbit P07        //定义P07为右前电机pwm输出端 //sbit P37        //定义P37为左后电机pwm输出端 //sbit P33        //定义P33左侧光敏 //sbit P32        //定义P32为右侧光敏  void init_all() {  pwm_init(PWM0_P07, 0, 0);  pwm_init(PWM3_P37, 0, 0); }  void go()        {   P15=1; P16=0;        //右前电机方向使能
    
    P35=1;
    P36=0;        //左后电机方向使能
	
	while(1)
	{	
		if(P33==1&&P32==1)
		{
			pwm_duty(PWM0_P07, 5000, 5000);        //右前电机正常速度
			pwm_duty(PWM3_P37, 5000, 5000);        //左后电机正常速度
		} 
		
		if(P33==1&&P32==0)
		{
			pwm_duty(PWM0_P07, 5000, 5000);        //右前电机正常速度
			pwm_duty(PWM3_P37, 4000, 5000);        //左后电机减速
		} 
		
		if(P33==0&&P32==1)
		{
			pwm_duty(PWM0_P07, 4000, 5000);        //右前电机减速
			pwm_duty(PWM3_P37, 5000, 5000);        //左后电机正常速度
		} 		
	}
}

void main()
{
	DisableGlobalIRQ();		//关闭总中断
	
	board_init();			//初始化内部寄存器,勿删除此句代码。
	init_all();
	
	EnableGlobalIRQ();	//开启总中断
	
    while(1)
	{
        go();        
    }
}	    

记格数行驶代码:

#include "headfile.h"
 
unsigned int i,j;        
//sbit P15,P16    //定义P15 P16为右前电机方向使能端
//sbit P35,P36    //定义P35 P36为左后电机方向使能端
//sbit P07        //定义P07为右前电机pwm输出端
//sbit P37        //定义P37为左后电机pwm输出端
//sbit P20        //定义P20为检测黑线记格数用光敏
//sbit P33        //定义P33为左侧光光敏
//sbit P32        //定义P32为右侧光光敏

void init_all()
{
	pwm_init(PWM0_P07, 0, 0);
	pwm_init(PWM3_P37, 0, 0);
}

void go_forward(i)        //定义变量i为格数       
{	
    j=0;
	P15=1;
	P16=0;        //右前电机方向使能
    
    P35=1;
    P36=0;        //左后电机方向使能
	
	while(1)
	{
        if(P20==1&&j!=i)        //两边光敏检测黑线并计数
		{
			j++;
			
			pwm_duty(PWM1_P07, 4000);        //右前电机低速 
	  	    pwm_duty(PWM3_P37, 4000);        //左后电机低度
		
			pca_delay_ms(500);        //延时度过黑线 
		}
	
		if(P33==1&&P32==1)
		{
			pwm_duty(PWM0_P07, 5000, 5000);        //右前电机正常速度
			pwm_duty(PWM3_P37, 5000, 5000);        //左后电机正常速度
		} 
		
		if(P33==1&&P32==0)
		{
			pwm_duty(PWM0_P07, 5000, 5000);        //右前电机正常速度
			pwm_duty(PWM3_P37, 4000, 5000);        //左后电机减速
		} 
		
		if(P33==0&&P32==1)
		{
			pwm_duty(PWM0_P07, 4000, 5000);        //右前电机减速
			pwm_duty(PWM3_P37, 5000, 5000);        //左后电机正常速度
		}

        if(P20==1&&i==j) break;        //当检测到黑线并格数记完退出循环
	}
    pwm_duty(PWM1_P07, 0);        //右前电机停止
	pwm_duty(PWM3_P37, 0);        //左后电机停止
}

void main()
{
	DisableGlobalIRQ();		//关闭总中断
	
	board_init();			//初始化内部寄存器,勿删除此句代码。
	init_all();
	
	EnableGlobalIRQ();	//开启总中断
	
    while(1)
	{
        go_forward(2);        //向前前进两格        
    }
}	    

在检测黑线时延迟是为了同一根黑线不检测两次,给一段延时在度过黑线后再继续检测黑线。代码中的库函数为逐飞库函数

本人小白,有问题交流讨论,虚心受教

标签: 电位器2k2k电位器turnp32j3m密封连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台