智能循迹小车+蓝牙遥控

寻迹小车+蓝牙遥控

此程序主要应用的是51中的定时器中断和串口中断
定时器中断主要是让小车进行循迹;
串口中断主要是为了实现蓝牙遥控;

其中m0和m1分别代表的是白线和黑线,也就是小车的红外接收管对黑线的判断;

然后zkb1和zkb2都代表的占空比,zkb1代表的是右轮的占空比,zkb2代表的是左轮的占空比;

IN1,IN2是控制右轮的,IN3,IN4是控制左轮的;

其中correct_left(),correct_right()都分代表的是向左或向右校正;
还有left(),right(),turn_right(),turn_left(),都是英文名来表示的左,右,向右转,向左转
这些都是子函数;

left1,left2,分别代表的是小车左边的两个红外接收管;
right1,right2,分别代表的是小车右边的两个红外接收管;
#include “reg51.h”
#include “intrins.h”

#define m0 0
#define m1 1
typedef unsigned int u16;
typedef unsigned char u8;
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^3;
sbit IN4=P1^4;
sbit ENA=P1^2;
sbit ENB=P1^5;

sbit left1=P0^0;
sbit left2=P0^1;
sbit right1=P0^2;
sbit right2=P0^3;

unsigned char zkb1=0;
unsigned char zkb2=0;
unsigned char t=0; //t代表的是周期
void line_left();
void zhidon();
void line_right();
void right();
void left();
void back();
void line_straight()reentrant;

void delay(long int Delay_time) //延时函数
{
unsigned int m=Delay_time;
while(m–);

}

unsigned char receiveData=‘0’; //蓝牙从手机中接收到的字符‘0’
//且让receiveData初始值为‘0’是为了让小车在没有手机进行蓝牙控制时
//小车进行的循迹模式

void init() //定时器中断
{
TMOD|=0x01; //选定定时/计数器0的工作的方式
TH0=(65536-100)/256;
TR0=(65538-100)%256;
EA=1; //打开总中断;
ET0=1; //打开中断服务程序
TR0=1; //打开计数器
ENA=1;
ENB=1;

}

void correct_left() //向左校正
{
zkb1=12;
zkb2=6;
IN1=0;
IN2=1;
IN3=0;
IN4=1;

}

void correct_right() //向右校正
{
zkb1=6;
zkb2=10;
IN1=1;
IN2=0;
IN3=1;
IN4=0;

}

void turn_left() //向左转
{
zkb1=10;
zkb2=16;
IN1=0;
IN2=1;
IN3=0;
IN4=1;

}

void turn_right() //向右转
{
zkb1=15;
zkb2=10;
IN1=1;
IN2=0;
IN3=1;
IN4=0;

}

void straight() //直行
{
zkb1=5;
zkb2=6;
IN1=0;
IN2=1;
IN3=1;
IN4=0;

}

void line_right() //右侧有黑线时
{
zkb1=10;
zkb2=15;
IN1=1;
IN2=0;
IN3=1;
IN4=0;

	}

void go_straight() //直行
{
zkb1=10;
zkb2=7;
IN1=0;
IN2=1;
IN3=1;
IN4=0;
}
void line_left() //左侧有黑线时
{
zkb1=15;
zkb2=10;
IN1=0;
IN2=1;
IN3=0;
IN4=1;

}	

void back() //后退
{
zkb1=7;
zkb2=10;
IN1=1;
IN2=0;
IN3=0;
IN4=1;

}

void zhidon() //制动
{
zkb1=10;
zkb2=10;
IN1=1;
IN2=1;
IN3=1;
IN4=1;
}
void right() //向右
{
zkb1=7;
zkb2=10;
IN1=0;
IN2=1;
IN3=1;
IN4=0;

}

void left() //向左
{
zkb1=10;
zkb2=7;
IN1=0;
IN2=1;
IN3=1;
IN4=0;

}

void timer0() interrupt 1
{
TH0=(65536-100)/256;
TR0=(65538-100)%256;
if(t<zkb1)
{
ENA=1;

	}
	else
	{
		ENA=0;
		
	}
 if(t<zkb2)
	{
		ENB=1;
		
	}
	else 
	{
		ENB=0;
	}
	++t;
	if(t>=50)   //t的周期是50
	{
		t=0;
		ENA=1;
		ENB=1;
	}
}

void initialize() //波特率 4800
{
SCON=0x50; //串口控制工作寄存器 SM0=0 SM1=1 REN=1 方式1

TMOD=0x20;   //定时/计数器的工作方式   八位自动重装 方式2
TH1=0XF3;    //定时器初始值
TL1=0xF3;    //定时器初始值
TR1=1;			 //T1运行控制位
ES=1;    //串口中断打开
EA=1;    //总中断打开
	
PCON=0X80;   //波特率倍增    SMOD

}

void detect_infrared() //循迹函数(判断黑线)
{
if((right2 ==m0 )&&(right1 == m0)&&(left1 == m1)&&(left2 == m0))
{
turn_left();
}
else if((right2 ==m0 )&&(right1 == m0)&&(left1 == m0)&&(left2 == m1))
{
correct_left();
}
else if((right2 ==m0 )&&(right1 == m1)&&(left1 == m0)&&(left2 == m0))
{

		turn_right();
		
	}
	else if((right2 ==m1 )&&(right1 == m0)&&(left1 == m0)&&(left2 == m0))
	{
		correct_right();
	}
	else if((right2 ==m0 )&&(right1 == m0)&&(left1 == m0)&&(left2 == m0))
	{
		straight();
	}
	else if((right2 ==m1 )&&(right1 == m1)&&(left1 == m0)&&(left2 == m0))
	{
		
		line_right();
		delay(56000);}
	else if((right2 ==m0 )&&(right1 == m0)&&(left1 == m1)&&(left2 == m1))
	{
		line_left();
		delay(56000);
	}
else
	{
		straight();
	}
}

void main() //主函数
{
initialize(); //串口初始
init();
while(1)
{
if(receiveData==‘0’) //若接收到的字符是‘0’则小车进行自主循迹
{detect_infrared();
}

	else   //否则进行以下指令
		{
	
		if(receiveData=='1')
		{go_straight();
		}
	else if(receiveData=='2')
	{turn_right();
	}
	else if(receiveData=='3')
	{turn_left();
	}
	else if(receiveData=='4')
	{
		right();
	}
	else if(receiveData=='5')
	{
		left();
	}
	else if(receiveData=='6')
	{
		line_right();
	}
	else if(receiveData=='7')
	{
		line_left();
	}
	else if(receiveData=='8')
	{
		zhidon();
	}
	else if(receiveData=='9')
	{
		back();
	}
}
}

}

void usart() interrupt 4
{
receiveData=SBUF;
RI=0;
SBUF=receiveData;
while(!TI);
TI=0;

}

  • 15
    点赞
  • 70
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值