基于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); //向前前进两格
}
}
在检测黑线时延迟是为了同一根黑线不检测两次,给一段延时在度过黑线后再继续检测黑线。代码中的库函数为逐飞库函数
本人小白,有问题交流讨论,虚心受教