基于51单片机的循迹小车
前言
该小车采用单片机STC89C52作为主控制核心,通过传感器传来的信号,对当前环境作出判断,最后对电机做出相应的动作。单片机通过红外传感器检测场地黑线,从而控制电机驱动模块,改变电机转速来控制小车方向,从而达到循迹的目的。
一、系统概述
整个系统包括51单片机控制模块、电机驱动模块、循迹模块、电源和小车车体。
1.工作原理
·本系统采用简单明了的设计方案。
·通过高发射功率红外光电二极管和高灵敏光电晶体管组成的传感器循迹模块判断黑线路径。
·然后由STC89C52单片机通过IO口控制L298N驱动模板改变两个直流电机的工作状态。
·最后实现小车循迹
2.控制系统结构框图
二、循迹小车硬件
1.电机驱动模块
L298N实物接线图及驱动原理图:
(1) L298N是一个内部有两个H桥的驱动芯片,这样电机的运转只需要用三个信号控制:两个方向信号和一个使能信号。(输入的电压不可超过它的额定电压)
(2)L298N芯片的工作电压需要两路:
第一路:输出供给电机回路的工作电源
第二路:输入逻辑控制回路电源5V(电源出/入)
L298N接入直流电机的端口接法:
2.循迹模块
(1)循迹原理: 利用红外线对于不同颜色具有不同的反射性质的特点。在小车行驶过程中传感器的红外发射二极管不断发射红外光,当红外光遇到白色地面时发生漫反射,红外对管接收管接收反射光;如果遇到黑线则红外光被吸收,则红外管接收不到信号。
红外对管采集回来的信号通过2路循迹传感器模块里面的LM339比较器后输出高或低电平,从而实现信号的检测。
原先只用了两个红外传感器,发现它并不能完成直角拐弯,需要四个传感器配合才能完成。
(2)所谓的差速,是指左右两车轮的速度差,假如左边车轮比右边快,则小车会偏向右。同时,左边的车轮转速比右的满,那么小车会向左边转动。
目前主要有以下两种方式:
①小车向左转,可以左轮停止,左轮继续转动,这样可实现左转,这种方式实现小角度的转弯,在角度不大时可采用此种方式。
②小车向左转,可以是左轮反转,右轮正转,这样可以实现大角度的左转,甚至可以进行原地打转。
同理可推出小车如何向右转向。
三、循迹小车软件
(1)主要采用C语言来编译程序。模块化结构程序的设计,可以使系统软件便于调试与优化,也使其他人更好的理解和阅读系统的程序设计。因此,软件的设计上,运用了模块化程序的结构对软件进行设计,使得程序变得更加直观易懂。程序的主要模块有:主程序、定时溢出中断服务程序、外部中断服务程序。
(2) Keil C51单片机软件开发系统可用于编译C或汇编源文件。然后分别由C51编译器编译生成目标文件(.OBJ)。目标文件与库文件一起经LIB51连接定位生成绝对目标文件(.ABS)。ABS文件由OH51转换成标准的Hex文件。
(3) 在软件调试中,使用功能强大的WAVE 6000软件进行软件编译与调试,使用Microcontroller ISP Software及其配套的单片机对程序进行烧录。
四、源码(仅供参考)
#ifndef _LED_H_
#define _LED_H_
//定义小车驱动模块输入IO口
sbit L293D_IN1=P1^2;
sbit L293D_IN2=P1^3;
sbit L293D_IN3=P1^4;
sbit L293D_IN4=P1^5;
sbit L293D_EN1=P1^6;
sbit L293D_EN2=P1^7;
/***蜂鸣器接线定义*****/
sbit BUZZ=P2^3;
#define Left_1_led P3_4 //左传感器
#define Right_1_led P3_5 //右传感器
#define Left_moto_pwm P1_6 //PWM信号端
#define Right_moto_pwm P1_7 //PWM信号端
#define Left_moto_go {P1_2=1,P1_3=0;} //左电机向前走
#define Left_moto_back {P1_2=0,P1_3=1;} //左边电机向后转
#define Left_moto_Stop {P1_2=0,P1_3=0;} //左边电机停转
#define Right_moto_go {P1_4=1,P1_5=0;} //右边电机向前走
#define Right_moto_back {P1_4=0,P1_5=1;} //右边电机向后走
#define Right_moto_Stop {P1_4=0,P1_5=0;} //右边电机停转
unsigned char pwm_val_left =0;//变量定义
unsigned char push_val_left =0;// 左电机占空比N/20
unsigned char pwm_val_right =0;
unsigned char push_val_right=0;// 右电机占空比N/20
bit Right_moto_stop=1;
bit Left_moto_stop =1;
unsigned int time=0;
/************************************************************************/
//前速前进
void run(void)
{
push_val_left=15; //速度调节变量 0-20。。。0最小,20最大
push_val_right=15;
Left_moto_go ; //左电机往前走
Right_moto_go ; //右电机往前走
}
//左转
void leftrun(void)
{
push_val_left=15;
push_val_right=20;
Right_moto_go ; //右电机往前走
Left_moto_Stop ; //左电机不动
}
//右转
void rightrun(void)
{
push_val_left=20;
push_val_right=15;
Left_moto_go ; //左电机往前走
Right_moto_Stop ; //右电机不动
}
//停止
void stop(void)
{
Right_moto_Stop ; //右电机停止
Left_moto_Stop ; //左电机停止
}
/************************************************************************/
/* PWM调制电机转速 */
/************************************************************************/
/* 左电机调速 */
/*调节push_val_left的值改变电机转速,占空比 */
void pwm_out_left_moto(void)
{
if(Left_moto_stop)
{
if(pwm_val_left<=push_val_left)
{
Left_moto_pwm=1;
// Left_moto_pwm1=1;
}
else
{
Left_moto_pwm=0;
// Left_moto_pwm1=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}
else
{
Left_moto_pwm=0;
// Left_moto_pwm1=0;
}
}
/******************************************************************/
/* 右电机调速 */
void pwm_out_right_moto(void)
{
if(Right_moto_stop)
{
if(pwm_val_right<=push_val_right)
{
Right_moto_pwm=1;
// Right_moto_pwm1=1;
}
else
{
Right_moto_pwm=0;
// Right_moto_pwm1=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}
else
{
Right_moto_pwm=0;
// Right_moto_pwm1=0;
}
}
/***************************************************/
///*TIMER0中断服务子函数产生PWM信号*/
void timer0()interrupt 1 using 2
{
TH0=0XFc; //1Ms定时
TL0=0X18;
time++;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}
#include<AT89X52.H> //包含51单片机头文件,内部有各种寄存器定义
#include<ZY-4WD_PWM.H> //包含HL-1蓝牙智能小车驱动IO口定义等函数
//主函数
void main(void)
{
P1=0X00; //关电机
TMOD=0X01;
TH0= 0XFc; //1ms定时
TL0= 0X18;
TR0= 1;
ET0= 1;
EA = 1; //开总中断
while(1) //无限循环
{
//有信号为0 没有信号为1
if(Left_1_led==0&&Right_1_led==0)
run(); //调用前进函数
else
{
if(Left_1_led==1&&Right_1_led==0) //左边检测到黑线
{
leftrun(); //调用小车左转 函数
}
if(Right_1_led==1&&Left_1_led==0) //右边检测到黑线
{
rightrun(); //调用小车右转 函数
}
if(Right_1_led==1&&Left_1_led==1) //悬空状态 避悬崖
{
stop(); //调用小车停止
}
}
}
}```
版权声明:本文为CSDN博主「·Cx330·」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_47854694/article/details/115471710
暂无评论