寻迹小车程序
A. 智能小车循迹程序
电设小车循迹模块 转自:http://blog.sina.com.cn/s/blog_4bb018e10100ermy.html供参考://包含所需头文件
#include <ioM16v.h>
#include <macros.h>
#include"time1_init.h"
#include"motor.h"#define ahead 1
#define backwards 0
#define compare(x,y) (x<y?1:0)
#define mid 0X17//端口初始化
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x08;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;
}void timer0_init(void)
{
TCCR0 = 0x00;//停止定时器
TCNT0 = 0x00;//初始值
OCR0 = 0x17;//匹配值
TIMSK |= 0x00;//中断允许
TCCR0 = 0x7D;//启动定时器
}void adc_init(void)
{
//adc转换初始化
ADCSRA = 0x00; //禁止AD转换
ADCSRA|=BIT(ADIF);
ADMUX=0X46;
SFIOR |= 0x00;
ACSR = 0x80; //禁止模拟比较器
ADCSRA = 0xE7;
}void init_devices(void)
{
CLI(); //禁止所有中断
MCUCR = 0x00;
MCUCSR = 0x80;//禁止JTAG
GICR = 0x00;
port_init();
timer0_init();
timer1_init();
adc_init();
SEI();//开全局中断
}uint sensor_head[3],sensor_back[3],cord; //存储6个传感器AD转换的值
uchar offset ; //黑线偏移小车中心轴的距离
uint sensor_compare_head[3]={300,300,300},sensor_compare_back[3]={300,300,300}; //判断黑线是否位于传感器下的阈值uchar start_head_sensor(void)
{
uchar i,j=0,sum=0;
ADMUX=0X40;
ADCSRA=0xC7;
while(ADCSRA&BIT(ADSC));
for(i=0;i<3;i++)
{
ADMUX=0X40+i; //启用前端传感器0,1,2通道
ADCSRA=0xC7;
while(ADCSRA&BIT(ADSC));
sensor_head[i]=ADC;
}
for(i=3;i;i--)
{
if(compare(sensor_head[i-1],sensor_compare_head[i-1]))
{
sum+=i-1;
j++;
}
}
if(j)
offset=sum*2/j;
ADMUX=0X46;
ADCSRA=0xE7;
return offset;
}
uchar start_back_sensor(void)
{
uchar i,j=0,sum=0;
ADMUX=0X43;
ADCSRA=0xC7;
while(ADCSRA&BIT(ADSC));
for(i=0;i<3;i++)
{
ADMUX=0X43+i; //启用前端传感器0,1,2通道
ADCSRA=0xC7;
while(ADCSRA&BIT(ADSC));
sensor_back[i]=ADC;
}
for(i=3;i;i--)
{
if(compare(sensor_back[i-1],sensor_compare_back[i-1]))
{
sum+=i-1;
j++;
}
}
if(j)offset=sum*2/j;
ADMUX=0X46;
ADCSRA=0XE7;
return offset;
}//角度传感器滤波函数
uint cord_sensor(void)
{
uchar i;
uint max=0,min=1023,sum=0;
for(i=0;i<5;i++)
{
ADCSRA|=BIT(ADIF);
while(!(ADCSRA&BIT(ADIF)));
cord=ADC;
sum+=cord;
max=(max>cord)?max:cord;
min=(min<cord)?min:cord;
}
return (sum-max-min)/3;
}void direc_ctrl(uchar x,uchar y)
{
if(y)
{
if(x==0)OCR0=mid+3;
if(x==4)OCR0=mid-3;
if(x==2) OCR0=mid;
}
else OCR0=mid+x-2;
}void menmber_path(void)
{
uchar j;
uint i;
uint max_head[3]={0,0,0},min_head[3]={1023,1023,1023},max_back[3]={0,0,0},min_back[3]={1023,1023,1023};
for(i=4000;i;i--)
{
start_head_sensor();
for(j=0;j<3;j++)
{
max_head[j]=(max_head[j]>sensor_head[j])?max_head[j]:sensor_head[j];
min_head[j]= (min_head[j]<sensor_head[j])?min_head[j]:sensor_head[j];
}
start_back_sensor();
for(j=0;j<3;j++)
{
max_back[j]=(max_back[j]>sensor_back[j])?max_back[j]:sensor_back[j];
min_back[j]= (min_back[j]<sensor_back[j])?min_back[j]:sensor_back[j];
}
}
for(j=0;j<3;j++)
{
sensor_compare_head[j]=(max_head[j]+min_head[j])/2;
sensor_compare_back[j]=(max_back[j]+min_back[j])/2;
}
}
uchar head_sensor_all(void)
{
start_head_sensor();
if( compare(sensor_head[0], sensor_compare_head[0]) && compare(sensor_head[1], sensor_compare_head[1]) && compare(sensor_head[2], sensor_compare_head[2]))
return 1;
else
return 0;
}uchar back_sensor_all(void)
{
start_back_sensor();
if( compare(sensor_back[0], sensor_compare_back[0]-30) && compare(sensor_back[1], sensor_compare_back[1]-30) && compare(sensor_back[2], sensor_compare_back[2]-30))
return 1;
else
return 0;
}
void search_path_ahead(uchar speed)
{
motor_autorun(ahead,speed);
while(1)
{
if(head_sensor_all())
{
motor_stop();
return;
}
else
{
direc_ctrl(offset,1);
}
}
}
void search_path_backward(uchar speed)
{
motor_autorun(0,speed);
while(1)
{
if(back_sensor_all())
{
motor_stop();
return;
}
else
direc_ctrl(offset,0);
}
}
B. 51单片机智能小车制作,求通俗易懂的讲解
系统的单片机程序:
#include"reg52.h"
#definedet_Dist2.55//
单个脉冲对应的小车行走距离,其值为车轮周长
/4#defineRD9//
小车对角轴长度。专
#definePI3.1415926
#defineANG_9090
#defineANG_90_T102
#defineANG_180189/
全局变量定属义区。
/sbitP10=P1^0;//
控制继电器的开闭sbitP11=P1^1;//
控制金属接近开关。
(2)寻迹小车程序扩展阅读:
控制器部分:接收传感器部分传递过来的信号,并根据事前写入的决策系统(软件程序),来决定机器人对外部信号的反应,将控制信号发给执行器部分。好比人的大脑。
执行器部分:驱动机器人做出各种行为,包括发出各种信号(点亮发光二极管、发出声音)的部分,并且可以根据控制器部分的信号调整自己的状态。
对机器人小车来说,最基本的就是轮子。这部分就好比人的四肢一样。 传感器部分:机器人用来读取各种外部信号的传感器,以及控制机器人行动的各种开关。好比人的眼睛、耳朵等感觉器官。
C. 50分悬赏循迹小车完整程序,
智能小车程序
#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=50; unsigned 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=0;j<time;j++)
{
for(i=0;i<60;i++)
{;}
}
}
/*-----------------------------------------------*/
/*-------------------显示控制模块----------------*/
/*-----------------------------------------------*/
/*数码管显示,显示铁片的数目(设接在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=0;i<40;i++)
{
P2=P2&249;
delay(2);
P2=((P2&240)|15);
delay(2);
}
P2=P2&249;
delay(100);
P2=((P2&240)|15); //停车
IornColor(); //判断铁片黑白,设置bkAim
for(i=0;i<95;i++)
{
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;
}