智能小车声音引导系统设计与制作报告.docx
《智能小车声音引导系统设计与制作报告.docx》由会员分享,可在线阅读,更多相关《智能小车声音引导系统设计与制作报告.docx(30页珍藏版)》请在冰点文库上搜索。
智能小车声音引导系统设计与制作报告
声音引导系统设计与制作报告
一、方案选择与论证
1、整体方案选择
方案一:
本方案采用音频收发的方式,由核心控制模块80C51F020发出一个特定频率的音频脉冲信号,前置音频接收模块接收并识别这个脉冲信号。
将其转变成TTL电平。
采用FPGA对接受的信号进行处理,经过无线收发模块通讯,将小车的定点位置传至核心模块单片机处理并控制小车在特定的范围内运动。
方案二:
本方案采用语音收发的方式来控制小车的运动,由核心控制模块控制语音芯片,发送特定的语音信号,再由语音识别模块对语音进行采集和数字化。
采用FPGA对接受的信号进行处理,经过无线收发模块通讯,将小车的定点位置传至核心模块单片机处理并控制小车在特定的范围内运动。
方案比较:
方案一的核心控制算法由80C51F020完成。
单片机的算法控制比较简单,容易实现。
而FPGA的算法较复杂,但其对边沿信号反应时间快,所以利用FPGA处理接受音频信号。
方案二用到语音收发的方式,由于识别语音的收发模块实现困难,所以本设计采用方案一。
2、控制理论计算方案选择
方案一:
可移动声源在运动前发出音频信号,根据三个接收器接收音频的时间不同,可以算出声源到接收器间的距离和声源到中线OX的距离,即可移动声源起始位置定位。
然后控制小车做垂直中线OX运动,到达中线OX。
再第二次发音频信号,定位此时可移动声源的位置,得出与中心点W的距离,使小车转动90度,运动至W点。
方案二:
可移动声源发出音频信号后,得到定位。
根据弧度的计算,控制小车做弧线运动。
到达至中线OX。
可移动声源第二次发出音频信号,得到与中心点W的距离,控制小车到达W点。
方案比较:
方案一直接利用走垂直线的方法,算法简单。
方案二用到弧长和角度的算法,控制困难,且调试繁琐。
为了满足方案的要求,所以本设计选择方案一。
二、硬件设计与实现
硬件系统的框图如图1所示。
单片机与FPGA通过无线的方式通讯。
图1、硬件系统框图
主要模块电路如下:
1、控制器模块
实现音频的接受和无线收发功能。
FPGA模块电路如图2所示。
接收经过锁相环选频后的信号和单片机控制发送的同步无线信号,通过处理后利用无线通讯将命令发会单片机。
图2、FPGA控制模块
2、音频接收模块
该模块通过驻极体话筒采集音频信号,驻极体话筒具有结构简单、重量轻、体积小、无方向性、频率响应宽、保真度好等优点。
音频信号通过前置放大、滤波。
再将放大信号通过LM567锁相环音频译码芯片,构建选频电路,当输入信号的频率落在其内部压控振荡器中心频率时,输出端将由原来的高电平变为低电平。
锁相环内部压控振荡器中心频率(f=1/1.1RC)由5、6脚外接的电阻与电容决定。
所以在5脚接入10K的滑动变阻器调节,可确定被选定的频率。
经过多次计算与验证,前置放大电路用TL082集成运放。
当麦克风接收到6k赫兹左右的频率时,输出会有很明显的电平跳变。
电路原理如图3。
图3、音频接收模块原理图
3、电机控制模块
根据大赛要求,电机控制采用MMC-ASSP作为电机驱动的主控芯片。
采用串口通信UART模式。
该芯片提供三个通道控制电机,即可同时控制三个电机运转。
每一路直流电机需要CHnDCPWM和CHnDCDIR两个引脚,CHnDCPWM用于PWM波输出,CHnDCDIR用于指定电机转向,外接一个全桥驱动芯片控制直流电机工作。
通过调节占空比控制电机的转速。
数据的输入输出端口(TXD和RXD)与主控MCU相连。
如图4所示。
采用了H桥驱动元件L298,避免了使用分立元件带来的电路板复杂的问题,电路简洁。
且可以提供最大为4A的电流。
MMC-ASSP控制电路如图4所示,L298驱动电路如图5所示。
图4、UART模式下直流电机控制模块
图5、电机驱动模块原理图
4、红外对管测速模块
用黑线将小车车轮圆盘平均15等分,采用光电传感器RCRT5000检测黑线,在一定时间内计数检测到的黑线条数,计算出车速,由80C51F020控制液晶显示。
红外对管模块如图6。
图6、红外对管测速原理图
5、显示模块
显示模块主要由80C51F020的开发板作为控制核心,另外显示电路作为外围电路。
主要功能:
红外对管采集车轮转动的数据,由单片机处理后经过1602液晶显示小车的车速。
三、软件系统设计
1、80C51F020和FPGA总体程序流程
图7、程序流程图
2、MMC-1ASSP电机控制程序流程
电机驱动需要配置相对应的寄存器,占空比给定寄存器(chnDuty)在用于直流电机驱动时需要配置,主要是通过设定该寄存器选择不同占空比,进而调节电机转速。
另外,在配置完chnDuty寄存器后,还要设置工作模式寄存器(chnMode)选择驱动电机的类型。
本方案选择的是直流电机。
具体程序流程如图8所示。
图8、MMC-1电机控制程序流程
四、硬件与软件调试
本方案所用到的硬件电路不多,主要是音频接收模块、电机驱动模块和核心板电路。
有关的硬件模块调试主要就是音频的接收。
该操作比较简单。
难度较大的是软件调试,本方案软件控制是核心。
通过对音频的控制和无线接受模块控制小车在特定要求下运动。
主要用到核心控制器80C51F020和FPGA进行协同控制。
调试在控制时序方面较困难,对音频的采集处理有难度。
五、性能与指标测试
1、测试仪器
数字示波器 DS1102C 功率函数信号发生器 YB1605P
直流稳压电源 YB1732A2A 秒表、2米卷尺
2、测试分析
本次设计用到声音的引导,会受到较大的干扰,前置的音频接受与转换的硬件也存在一定的误差,导致FPGA测得的时序浮度比较大,所测得的数据稳定性不高。
不过对小车的控制比较到位。
六、总结
经过4天3夜的努力,我们终于完成了本题的制作,在参数和功能上尽量完成要求。
在理论设计计算方面,我们充分运用了我们所掌握的知识,力争做到更好。
在实际过程中,关于音频信号的处理和相关时序处理遇到的问题较大。
这一方面成为本设计的关键所在。
说明了我们还是缺少相关知识技术和实际的工程经验。
通过此次大赛,我们队的每个成员都获益非浅。
参考文献
[1]综合电子设计与实践.田良.南京:
东南大学出版社,2002.3.
[2]FPGA设计与应用.刘皖,何道君,谭明.北京:
清华大学出版社,2006.
[3]C8051F单片机原理及应用.鲍可进.北京:
中国电力出版社,2006.
[4]FPGA原理与实践.张庆玲,杨勇.北京:
北京航空航天大学出版社,2006.
附 录
附录1. 单片机源程序
//020串口UART0发送程序模块
#include
unsignedintcount,count1,count2;
unsignedcharlcd[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
unsignedintcnt; //用于控制发6KHz的方波的个数
unsignedinta,b,c;
bitflag_sound; //标志位,用于控制发送方波的个数
bitflag,flag1,flag2;
bitkey_flag;
sbitkey1=P0^5;
sbitkey2=P0^6;
sbitsound=P0^7;
sbitRS=P2^5;//液晶
sbitRW=P2^6;
sbitEN=P2^7;
sbitP30=P3^0;//EN_1,EN_2
sbitP31=P3^1;
sbitP33=P2^3;
voidDelay(unsignedinti);
voidPORT_Init(void);
voidSYSCLK_Init(void);
voidUART0_INT();
voidUART1_INT();
voidE_int(void);
voidWait_Busy(void);
voidWrite_Data(unsignedchardata_in);
voidWrite_Code(unsignedcharcode_in);
voidLcd_Init(void);
voidstright(void);
voidzhuanwan_left(void);
voidzhuanwan_right(void);
voidstop_8s(void);
voiddelay_long(void);
voidstop();
voidkey_puanduan();
voidTimer_INT();
voidDelay(unsignedinti)//延时子程序
{
while(i--);
}
voidTimer_INT()interrupt1using1
{
if(cnt==b) //发10个周期的6KHz的方波
{
TL0=0x69; //6KHz的频率产生的定时器的值
TH0=0xff;
flag_sound=1;
TR0=0;
cnt=0;
}
else
{
TL0=0x69;
TH0=0xff;
sound=~sound;
cnt++;
flag_sound=0;
TR0=1;
}
}
void PORT_Init(void) /**********端口的初始化***********/
{
XBR0=0x04; //使UART0的TXD和RXD分别连接到P0.0,P0.1
XBR1=0x04;
XBR2=0x44;
P0MDOUT=0x60; /*******P口输出方式的设置*********/
P1MDOUT=0X00;
P2MDOUT&=0x00;
P3MDOUT&=0x00;
}
voidSYSCLK_Init(void) /*******系统时钟初始化**********/
{
unsigned intQ=0; /*******外部时钟的配置*********/
OSCXCN=0x67;
for(Q=0;Q<255;Q++);
while((OSCXCN&0xe7)!
=0xe7);
OSCICN=0x88;
}
voidwait_busy(void)
{
P1|=0x80;
RS=0;
RW=1;
EN=1;
Delay(10);
while(P1&0x80);
EN=0;
}
voidWrite_Data(unsignedchardata_in) /*****发送数据函数*******/
{
Wait_Busy();
RS=1;
RW=0;
EN=1;
P1=data_in;
Delay(100);
EN=0;
}
voidWrite_Code(unsignedcharcode_in) /*****发送指令函数*******/
{
Wait_Busy();
RS=0;
RW=0;
EN=1;
P1=code_in;
Delay(100);
EN=0;
}
voidLCD_Init(void) /********液晶初始化***********/
{
Write_Code(0x01);
Delay(100);
Write_Code(0x38);
Delay(100);
Write_Code(0x0c);
Delay(100);
Write_Code(0x06);
Delay(100);
}
voidT1_inter()interrupt3 /*****计时对数据进行处理*****/
{ if(count2==a)
{
TR1=0;
TL1=0xFF;
TH1=0x6f;
flag2=1;
count2=0;
}
else
{
TL1=0xff;
TH1=0x6f;
TR1=1;
flag2=0;
count2++;
}
}
voidE_int()interrupt0//外部中断函数
{
if(count1==c)
{
flag=1;
count1=0;
P30=0;
P31=0;
}
else
{
count1=count1+1;
count=count+1;
}
}
voidstright(void)//直走50cm
{
///////////////直走///////////////////////////
//***********************//通道1PWMchnfreq的配置
TB80=1; //发送0X53--5-》写命令字,3-》通道1占空比给定寄存器
SBUF0=0X53;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0Xcc--占空比(控制转速)
SBUF0=0Xf6;
while(~TI0);
TI0=0;
Delay(10000);
//***********************//通道2PWMchnfreq的配置
TB80=0;//发送0X57
SBUF0=0X57;
while(~TI0);
TI0=0;
Delay(10000);
TB80=0;//发送0XCc
SBUF0=0Xf8;
while(~TI0);
TI0=0;
Delay(10000);
//***********************//通道1,2不同步的同步模式寄存器synmode的设置
TB80=1;//发送0X5C
SBUF0=0X5C;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X00
SBUF0=0X00;
while(~TI0);
TI0=0;
Delay(10000);
//***********************//通道1chnmode的配置
TB80=1;//发送0X50
SBUF0=0X50;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0Xc0
SBUF0=0Xc0;
while(~TI0);
TI0=0;
Delay(10000);
//***********************//通道2chnmode的配置
TB80=0;//发送0X54
SBUF0=0X54;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0Xc0
SBUF0=0XC0;
while(~TI0);
TI0=0;
P30=1;P31=1;
}
voidstop_8s(void)
{
while(~flag);
flag=0;
SCON1&=0xfd;
SBUF1=0x0d; //////发送13cm/s
while(SCON1&0x02==0x00);
Write_Code(0x80);
Write_Data(0x31);
Write_Data(0x33);
Write_Data(0x63);
Write_Data(0x6d);
Write_Data(0x2f);
Write_Data(0x73);
/////////停止//////////////////////////////////////////////
a=400;
TR1=1;
flag2=0;
while(~flag2)
{
Delay(10000);
P33=~P33;
}
flag2=0;count2=0;P33=0;
}
voidzhuanwan_left(void)//////右转
{
EA=0;EX0=0;
/////////转90度//////////////////////////////////////////////
//***********************///通道1PWMchnfreq的配置
TB80=1; //发送0X53
SBUF0=0X53;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X33
SBUF0=0XB4;
//SBUF0=0Xf6;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道2PWMchnfreq的配置
TB80=0;//发送0X57
SBUF0=0X57;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X33
SBUF0=0XB4;
//SBUF0=0Xf7;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道1,2不同步的同步模式寄存器synmode的设置
TB80=1;//发送0X5C
SBUF0=0X5C;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X00
SBUF0=0X00;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道1chnmode的配置
TB80=1;//发送0X50
SBUF0=0X50;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0Xe0
SBUF0=0XC0;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道2chnmode的配置
TB80=0;//发送0X54
SBUF0=0X54;
while(~TI0);
TI0=0;
Delay(10000);
TB80=0;//发送0Xe0
SBUF0=0XE0;
while(~TI0);//发送0X80
TI0=0;
P30=1;P31=1;
}
voidstop(void)
{
/////////停止//////////////////////////////////////////////
P30=0;P31=0;
Write_Code(0x80);
Write_Data(0x20);
Write_Data(0x20);
Write_Data(0x20);
Write_Data(0x20);
Write_Data(0x20);
Write_Data(0x20);
}
voidzhuanwan_right(void)//左转
{
EA=0;EX0=0;
/////////转90度//////////////////////////////////////////////
//***********************///通道1PWMchnfreq的配置
TB80=1; //发送0X53
SBUF0=0X53;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X33
SBUF0=0XB4;
//SBUF0=0Xf6;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道2PWMchnfreq的配置
TB80=0;//发送0X57
SBUF0=0X57;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X33
SBUF0=0XB4;
//SBUF0=0Xf7;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道1,2不同步的同步模式寄存器synmode的设置
TB80=1;//发送0X5C
SBUF0=0X5C;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0X00
SBUF0=0X00;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道1chnmode的配置
TB80=1;//发送0X50
SBUF0=0X50;
while(~TI0);
TI0=0;
Delay(10000);
TB80=0;//发送0Xe0
SBUF0=0Xe0;
while(~TI0);
TI0=0;
Delay(10000);
//***********************///通道2chnmode的配置
TB80=0;//发送0X54
SBUF0=0X54;
while(~TI0);
TI0=0;
Delay(10000);
TB80=1;//发送0Xe0
SBUF0=0Xc0;
while(~TI0);//发送0X80
TI0=0;
P30=1;P31=1;
}
voidmain(void)
{
c=0;
WDTCN=0xde; /********关看门狗*********/
WDTCN=0xad;
count=0;count1=0;
cnt=0;flag_sound=0;
PORT_Init();
SYSCLK_Init();
LCD_Init();
SCON0=0xD0; //UART0工作在方式2,9位UART,可变波特率
SCON1=0x50; //UART1工作在方式1,8位UART,可变波特率
T2CON=0x30;
T4CON=0x30;
RCAP2L=0xb8; //设置波特率(定时器2作为波特率发生器)
RCAP2H=0xff;
RCAP4L=0x0b8; //设置波特率(定时器4作为波特率发生器)
RCAP4H=0xff;
EA=1;
TR2=1;
T4CON|=0x04; //开定时器4
TI0=0;
IT0=1;
EX0=1;
CKCON=0x00; /*****定时器0,1用的时钟为系统时钟的12分频*****/
TMOD=0x11; /*****定时器1用来定时,定时器0用来计被测脉冲******/
TH1=0x6f;TL1=0xff; /*****定时器1的初值*****/
ET1=1;
TR1=0;
/**********配置定时器0*************/
TL0=0x69;
TH0=0xff;
ET0=1;
EA=1;
TR0=0;
flag=0;
flag1=0;
//P33=1;
while
(1)
{
P30=0;P31=0;
//P33=1;
while(key1&&key2);
if(key1==0)
key_flag=1;
if(key2==0)
key_flag=0;
b=1000;
TR0=1;//开定时器0,6Khz方波
while(~flag_so