为何变?
今年智能车竞赛中的信标组的导引信号发生了改变,由原来的光,变成了声(还有射频信号),除了传承智能车竞赛赛题永远在变化的传统,还有阻断…(此处省略三千字)。
传统的信标组发送的引导信标主要通过红色可见光、红外光做引导。它们的规格可以参见文档“全国大学生智能车竞赛信标组规格说明”。
传统的信标灯内部结构
在新版的信标比赛中,对于信标的改造主要包括两个方面:
- 去掉原有的红色、红外的导航信号,将内部的的发光盘拿掉。同时可以省去为了视觉识别的灯罩,以减少在比赛过程中被高速行驶的车模撞击损毁的几率。
- 增加两种导航信号:(1)声音信号;(2)射频信号;
关于声音定位的相关实验博文可以参见:
(1)根据声音信号测量距离
(2)直线轨道上声音延迟信号分析
(3)如果提高声音测距的分辨率?
(4)影响声音定位的几个因素
(5)声音定位的距离误差到底有多高?
(6)声音定位硬件电路
(7)滑轨声源定向的理论模型与参数估计
(8)AMP328音频放大器
(9)室外声音信标可行性分析
(10)声音大小对于测距数值的影响
(11)基于STM32F103RE ADDA板制作
(12)声音测距
(13)关于声音信标的提问
关于射频信号的发送和接收相关实验博文可以参见:
(1)QN8027性能调试
(2)信标的调频发送
(3)调频立体声
(4)小型化RDA5807调频收音模块实验板
(5)单片调频收音机
(6)使用AD9833谐波发送调频广播
关于扬声器驱动电路相关博文:
(1)音频功放L2726
(2)AMP328音频放大器
下面就介绍一下如何将传统信标中的发光LED板修改成新版的信标电路。
信标灯内部的控制板和灯盘
如何变?
1. 原有信标的接口
原有信标的发光灯板与底座控制器之间是通过两个接口相同的双排8PIN插座相连接。两个插座功能是重复的,主要是为了保证发光LED灯板与控制板之间的插接牢靠,同时满足发光LED灯大电流的需要。
接口的原理图、PCB版图如下图所示:
灯盘与控制板之间的接口
接口具有四种信号:
序号 | 管脚 | 功能 | 备注 |
---|---|---|---|
1 | 1,2 | 工作电源 | 实际工作电源可能为+12V |
2 | 3,4 | 地 | |
3 | 5,6 | 红色LED驱动 | |
4 | 7,8 | IRLED驱动 |
新的信标接口板可以通过接口上的工作电源和地线获得工作电源。通过LED驱动信号可以得到开始和停止工作的状态。
在红色LED驱动信号实际上是驱动LED功率MOS的漏极。如果使用R=10kΩ上拉电阻到单片机的工作电源,在信标点亮的时候,可以测量得到10Hz的方波信号。在红外LED的接口信号上可以得到带有40kHz调制的脉冲信号。具体波形参加下面示波器测量结果。
接口信号:在闪烁的时候的红色LED接口信号
信标灯工作时IRLED接口信号
在制作新的信标信号产生板的时候,使用红色LED(也就是接口5,6中的信号)相对比较简单。
2. 声音信号发送板电路框架
根据声音信标的功能以及与主控板的接口约束,定义声音信号发送电路板的功能框图如下图所示:
框图包括有五个部分:
- 核心的单片机板:主要完成Chirp信号的产生,判断主控电路版的红色LED的方波信号来确定信号的发送与接收。通过I2C总线控制调频信号的工作频率,工作状态。通过DA控制发送的Chirp声音信号。
- 调频信号发送模块:发送调频广播信号。频率设定为两个:85MHz,或者110MHz。内部具有调频信号产生电路和射频放大电路。实验所用的芯片为:QN8027。
- 音频功放:将由单片机产生的音频信号放大,驱动信标上的扬声器,产生声音。实验所用的信号为L2726。
- 单片机工作电源:将控制板接口电路提供的工作电源转换成单片机和调频发送板的工作电压信号。
- 控制板的接口:主要是完成电源、信号的连接以及信号板的插接固定。
声音信标电路框架
实验电路设计
1. MCU电路功能设计
(1)电路设计:
硬件设计所在目录:
d:\zhuoqing\AltiumDesinger\SmartCar\2020\BeaconSound
由于需要产生Chirp音频信号,所以选择一款带有DA输出的单片机。实验电路的单片机采用STM32F051K8。
为了便于实验,电路板的电源和接口采用100mil接口的插针对外引出,便于插接在面包板上与其它模块连接实验。
MCU电路原理图设计
(2)电路板制作
通过快速制版,完成实验板的制作。
F051K8QFN封装
由于STM32F051K8的封装比较特别,焊接使用热风枪来完成。
焊接表贴元器件
焊接完之后的实验电路。
焊接完毕之后的电路板
(3)电路板的初步实验
将电路板安置在小型实验面包板上,通过编程对MCU进行初步功能测试。
软件开发所在的目录:
D:\zhuoqing\window\ARM\IAR\STM32\Application\Test\2020\SmartCar\ChirpBeacon051k\Src\main.c
通电后准备实验的电路板
单片机输出的主时钟信号(MCO)用于驱动调频信号芯片QN8027,下面是测试该信号的波形。
MOSC 的波形
2. FM发射模块
FM发射模块是基于之前的QN8027的调频发射模块。相关的前期工作参见:
-
QN8027性能调试
-
信标的调频发送
修改的方面:
- 将原来的时钟晶体去掉,从MCU板的MOSC引入
- . 左右两个声道来自于同一个外部引脚。
原理图和电路板如下图所示:
QN8027修改后的原理图和电路版图
快速制版后的实验电路板。
QN8027快速制版的实验电路板
焊接完成后的电路板。
焊接之后的实验电路板
3. 单片机与调频模块联合测试
(1)连接实验模块:
下面是将单片机板与FM发送模块在面板上安装调试。
控制板和FM发射板
(2)设置FM发射频率
通过软件改变调频信号发送频率。为了避免实际比赛时,FM的频率与当地的调频广播重叠,实际发送的频率选择85MHz,或者110MHz。
FM发送频率改变
(3)发送Chirp信号:
Chirp信号的数据存储在内存2048的RAM中,通过单片机DA转换输出,转换的频率为10kHz。
Chirp信号的数据初始化子程序为:
//------------------------------------------------------------------------------
void InitDACBuffer(float fStartF, float fEndF) {float fAngle = 0;float fFrequency;float fDeltaT = 1.0 / DAC_OUTPUT_FREQUENCY;int i;for(i = 0; i < DAC_BUFFER; i ++) {g_nDACBuffer[i] = (unsigned short)((sin(fAngle * 2 * 3.1415926) + 1.0) / 2 * 0x4ff)+0x100;fFrequency = (fEndF - fStartF) * (i + 1) / DAC_BUFFER + fStartF;fAngle += fFrequency * fDeltaT;}
}
其中的参数:
fStartF = 250;
fEndF = 2000;
DAC_BUFFER=2048;
DAC_OUTPUT_FREQUENCY = 10000;
下面两张波形图分别实现了调频信号的发送音频信号波形以及通过调频收音机接收到的信号波形。由于Chirp信号是变频信号,所以在不同时间点,看到的声音波形频率不同。
发送和接收的波形
发送和接收的波形
4. 音频功放电路模块
这部分的电路实验请参考博文:音频功放L2726 。
控制协议
单片机通过检查控制板上红色LED的方波信号来确定是否发送调频信号以及驱动扬声器发送Chirp信号。
由于控制信号比较简单,所以可以直接在主程序的循环(循环周期1ms)中,检查LED驱动脉冲信号(10Hz)。出现高低电平变化就启动信号发送过程。如果在60ms之内没有检测到驱动脉冲变化,则关闭信号发送过程。
下面给出相关的C语言代码。其中CheckFlashInit函数在主程序初始化中进行一次。 CheckFlashInput()是在主程序循环中进行调用。
//------------------------------------------------------------------------------
void CheckFlashInit(void) {g_nCheckCount = 0;g_nCheckLastStatus = 0;if(VAL(INPUT_PIN_1))g_nCheckLastStatus = 0;g_nCheckUpdateCount = 0;g_nCheckFlashUpdateCount = 0;}//------------------------------------------------------------------------------
void CheckFlashInput(void) {if(g_nCheckCount < CHECK_FLASH_MIN)g_nCheckCount ++;if(g_nCheckCount >= CHECK_FLASH_MIN) {StopChirpSound();}if(VAL(INPUT_PIN_1)) {if(g_nCheckLastStatus == 0) {g_nCheckUpdateCount = g_nCheckCount;g_nCheckCount = 0;StartChirpSound();g_nCheckFlashUpdateCount ++;}g_nCheckLastStatus = 1;} else {if(g_nCheckLastStatus == 1) {g_nCheckUpdateCount = g_nCheckCount;g_nCheckCount = 0;g_nCheckFlashUpdateCount ++;}g_nCheckLastStatus = 0;}
}