1、循迹小车是一种能够自己寻找轨迹并按轨迹运动的“智能”车。本文简要记录这一电子制作过程,希望大家喜欢。有什么建议和意见,欢迎大家留言。
2、根据元器件清单清点器件蚂裂,看是否缺件少件。下图是元器件全家福:
3、依次焊接元器件:要先焊接小的元器件,再焊接大的元器件,最后粘上电池座和马达。焊接好所有元器件后再次肉眼检查有没有焊反,虚焊漏焊的点。确认无误后,进行第三步。
4、焊接好所有元器件后再次肉眼检查有没有焊反,虚焊漏焊的点。确认无误后,进行第三步。
5、装上电池调试。电马达的2根线可搜衫能闷漏闭会装反,光敏电阻和发光二极管的相对位置可能需要调整,可调电阻(电位器)的电阻值可能不合适需要调整。
6、调试后,小车可以再黑色的轨道上自动循迹,制作成功。黑色轨迹可以自己做,用黑色胶布再地板上自定义轨道,小车慢悠悠的在轨道上行走。
主程序和中断程序入口 ***
*************************************
ORG 0000H程序执行起始地址
LJMP START 跳至START
ORG 0003H外中断0入口
LJMP INTEX0 跳至INTEX0中断服务程序
ORG 000BH定时器T0中断入口
RETI 中断返回
ORG 0013H外中断1入口
LJMP INTEX1 跳至INTEX1中断服务昌毁程序
ORG 001BH定时器T1中断入口
LJMP INTT1 跳至INTT1中断服务程序
ORG 0023H串口锋迅毁中断入口
RETI 中断返回
ORG 002BH定时器T2中断入口
RETI 中断返回
***************************
* *
*初始化程序 *
* *
****************************
CLEARMEMIO: MOVR0, #70H 清70H-76H显示单元
MOVR7, #07H 循环次数
ML0: MOV@R0, #00H 清0
INCR0 下一地址
DJNZ R7, ML0未完再循环
MOVTMOD,#10H T1为16位定时器
MOVR4,#14H1秒定时用(50毫秒20次)
MOVTL1,#0B0H 50毫秒定时用初值
MOVTH1,#3CH
MOV 20H,#00H 清0 *** 作
MOV 21H,#00H
MOV 22H,#00H
MOV 23H,#00H
MOV 24H,#00H
CLR 30H 清停车标志
SETB ET1 开银备T1中断
SETB EX1 开外中断1
SETB IT1 外中断1采用边沿触发
SETB IT0 外中断0优先级为1(最高)
SETB EX0 开外中断0
SETBEA 开总中断允许
SETBTR1 开启定时器T1
RET 子程序返回
*************************************
**
*主 程 序*
**
*************************************
START: LCALLCLEARMEMIO 上电初始化
SETB P1.6 选择7.5V输出
CLR P1.7 选择7.5V输出
SETB P3.7 前进状态
CLR P3.6 前进状态
CLR P1.0 电机供电开始
;MAIN:LCALLDISP LED显示一次
LJMP MAIN 转MAIN循环
NOP PC值出错处理
NOP
LJMP START 重新初始化
*************************************
**
*外中断0服务程序,用作跑道位置处理 *
*23H作跑道计数器 *
*************************************
INTEX0:PUSH ACC 堆栈保护
PUSH PSW
CLR EX0 关中断
LCALLDISP LED显示一次(延时抗干扰)
JB P3.2,IN0RET P3.2为1退出(干扰)
INC 23H 跑道计数器加1
MOV A,23H 数据入A
CJNE A,#06H,JUDGE1 不是第6道转JUDGE1
LCALLSTOP 是第6道,停车
LJMP IN0RET 转中断退出
JUDGE1:CJNE A,#03H,JUDGE2 不是第3道转JUDGE2
LCALLSTOPSLOW 是第3道,变慢车
LJMP IN0RET 转中断退出
JUDGE2:CJNE A,#04H,JUDGE3 不是第4道转JUDGE3
LCALLFAST 是第4道,变快车
LJMP IN0RET 转中断退出
JUDGE3:CJNE A,#05H,IN0RET 不是第5道转INORET退出
LCALLSTOPSLOW 是第5道,变慢车
IN0RET:CLR IE0 清外中断0中断标志
POP PSW 恢复现场
POP ACC
LCALLDL7MS 延时7毫秒(抗干扰)
SETB EX0 开外中断0
RETI 中断返回
************************************
* 慢车控制子程序 *
************************************
STOPSLOW: CLR P1.6 关7.5V电源
CPL P3.6 反向驱动(刹车)
CPL P3.7 反向驱动
LCALLDS50MS 刹车时间(可根据试车情况调整)
LCALLDS50MS
LCALLDS50MS
CPL P3.6 正向驱动
CPL P3.7 正向驱动
SETB P1.7 开4.3V电源
RET 返回
************************************
* 快车控制子程序*
************************************
FAST: CLR P1.7 关4.3V电源
SETB P1.6 开7.5V电源
RET 返回
************************************
* 停车控制程序 *
************************************
STOP: MOV 23H,#00H 跑道计数单元清0
CPL P3.6 反向驱动(刹车)
CPL P3.7 反向驱动(刹车)
LCALLDS50MS 刹车时间
LCALLDS50MS 刹车时间(可调整)
SETBP1.0 关电机电源
SETBPT1 定时器T1为高优先级
LCALLDS10S 停车10秒
CLR PT1 恢复T1为低优先级
SETB P1.6 开7.5V电源(高速)
CLR P1.7 关4.3V
CLR P1.0 电机电源开
CPL 30H 停车点位置判断标志取反
JB 30H,STREN 为1(中途停车)转STREN
LCALLCLR00 是终点,调复0程序
STREN:RET 返回
智能小车程序#include "reg52.h"
#define det_Dist 2.55 //单个脉冲对应的小车行走距离,其值为车轮周长/4
#define RD 9 //小车对角轴长度
#define PI 3.1415926
#define ANG_90 90
#define ANG_90_T 102
#define ANG_180 189
/*============================全局变量定义区============================*/
sbit P10=P1^0//控制继电器的开闭
sbit P11=P1^1//控制金属接近开关
sbit P12=P1^2//控制颜色传感器的开闭
sbit P07=P0^7//控制声光信号的开启
sbit P26=P2^6//接收颜色传感器的信号,白为0,黑为1
sbit P24=P2^4//左
sbit P25=P2^5//右 接收左右光传感器的信号,有光为0
unsigned char mType=0//设置运动的方式,0 向前 1 向左 2 向没搭后 3 向右
unsigned char Direction=0//小车的即时朝向 0 朝上 1 朝左 2 朝下 3 朝右
unsigned sX=50unsigned char sY=0//小车的相对右下角的坐标 CM(sX,sY)
unsigned char StartTask=0//获得铁片后开始执行返回卸货任务,StartTask置一
unsigned char Inter_EX0=0// 完成一个完整的任务期间只能有一次外部中断
// Inter_EX0记录外部中断0的中断状态
// 0 动作最近的前一次未中断过,
// 1 动作最近的前一丛森次中断过
unsigned char cntIorn=0//铁片数
unsigned char bkAim=2//回程目的地,0为A仓库,1为B仓库,2为停车场,
//(在MAIN中接受铁片颜色判断传感器的信号来赋值)
unsigned char Light_Flag=0//进入光引导区的标志(1)
unsigned int cntTime_5Min=0//时间周期数渗察亩,用于 T0 精确定时
unsigned int cntTime_Plues=0//霍尔开关产生的脉冲数
/*============================全局变量定义区============================*/
/*------------------------------------------------*/
/*-----------------通用延迟程序-------------------*/
/*------------------------------------------------*/
void delay(unsigned int time) // time*0.5ms延时
{
unsigned int i,j
for(j=0j<timej++)
{
for(i=0i<60i++)
{}
}
}
/*-----------------------------------------------*/
/*-------------------显示控制模块----------------*/
/*-----------------------------------------------*/
/*数码管显示,显示铁片的数目(设接在P0,共阴)*/
void Display(unsigned char n)
{
char Numb[12]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x37,0x77}
P0=Numb[n]
}
/*-----------------------------------------------*/
/*-------------------传感器模块------------------*/
/*-----------------------------------------------*/
/*光源检测程序: */
/*用于纠正小车运行路线的正确性*/
unsigned char LightSeek()
{ void Display(unsigned char)
bit l,r
l=P24
r=P25
if(l==0&&r==1)
{
//Display(1)
return (3)//偏左,向右开
}
if(r==0&&l==1)
{
//Display(3)
return(1)//偏右,向左开
}
if((l==1&&r==1)||(l==0&&r==0))
{//Display(9)
return(0)//没有偏离,前进
}
}
/*铁片检测程序: */
/*判断铁片的颜色,设定bkAim,0为A仓库,1为B仓库,2为停车场*/
void IornColor()
{
delay(4000)
bkAim=(int)(P26)
Display((int)(P26)+2)
}
/*-----------------------------------------------*/
/*------------------运动控制模块-----------------*/
/*-----------------------------------------------*/
/*====基本动作层:完成基本运动动作的程序集====*/
/*运动调整程序: */
/*对小车的运动进行微调*/
void ctrMotor_Adjust(unsigned char t)
{
if(t==0)
{
P2=P2&240|11//用来解决两电机不对称的问题
delay(6)
}
if(t==3)
{
P2=P2&250//向左走
delay(1)
}
if(t==1)
{
P2=(P2&245)
delay(1)//向右走
}
P2=((P2&240)|15)
delay(10)
}
/*直走程序:*/
/*控制小车运动距离,dist为运动距离(cm),type为运动方式(0 2)*/
/*只改变小车sX 和 sY的值而不改变Direction的值. */
void ctrMotor_Dist(float dist,unsigned char type)
{unsigned char t=0
mType=type
P2=((P2&240)|15)
cntTime_Plues=(int)(dist/det_Dist)
while(cntTime_Plues)
{
if(Inter_EX0==1&&StartTask==0)
{
cntTime_Plues=0
break
}
if(Light_Flag==1) t=LightSeek()
if(type==0) //向前走
{
P2=P2&249
delay(40)
ctrMotor_Adjust(t)
}
if(type==2) //向后退
{
P2=P2&246
delay(50)
ctrMotor_Adjust(t)
}
P2=((P2&240)|15)
if(mType==2) delay(60)//刹车制动 0.5ms
else delay(75)
}
}
/*拐弯程序: */
/*控制小车运动角度,type为运动方式(1 3) */
/*只改变小车Direction的值而不改变sX 和 sY的值*/
void ctrMotor_Ang(unsigned char ang,unsigned char type,unsigned char dir)
{
unsigned char i=0
mType=type
P2=((P2&240)|15)
cntTime_Plues=(int)((PI*RD*90/(180*det_Dist)*1.2)*ang/90)
while(cntTime_Plues)
{
if(Inter_EX0==1&&StartTask==0)
{
cntTime_Plues=0
break
}
if(type==1) //向左走
{
P2=P2&250
delay(100)
ctrMotor_Adjust(0)
}
if(type==3) //向右走
{
P2=P2&245
delay(100)
ctrMotor_Adjust(0)
}
P2=((P2&240)|15)
delay(50)//刹车制动 0.5ms
}
if(!(Inter_EX0==1&&StartTask==0))
{
Direction=dir
}
}
/*====基本路线层:描述小车基本运动路线的程序集====*/
/*当小车到达仓库或停车场时,放下铁片或停车(0,1为仓库,2为停车场)*/
void rchPlace()
{unsigned int time,b,s,g
time=(int)(cntTime_5Min*0.065535)//只有一个数码管时,轮流显示全过程秒数 个 十 百
b=time%100
s=(time-b*100)%100
g=(time-b*100-s*10)%10
if(bkAim==2)
{
//到达停车场了,停车
EA=0
P2=((P2&240)|15)
while(1)
{
Display(10)//N
delay(2000)
Display(cntIorn)
delay(2000)
Display(11)//A
delay(2000)
Display(b)
delay(2000)
Display(s)
delay(2000)
Display(g)
delay(2000)
}
}
else
{
if(Inter_EX0==1&&StartTask==1)P10=0//到达仓库,卸下铁片
}
}
/*无任务模式: */
/*设置小车的固定运动路线,未发现铁片时的运动路线*/
void BasicRoute()
{ //Light_Flag=1
ctrMotor_Dist(153,0)
//Light_Flag=0
ctrMotor_Ang(ANG_90,1,1)
ctrMotor_Dist(100-sX,0)
ctrMotor_Dist(125,2)
ctrMotor_Dist(73,0)
ctrMotor_Ang(ANG_90,1,2)
//Light_Flag=1
ctrMotor_Dist(153,0)
//Light_Flag=0
ctrMotor_Ang(ANG_180,1,0)
rchPlace()
}
/*任务模式: */
/*设置小车的发现铁片后的运动路线*/
void TaskRoute()
{
//基本运行路线表,记载拐弯 0 向前 1 左拐 2 向后 3 右拐,正读去A区反读去B区
StartTask=1
ctrMotor_Ang(ANG_90_T,1,2)
if(bkAim==1)//仓库A
{
ctrMotor_Dist(10,0)
P2=((P2&240)|15)
delay(60)
ctrMotor_Ang(ANG_90_T,1,3)
ctrMotor_Dist(100-sX,2)
ctrMotor_Ang(ANG_90_T,1,2)
Light_Flag=1
ctrMotor_Dist(153,2)
Light_Flag=0
// ctrMotor_Ang(208,1,0)
}
else if(bkAim==0) //仓库B
{
ctrMotor_Dist(10,0)
P2=((P2&240)|15)
delay(60)
ctrMotor_Ang(ANG_90_T,1,3)
ctrMotor_Dist(100-sX,0)
ctrMotor_Ang(ANG_90_T,1,0)
Light_Flag=1
ctrMotor_Dist(153,2)
Light_Flag=0
//ctrMotor_Ang(208,1,0)
}
delay(5000)
rchPlace()
}
/*---------------------------------------------*/
/*-------------------主程序段------------------*/
/*---------------------------------------------*/
void main()
{
delay(4000)
P2=0xff//初始化端口
P07=0
P1=0
TMOD=0x01//初始化定时器0/1 及其中断
TL0=0
TH0=0
TR0=1
ET0=1
ET1=1
IT0=1//初始化外部中断
EX0=1
IT1=1
EX1=1
EA=1
P11=1
while(1)
{
Display(cntIorn)
bkAim=2
BasicRoute()
if(Inter_EX0==1)
{
TaskRoute()//按获得铁片后的路线运动
IE0=0
EX0=1
}
Inter_EX0=0
}
}
/*----------------------------------------------------*/
/*----------------------中断程序段--------------------*/
/*----------------------------------------------------*/
/*定时器0中断程序: */
/*当时间过了5分钟,则就地停车并进入休眠状态*/
void tmOver(void) interrupt 1
{
cntTime_5Min++
TL0=0
TH0=0
if(cntTime_5Min>=4520)
{
Display(5)
P2=((P2&240)|15)
EA=0//停车程序
P07=1
delay(4000)
PCON=0X00
while(1)
}
}
/*外部中断0中断程序: */
/*发现铁片,发出声光信号并将铁片吸起,发光二极管和蜂鸣器*/
/*并联在一起(设接在P07). 0为A仓库,1为B仓库,2为停车场*/
void fndIorn(void) interrupt 0
{
unsigned char i
P10=1
P2=((P2&240)|15)//停车
P07=1
delay(1000)//刹车制动 0.5ms
P07=0
Inter_EX0=1
cntIorn++
Display(cntIorn)
for(i=0i<40i++)
{
P2=P2&249
delay(2)
P2=((P2&240)|15)
delay(2)
}
P2=P2&249
delay(100)
P2=((P2&240)|15)//停车
IornColor()//判断铁片黑白,设置bkAim
for(i=0i<95i++)
{
P2=P2&249
delay(3)
P2=((P2&240)|15)
delay(2)
}
P2=((P2&240)|15)//停车
delay(4000)//把铁片吸起来
EX0=0
}
/*外部中断1中断程序:*/
/*对霍尔开关的脉冲记数,对小车的位置进行记录,以便对小车进行定位*/
void stpMove(void) interrupt 2
{
cntTime_Plues--
if(Direction==0) //向上
{
if(mType==0) sY+=det_Dist
else if(mType==2)
sY-=det_Dist
}
else if(Direction==1) //向左
{
if(mType==0) sX+=det_Dist
else if(mType==2)
sX-=det_Dist
}
else if(Direction==2) //向下
{
if(mType==0) sY-=det_Dist
else if(mType==2)
sY+=det_Dist
}
else if(Direction==3) //向右
{
if(mType==0) sX-=det_Dist
else if(mType==2)
sX+=det_Dist
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)