单片机交流
登录
直播中
王彬
8年用户
1091经验值
私信
关注
[问答]
如何利用51单片机制作简单的循迹小车?
开启该帖子的消息推送
51单片机
如何利用51
单片机
制作简单的循迹小车?
回帖
(1)
陆焙兆
2021-11-3 10:01:44
一、前言
因为自己对编程十分热爱,同时为了夯实竞赛班和大创项目的基础,我自学了51单片机,为了检验自己的学习成果,我制作了简易的寻迹小车。
二、相关硬件
芯片为STC89C52RC
稳压模块
由于电池选择的是18650锂电池,过放会导致电池永久损坏,就选择了带有示数的稳压模块;将电池盒的两根线接入VIN即可(注意正负极),利用螺丝刀旋转螺丝即可调压。
电机驱动模块L298N
非常常用的电机驱动模块,由稳压引出线给电机驱动供电,电机驱动自带5V调压引出线给单片机供电,注意要共地;逻辑输入后电机工作情况如下:
四路循迹模块
在装上小车前,调整好检测距离,当发射红外线遇到白色则会反射回来,输出低电平,同时主板上对应的灯亮起;遇到黑色会被吸收,输出高电平,同时主板上对应的灯熄灭。
最后组装好的成品
三、软件实现
代码如下:
#include
typedef unsigned int u16;
typedef unsigned char u8;
***it right_ENA=P1^0; //小车右侧电机驱动
***it right_ENB=P1^5;
***it right_IN1=P1^1;
***it right_IN2=P1^2;
***it right_IN3=P1^3;
***it right_IN4=P1^4;
***it left_ENA=P0^0; //小车左侧电机驱动
***it left_ENB=P0^5;
***it left_IN3=P0^1;
***it left_IN4=P0^2;
***it left_IN1=P0^3;
***it left_IN2=P0^4;
***it left1=P2^4; //四路红外
***it left2=P2^3;
***it right2=P2^2;
***it right1=P2^1;
u8 pwm_t=0; //计时器溢出统计
u8 pwm_right_val=0; //右侧电机使能值
u8 pwm_left_val=0; //左侧电机使能值
void forward() //前进
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=185;
pwm_right_val=185;
}
void turnLeft1() //左转小弯
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=0;
left_IN2=1;
left_IN3=0;
left_IN4=1;
pwm_left_val=120;
pwm_right_val=100;
}
void turnLeft2() //左转大弯
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=0;
left_IN2=1;
left_IN3=0;
left_IN4=1;
pwm_left_val=100;
pwm_right_val=80;
}
void turnRight1() //右转小弯
{
right_IN1=0;
right_IN2=1;
right_IN3=0;
right_IN4=1;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=100;
pwm_right_val=120;
}
void turnRight2() //右转大弯
{
right_IN1=0;
right_IN2=1;
right_IN3=0;
right_IN4=1;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=80;
pwm_right_val=100;
}
void stop() //停止
{
right_IN1=0;
right_IN2=0;
right_IN3=0;
right_IN4=0;
left_IN1=0;
left_IN2=0;
left_IN3=0;
left_IN4=0;
}
void follow() //根据红外的不同情况循迹
{
if((right2 == 0)&&(right1 == 0)&&(left1 == 0)&&(left2 == 0)
||(right2 == 1)&&(right1 == 1)&&(left1 == 1)&&(left2 == 1)
||(right2 == 1)&&(right1 == 0)&&(left1 == 0)&&(left2 == 1))
{
flag = 0;
}
if((right2 == 1)&&(right1 ==0)&&(left1 == 0)&&(left2 == 0))
{
flag = 1;
}
if((right2 == 0)&&(right1 == 0)&&(left1 == 0)&&(left2 == 1))
{
flag = 2;
}
if((right2 == 0)&&(right1 == 0)&&(left1 == 1)&&(left2 == 0)
||(right2 == 0)&&(right1 == 0)&&(left1 == 1)&&(left2 == 1))
{
flag = 3;
}
if((right2 == 0)&&(right1 == 1)&&(left1 == 0)&&(left2 == 0)
||(right2 == 1)&&(right1 == 1)&&(left1 == 0)&&(left2 == 0))
{
flag = 4;
}
switch(flag)
{
case 0:forward();break;
case 1:stop();turnRight1();break;
case 2:stop();turnLeft1();break;
case 3:stop();turnLeft2();break;
case 4:stop();turnRight2();break;
default:stop();break;
}
}
void main()
{
TMOD=0x02; //定时器模式设置并赋初值,打开定时器和中断
TH0=220;
TL0=220;
TR0=1;
ET0=1;
EA=1;
while(1)
{
follow();
}
}
void time0() interrupt 1
{
if(pwm_t >=256) //占空比分为256份,但最大200就不能转
pwm_t=0;
if(pwm_t < pwm_left_val)
left_ENA=left_ENB=0;
else
left_ENA=left_ENB=1;
if(pwm_t < pwm_right_val)
right_ENA=right_ENB=0;
else
right_ENA=right_ENB=1;
pwm_t++;
}
四、总结
这次因为时间紧张,且传感器受光影响太大,规定时间内没有做出走内圈的程序,只有了大致思路;但这个循迹图总体来讲不是太难,十分适合练手。若有小伙伴借鉴了我的程序,可以适当更改占空比的份数,定时器的初值等让小车走的更稳定。
附录:循迹图
一、前言
因为自己对编程十分热爱,同时为了夯实竞赛班和大创项目的基础,我自学了51单片机,为了检验自己的学习成果,我制作了简易的寻迹小车。
二、相关硬件
芯片为STC89C52RC
稳压模块
由于电池选择的是18650锂电池,过放会导致电池永久损坏,就选择了带有示数的稳压模块;将电池盒的两根线接入VIN即可(注意正负极),利用螺丝刀旋转螺丝即可调压。
电机驱动模块L298N
非常常用的电机驱动模块,由稳压引出线给电机驱动供电,电机驱动自带5V调压引出线给单片机供电,注意要共地;逻辑输入后电机工作情况如下:
四路循迹模块
在装上小车前,调整好检测距离,当发射红外线遇到白色则会反射回来,输出低电平,同时主板上对应的灯亮起;遇到黑色会被吸收,输出高电平,同时主板上对应的灯熄灭。
最后组装好的成品
三、软件实现
代码如下:
#include
typedef unsigned int u16;
typedef unsigned char u8;
***it right_ENA=P1^0; //小车右侧电机驱动
***it right_ENB=P1^5;
***it right_IN1=P1^1;
***it right_IN2=P1^2;
***it right_IN3=P1^3;
***it right_IN4=P1^4;
***it left_ENA=P0^0; //小车左侧电机驱动
***it left_ENB=P0^5;
***it left_IN3=P0^1;
***it left_IN4=P0^2;
***it left_IN1=P0^3;
***it left_IN2=P0^4;
***it left1=P2^4; //四路红外
***it left2=P2^3;
***it right2=P2^2;
***it right1=P2^1;
u8 pwm_t=0; //计时器溢出统计
u8 pwm_right_val=0; //右侧电机使能值
u8 pwm_left_val=0; //左侧电机使能值
void forward() //前进
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=185;
pwm_right_val=185;
}
void turnLeft1() //左转小弯
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=0;
left_IN2=1;
left_IN3=0;
left_IN4=1;
pwm_left_val=120;
pwm_right_val=100;
}
void turnLeft2() //左转大弯
{
right_IN1=1;
right_IN2=0;
right_IN3=1;
right_IN4=0;
left_IN1=0;
left_IN2=1;
left_IN3=0;
left_IN4=1;
pwm_left_val=100;
pwm_right_val=80;
}
void turnRight1() //右转小弯
{
right_IN1=0;
right_IN2=1;
right_IN3=0;
right_IN4=1;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=100;
pwm_right_val=120;
}
void turnRight2() //右转大弯
{
right_IN1=0;
right_IN2=1;
right_IN3=0;
right_IN4=1;
left_IN1=1;
left_IN2=0;
left_IN3=1;
left_IN4=0;
pwm_left_val=80;
pwm_right_val=100;
}
void stop() //停止
{
right_IN1=0;
right_IN2=0;
right_IN3=0;
right_IN4=0;
left_IN1=0;
left_IN2=0;
left_IN3=0;
left_IN4=0;
}
void follow() //根据红外的不同情况循迹
{
if((right2 == 0)&&(right1 == 0)&&(left1 == 0)&&(left2 == 0)
||(right2 == 1)&&(right1 == 1)&&(left1 == 1)&&(left2 == 1)
||(right2 == 1)&&(right1 == 0)&&(left1 == 0)&&(left2 == 1))
{
flag = 0;
}
if((right2 == 1)&&(right1 ==0)&&(left1 == 0)&&(left2 == 0))
{
flag = 1;
}
if((right2 == 0)&&(right1 == 0)&&(left1 == 0)&&(left2 == 1))
{
flag = 2;
}
if((right2 == 0)&&(right1 == 0)&&(left1 == 1)&&(left2 == 0)
||(right2 == 0)&&(right1 == 0)&&(left1 == 1)&&(left2 == 1))
{
flag = 3;
}
if((right2 == 0)&&(right1 == 1)&&(left1 == 0)&&(left2 == 0)
||(right2 == 1)&&(right1 == 1)&&(left1 == 0)&&(left2 == 0))
{
flag = 4;
}
switch(flag)
{
case 0:forward();break;
case 1:stop();turnRight1();break;
case 2:stop();turnLeft1();break;
case 3:stop();turnLeft2();break;
case 4:stop();turnRight2();break;
default:stop();break;
}
}
void main()
{
TMOD=0x02; //定时器模式设置并赋初值,打开定时器和中断
TH0=220;
TL0=220;
TR0=1;
ET0=1;
EA=1;
while(1)
{
follow();
}
}
void time0() interrupt 1
{
if(pwm_t >=256) //占空比分为256份,但最大200就不能转
pwm_t=0;
if(pwm_t < pwm_left_val)
left_ENA=left_ENB=0;
else
left_ENA=left_ENB=1;
if(pwm_t < pwm_right_val)
right_ENA=right_ENB=0;
else
right_ENA=right_ENB=1;
pwm_t++;
}
四、总结
这次因为时间紧张,且传感器受光影响太大,规定时间内没有做出走内圈的程序,只有了大致思路;但这个循迹图总体来讲不是太难,十分适合练手。若有小伙伴借鉴了我的程序,可以适当更改占空比的份数,定时器的初值等让小车走的更稳定。
附录:循迹图
举报
更多回帖
rotate(-90deg);
回复
相关问答
51单片机
求
简单
红外
循迹
小车
制作
程序与仿真图
2014-05-29
4987
如何
利用
51
单片机制作
简易的光电
小车
?
2021-09-26
1706
如何
利用
12864和
51
单片机制作
游戏机???
2013-11-08
3865
如何
利用
51
单片机制作
从左至右再从右
制作
的流水灯呢
2021-09-17
1178
如何
利用
51
单片机制作
流水灯?
2021-10-09
1556
如何
制作
一个
循迹
小车
?
2022-01-18
1437
如何
利用
STC89c52rc
单片机
实现红外
循迹
小车
的设计?
2021-10-20
2112
如何
利用
LDC1314检测铁丝
制作
循迹
小车
?
2018-12-24
2501
求大佬分享以
51
单片机
为基础的自动
循迹
小车
的程序
2021-10-13
976
如何
制作
出一个
简单
的
单片机
小车
?
2021-10-28
1579
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
首页
论坛版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分