第一章前言
本系统是基于PIC单片机为主控制器的声音引导系统,主要由可移动声源,信号分析处理电路,无线数据传输模块,液晶显示模块等部分组成。本设计采用PIC单片机作为核心器件,音频脉冲信号由单片机控制产生,发声移动平台用PMMA(Acrylic)制作,平台的移动由直流减速电机完成,用ASSP芯片MMC-1和L298来实现电机的控制,用语音接收电路采集信号,并对信号进行处理后通过无线数据传输,实现可移动声源的智能控制。同时应用数码管显示平均速度。
第二章方案设计与论证
总体方案架构:
对于声源的定位有多种办法,比如测量接收端的幅值,声音测距,测量两个接收点的时间差等。我们首先选用的即时测量幅值的方案。但在实际测量过程中发现此方案不仅受环境影响极大,而且在声音距离大于50厘米后经过尽可能的放大后变化仍然达不到单片机最小采样的精度5mV(10位精度ad),因此放弃了此方案。使用声音测距的方案在经过实际测试后发现由于声波存在相位的问题,对定位精度影响很大,返回的数据亦呈现出一个正弦变化的函数关系,同时,在声源行进过程中的影响也是很大,所以也放弃了此方案。最终我们采用了计算两点时间差值的方法,在考虑相位的情况下,取每次高电平的中点作为有效数据点。声源产生的信号如下:
经不断测试,在脉冲信号阶段最佳的频率为4kHz,接收的信号最稳定,抗干扰最强。
一个周期为50ms,在前25ms内产生脉冲信号,在后25ms持续低电平。如果三个接收点接收低电平的持续时间均超过10ms,则可视为一个新周期的开始。
可移动声源的最大速度为16cm/s,则每一个处理周期为50ms,此段时间之前声源移动的最大距离 = 16cm/s×0.05s = 0.8cm<1cm,可见此精度足以满足误差为1cm的系统需求。
举例,三个声源某一时刻可能接收到的声音信号,经比较输出后波形如下:
因此只要检测首次出现高电平的时间差dT1和dT2即可判断声源是否到达OX或者OY轴。
2.1主控芯片的选择
方案一
采用51系列单片机进行控制。此方案的优点是成本很低,为保证为系统设计的总体构架对时间要求很高,需要不断的计算出高电平的中间值,为保证系统能按需求进行正常工作,单片机的处理速度必须考虑的一个问题。虽然51系列单片机支持最高晶振频率为24MHz,但此时稳定性会相应下降,此外51系列单片机IO资源均较少,对其他功能的扩展限制很大。此外,本方案还需同时处理无线数据发送接收,产生声音信号,系统计时,与MMC-1芯片通信,pid电机掉接等任务,限于51系列单片机处理速度因此放弃了此方案。
方案二
采用PIC系列单片机进行控制。此方案优点是PIC是RISC结构内核,而且PIC单片机是四分频的,而51系列单片机是12分频的,所以指令速度比51单片机快得多,因此在同样晶振下有着更快的处理运算速度,因此非常适合处理采集的声音测量值。虽然PIC单片机比51系列单片机成本高一些,但就整体而言却有着更高的性价比。因此最终采用PIC单片机。
2.2声源系统方案
方案一
用蜂鸣器作为发声器件,用高耐压、大电流达林顿管ULN2003进行功率放大 ,此电路结构简单,易于控制,价格低廉,功耗低。但在实际测试中发现由于发出声音相对较弱,因此外界极容易造成干扰,处理数据时精度达不到所需要求,因此放弃使用蜂鸣器。
方案二
用扬声器作为发声器件,用TDA2822进行功率放大,此电路能够得到比蜂鸣器更强的音频信号,虽然功率有些大,但能产生足够的振幅,干扰相对较小,因此选择此方案。
2.3移动平台系统方案
方案一
购买普通玩具小车改装成移动平台,玩具小车一般由两个直流电机组成,前轮用一个控制方向,后轮用一个控制速度
方案二
购买有机玻璃等材料自己制作移动平台、采用两个步进电机分别控制左右两个轮子,用一个万向轮作支撑。
方案三
仍购买有机玻璃等材料自己制作移动平台采用两个直流减速电机分别控制左右两个轮子,用一个万向轮作支撑。
以上三种方案中,方案一是常见的平台移动控制方法,但是由于玩具小车转向的角度很难控制,而且电机容易卡死,可能造成电机烧毁,加上题目中要求可移动生源转直角弯,此方案很难做到。方案二虽然采用步进电机左右轮分开控制的策略,而且能够精确控制转速和计算路程,但一般小型步进电机产生的力矩较小,难以达到要求。方案三中只要直流减速电机安装较好,其控制就能达到较高的精度,对于负载较多的移动平台而言,此方案最为实用。
2.4声音接收方案
方案一
购买集成好的拾音器模块,这种方法能有效采集到音频信号,但是集成模块价格较为昂贵,性价比不高,有大材小用之嫌,因此不用。
方案二
用驻极体话筒和晶体管制作简单的音频采集放大电路。此方法成本低,功耗小,外围器件少,电路简单,而音质也较佳为。经综合考虑,我们决定采用此方案。
2.5显示方案
方案一
LCD12864进行背光显示,此方案能够实时显示能容丰富、清晰,显示信息容量大,但是此液晶功耗大(开启背光时12864接近500mA),而且需要安装面积大,占用I/O资源较多,价格较为昂贵,因此不采用。
方案二
用数码管进行显示,控制简单,亮度大,价格低廉,在较强的光线下也能显示清晰的数据,所以选择数码管进行显示。
2.6 无线方案
采用NRF905为主控芯片的无线通信模块,通信频率高,传输速度较快,能够胜任本系统要求的任务。
第三章硬件电路设计
3.1音频信号发生电路的设计
我们采用用TDA2822对音频信号进行功率放大,该芯片性价比很高。扬声器的频率直接由单片机给出,单片机输出的脉冲信号通过扬声器反映出来。具体电路图见附图1。
3.2电机控制电路设计
本题必须采用组委会提供的电机控制ASSP芯片(型号MMC-1)实现可移动声源的运动。MMC-1为多通道两相四线式步进电机/直流电机控制芯片,基于十六位通用的MCU固化专用程序实现。通过USAT或SPI串行接口,为主控CPU扩展专用电机控制功能。在此次比赛中由于硬件资源有限,而整个系统对主控CPU的性能有要求很高,如电机驱动与音频信号都会用到PWM,51单片机没有PWM,而PIC单片机也只有两路PWM,为了提高性价比,这款芯片很有必要!整个电机驱动电路请见附图2、附图3、附图4、附图5。
3.3音频信号接收电路
为了降低小车的功耗,减少作品成本,以三极管为基本放大环节的话筒功放电路,外围元件少,制作简单,音质却出乎意料的好。其主要特点是效率高、耗电省,静态工作电流典型值只有6mA左右,具体电路如图所示。该电路输出端的信号不能直接给单片机,由于环境中不确定的噪声很多,所以必须滤波,我们选取带通滤波,其中中心频率为:F=1/2<<<<<<<<<<<<<<<<<<<<<<<<<π R C
由于环境中的干扰的频率大多分布在2KHZ以下,于是便要求音频信号频率要在它之上,在测试中发现并不是频率越高越好,随着频率升高,音频信号的响度也随着降低,响度太低也会使信号的检测变困难,经过测试发现声音引导系统最佳频率是4KHZ。由于采用相位比较算法,单片机得到的理想值是一个数字信号,通过电压比较器将输出的信号通过电压比较,输出方波信号。这样可以使得干扰基本上消失,而且控制也相对比较简单,更值得一提的是,通过比较器的可调比较电压,可以在不同的环境下通过调节比较器的比较电压,达到抗干扰的目的。具体的滤波比较电路请见附图六、附图七。
3.4测速电路设计
本声源移动平台采用双电机差速控制,由于是差速控制,两电机转速不一定一样,所以要通过测定两个电机的转速来确定,最简单的算法是取平均值。性价比最高的一种方法是通过光电管配合自制的光电码盘来实现。光电管通过电压比较器使得当光电管处于光电码盘黑白上时输出高低电平信号,再通过单片机计数、运算的出速度值,还可以算出路程。
V=相邻码盘距离/通过相邻码盘所用的时间
S=V*T
第四章软件设计
4.1 总体构架分析:
所有数据采集、处理以及计算均在声音接收部分完成,在处理完成后通过无线模块发送给声源,声源根据接收到的命令采取不同的控制策略。此外声源部分和声音接收部分均采用AvrX操作系统,同时进行多个操作,保证了系统系统运行的实时性。
声源部分:
Task1: 产生系统所需的声音信号。
Task2:电机速度检测,与MMC-1电机驱动芯片进行通信,构成电机速度的闭环控制。
Task3:记录系统运行时间,并时时显示速度。
Task4:无线数据通信,时时接收控制指令。
声音接收部分:
Task1:信号的接受和处理
Task2:对接受的信号进行计算,产生不同的控制命令。
Task3:对更新的控制命令通过无线模块发送到移动声源。
4.2 PID电机调速的设计:
因为实现本题必须实用精确控制,因此必须采用闭环的控制系统,对双电机进行精确控制以达到精度控制要求。而此系统中同时要求电机进行前进和后退,因此需采用位置式PID控制。
经过不断的测试,比例,积分,微分常数目前调出的最佳参数如下:
Kp: 1.6 Ki: 2.1 Kd:1.4 具体部分代码参见附录。
第五章调试及结果分析
5.1音频信号采集模块调试
5.2路程测量测试
调试仪器:20MHz双踪示波器、信号发生器、数字万用表、秒表、米尺等
5.3结果分析
经测试,在外界干扰不是太强的情况下,可移动声源能够通过接收器方传回的数据精确地定位,精度在1—3cm.
附录1
附图1、音频发生电路
附图2、L298驱动电路
附图三、做好的L298驱动电路PCB
附图四、MMC-1封装图
附图五、大赛提供MMC-1芯片的转接板
附图六、选频滤波电路
附图七、比较输出电路
附录2
MCU1程序流程图
MCU2程序流程图
PID调试部分代码:
// define difference : the difference between the latest data and the previous data
// define U0 : the PWM to send to the moto
int main (void)
{
······ // Omitted the previous code
int P = 0 , D = 0 ;
tcount++ ;
CarState.E0 = BitNum ;
if ( CarState.E0 == CarState.E1 ) if ( CarState.E0 == 0 ) FlagD = 0 ;
else if ( CarState.E0 < CarState.E1 ) FlagD = -1 ;
else if ( CarState.E0 > CarState.E1 ) FlagD = 1 ;
P = CarState.E0 * Kp ;
D = Kd * KdS * ( CarState.E0 + 3*CarState.E1 - 3*CarState.E2 - CarState.E3 ) ;
if ( D < - 30 * KdS ) D = -30*KdS ;
else if ( D > 30*KdS ) D = 30*KdS ;
if ( D != 0 ) D_old = D ;
if ( D_old < -10 ) D_old++ ;
else if ( D_old > 10 ) D_old-- ;
if ( (CarState.E0 > -3)&&(CarState.E0 < 3) ) S = 0 ;
else if ( ( FlagD == -1) && ( CarState.E0 <= -1 ) )
if ( S > ( BitNum * BitNum * 20 * KsS ) ) S-- ;
else if ( ( FlagD == -1) && ( CarState.E0 >= -1 ) ) S = 0 ; //
else if ( ( FlagD == 1 ) && ( CarState.E0 <= 1 ) ) S = 0 ; //
else if ( ( FlagD == 1 ) && ( CarState.E0 >= 1 ) )
if ( S < ( BitNum * BitNum * 20 * KsS) ) S++ ; //
u8_pwm_a = U0 + P + ( D_old / KdS )+ ( S / KsS ); // ;
······ // Omitted the following code
}