拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于STM32与四驻极体话筒的TDOA声源定位系统

简介这份基于STM32的声源定位装置毕业设计说明书面向电子信息、嵌入式与自动化方向的学生及工程师聚焦如何用STM32F103搭建可定位声源的软硬件系统。全文从总体方案比较入手依次覆盖555多谐振荡器、电源、AGC、有源高低通滤波、STM32F103最小系统、液晶显示与电平转换等单元电路并给出参数计算、元器件选型、ILI9320与VCA810等器件说明以及软件流程图和系统调试记录。资源包仅含1个PDF文件压缩后约4.23MB便于直接查阅与打印。已有335人学习适合作为课程设计、毕业设计或嵌入式竞赛的参考模板可借此理解声源信号采集、滤波放大、ADC采样、坐标解算和结果显示的完整链路也能为电路调试与论文撰写提供可复用框架。1. 从四个驻极体话筒到一组超定方程这套STM32声源定位装置到底在做什么多数人第一次看到声源定位会条件反射想到麦克风阵列加波束成形动辄要十几路同步采样和FPGA做互相关。这套西华大学的毕业设计走的完全是另一条路四个驻极体话筒摆在矩形四个角用一个555多谐振荡器发出定频方波当声源靶子靠测四个通道之间的到达时间差反推坐标主控只用一颗STM32F103。听起来简陋但它把被动声测的几个核心问题——信号增益随距离剧烈变化、带外噪声淹没有效频点、时差测量分辨率不足——全都摆到了台面上逼着你一个个去解。它适合两类人一是正在做嵌入式毕业设计、需要一份硬件链路完整可复现的参考二是想搞明白TDOA定位从模拟前端到解方程全链路的人。下面按信号怎么产生、怎么调理、怎么采样、怎么解算、怎么验证的顺序拆开讲。2. 声源激励与模拟前端555多谐振荡器、AGC与两级有源滤波2.1 用555定时器把方波频率钉在500Hz方案对比里提到过用STC89C51的定时器翻转IO口产生方波但那样占用一整个单片机只为发一个音性价比确实低。555接成多谐振荡器只需要两个电阻一个电容输出占空比和频率都能算得死死的。核心公式是充电时间tpH0.7(R1R2)C、放电时间tpL0.7R2C振荡频率f 1.43 / ((R1 2*R2) * C)按正文C取100nF、令R1R2R要得到500HzR 1.43 / (3 * f * C) 1.43 / (3 * 500 * 100e-9) ≈ 9533 Ω ≈ 9.5 kΩ逻辑说明555内部两个比较器分别卡在1/3 Vcc和2/3 Vcc电容在两者之间往复充放电形成弛张振荡。参数说明上R1同时影响充电支路和占空比R2只影响放电支路所以想微调频率优先动R2C的取值范围受限于漏电流100nF是稳定性比较好的甜点。实际搭电路时建议R1或R2用10k多圈可调电阻串一个固定电阻把频率调到实测490~510Hz即可不必死磕理论值。提示555的输出是方波谐波非常丰富。如果接收端滤波器通带没卡准三次谐波1500Hz会直接串进来干扰过零检测这是后面带通设计必须衔接的点。2.2 声源用无源蜂鸣器而不是扬声器方案比较里选无源蜂鸣器理由是功耗低、价格便宜、声音清晰度够。这里有个工程细节值得展开无源蜂鸣器本质是个小功率压电或电磁换能器在谐振点附近声压输出效率最高所以必须用方波驱动而不是直流。扬声器声压更大但需要较大的驱动电流555的灌电流能力有限直接推扬声器会出现波形失真反而让TDOA测量变得不可控。所以低频小功率场景下蜂鸣器是更合适的激励源。器件驱动方式典型功耗声压表现对555的负载低音扬声器模拟/方波需功率级高强但易失真需加三极管或功放无源蜂鸣器方波直接驱动低中等谐振点清晰可直接挂IO或输出端2.3 VCA810构成的AGC为什么要做不做会怎样声源离某个话筒近、离另一个远接收幅度可能差十几倍。12位ADC的参考电压固定如果最远的通道信号刚够量程的一半最近的通道早就削顶了过零点检测会严重偏移时差直接算错。所以正文在发射通路后面串了一级基于VCA810的自动增益控制把进入ADC的信号稳定在一个固定范围内。VCA810的增益由第3脚的控制电压决定是压控增益放大器增益范围用dB线性表示控制口经接插件引出就是为了方便你在调试时拿一个可调直流电压去标定。外围电路里两个电源脚各挂一颗2.2~6.8uF的大电容排低频干扰再并104的小电容做高频去耦输入端的50Ω接地电阻做阻抗匹配R10用来消除V−输入端的偏置电流。常见做法是先固定一个已知距离测出各通道原始幅度算出动态范围再反推AGC需要压多少dB然后用DAC或PWM滤波产生控制电压。这样比盲调更省时间。2.4 二阶低通与二阶高通级联出带通正文里低通截止设550Hz、高通截止设450Hz通带宽度100Hz正好把500Hz的方波基频圈在中间又滤掉工频50Hz、电源纹波和高频谐波。电路采用NE5532搭的压控电压源VCVS结构同相输入、增益通过反馈电阻设定特点是输入阻抗高、输出阻抗低、Q值可调。低通部分的电阻电容决定截止频率与品质因数fc 1 / (2*pi*sqrt(R3*R4*C3*C4)) Q sqrt(R3*R4*C3*C4) / (C4*(R3R4)) 单位增益同相结构参数说明正文取R32k、R44k、C3C4104即100nF代入可算出截止频率落在几百赫兹量级。注意这不是教科书上常见的等值设计因为要让Q略微大于0.707来获得巴特沃斯响应。高通级增益必须限制在2倍以内所以NE5532的第6、7脚直接相连单位增益跟随否则会自激。两级级联后通带内的相位一致性非常重要——相位在通带边缘剧烈变化如果你的频率刚好卡在边缘四个通道测出来的时间差会带上非线性的相位延迟这个误差很难事后用算法补。所以实际调试时建议先用信号发生器扫频把通带中心确认在500Hz附近。注意级联滤波器的实际Q值是各级Q的乘积关系不是简单相加。两级都用高Q会形成尖峰容易在500Hz附近产生振铃做TDOA时会带来额外的群延迟反而误事。3. STM32F103的采样链路ADC配置、定时器触发与相位差提取3.1 引脚与时钟的最基本配置STM32F103VET672MHz主频12位ADC这里要用至少四路ADC通道去采四角话筒。核心配置是ADC工作在扫描模式配合DMA把结果搬到内存避免CPU轮询。以下是一段可用的初始化骨架标准库风格Keil环境下// ADC1 扫描 DMA 搬运规则通道4路 void ADC_DMA_Init(void) { ADC_InitTypeDef adc; DMA_InitTypeDef dma; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // PA0~PA3 模拟输入 GPIO_InitTypeDef gpio; gpio.GPIO_Pin GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; gpio.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, gpio); dma.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; dma.DMA_MemoryBaseAddr (uint32_t)adc_buf; // uint16_t adc_buf[4] dma.DMA_DIR DMA_DIR_PeripheralSRC; dma.DMA_BufferSize 4; dma.DMA_PeripheralInc DMA_PeripheralInc_Disable; dma.DMA_MemoryInc DMA_MemoryInc_Enable; dma.DMA_Mode DMA_Mode_Circular; // 循环覆盖实时刷新 DMA_Init(DMA1_Channel1, dma); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DeInit(ADC1); adc.ADC_Mode ADC_Mode_Independent; adc.ADC_ScanConvMode ENABLE; // 扫描4个通道 adc.ADC_ContinuousConvMode ENABLE; adc.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; adc.ADC_DataAlign ADC_DataAlign_Right; adc.ADC_NbrOfChannel 4; ADC_Init(ADC1, adc); ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE); }逻辑说明ADC_ScanConvMode打开后ADC会按规则组顺序依次转换4个通道每转完一轮DMA自动把DR里的结果搬到数组对应位置CPU完全不插手。参数说明采样时间选55.5个ADC周期是因为四个话筒的信号源阻抗较高经滤波网络后采样保持电容需要更长时间充电如果直接用7.5周期会看到明显串扰。DMA_Mode_Circular保证缓冲区永远是最新的数据主循环里随时读adc_buf[0..3]就能拿到四路当前值。3.2 用定时器做精确采样时钟500Hz的方波周期是2ms要做相位差测量采样率至少要到信号频率的10倍以上也就是5kHz以上换算到采样周期要短于200us。更好的做法是用STM32的定时器定时触发ADC比如TIM2更新事件触发这样采样时间完全由硬件控制不受主循环抖动影响。// TIM2 每 50us 触发一次 ADC 转换采样率 20kHz void TIM2_Trig_ADC_Init(void) { TIM_TimeBaseInitTypeDef tim; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); tim.TIM_Prescaler 72 - 1; // 72MHz/72 1MHz计数单位1us tim.TIM_Period 50 - 1; // 每50us溢出 20kHz触发 tim.TIM_CounterMode TIM_CounterMode_Up; tim.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, tim); // 配置用更新事件作为ADC外部触发 ADC_ExternalTrigConvConfig(ADC1, ADC_ExternalTrigConv_T2_TRGO); TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); TIM_Cmd(TIM2, ENABLE); }逻辑说明预分频72把72MHz降到1MHz周期设为50即50us溢出一次溢出事件通过TRGO连到ADC的触发输入。参数说明TIM_SelectOutputTrigger这一步非常关键很多人只配置了ADC的外部触发源却忘了打开定时器的TRGO输出结果ADC一直不转换还以为是ADC坏了。采样率选20kHz是为了让过零点的位置分辨率落在50us量级对应声程误差约1.7cm——这个精度对矩形尺寸的定位足够。3.3 相位差到距离差的换算采集到四路数据后用软件找每路的过零点或者互相关计算时间差。简化实现可以测上升沿过零点的样本序号// 找某一通道的第一个上升过零点简化版过中值判断 int find_zero_cross(uint16_t *buf, int start, int end) { int mid 2048; // 12位ADC中值约2048 for (int i start; i end - 1; i) { if (buf[i] mid buf[i 1] mid) { return i; // 返回过零点样本索引 } } return -1; }逻辑说明找到四路的过零索引后两两相减再乘以采样周期就是时间差t1、t2、t3。参数说明中值用2048是假设信号已经偏置到Vcc/2如果没有抬升就要先算每路的平均值再比较。实际工程里更好的选择是互相关或相位检波过零法对噪声很敏感所以前面滤波通带一定要干净。指标典型值影响采样率20kHz决定时间分辨率误差≈1/fsADC位数12位幅度分辨率约0.8mV3.3V滤波通带450~550Hz保证500Hz基频无衰减时间差误差50us对应约17mm声程误差4. 四点TDOA解算从距离差到二元二次方程组4.1 为什么用三角形法加校正点而不是双曲线正文比较了三种坐标解算方案最终选了用三角形法求出一组解再用第三点距离差校正。双曲线法的原理是两个接收点到声源的距离差为常数轨迹是一条双曲线四个接收点两两配对可以得三组双曲线交点即声源。问题在于当声源恰好在矩形中心附近时多条双曲线几乎退化交点数值不稳定——这就是所谓盲区。三角形法则是直接构造方程。设矩形四角坐标A(0,0)、B(L,0)、C(L,W)、D(0,W)声源O(x,y)。四点到声源的距离是Da sqrt(x^2 y^2) Db sqrt((x-L)^2 y^2) Dc sqrt((x-L)^2 (y-W)^2) Dd sqrt(x^2 (y-W)^2)单片机测到的是到达时间Ta、Tb、Tc、Td两两相减乘以声速v就得到距离差。例如Db - Da v*(Tb - Ta) v*t1 Dd - Da v*(Td - Ta) v*t2 Dc - Da v*(Tc - Ta) v*t3三个等式、两个未知数x和y属于超定方程组。任取两式可以解出一组(x,y)三式组合可解出三组最后取平均。4.2 解析求根的简化思路直接展开平方根式会得到二次方程手推容易出错用MATLAB或Python预先符号推导更靠谱。思路是把Db - Da k1两边平方式化利用Db^2 - Da^2 (Db-Da)(DbDa) k1*(DbDa)可以把DbDa写成含x、y的线性表达式从而把非线性方程组转成线性。对A、B两点Db^2 - Da^2 (x-L)^2 y^2 - x^2 - y^2 L^2 - 2Lx而右边等于k1*(DbDa)于是DbDa (L^2 - 2Lx)/k1。结合Db - Da k1可得Da [(L^2 - 2Lx)/k1 - k1] / 2 sqrt(x^2 y^2)再平方一次就得到关于x、y的二次方程。同理对其他点对做同样处理最后用最小二乘求解。import numpy as np def solve_source(meas, rect, v340.0): meas: 四个到达时间 [Ta, Tb, Tc, Td] rect: 矩形尺寸 [L, W] 返回声源坐标 (x, y) L, W rect t1 v * (meas[1] - meas[0]) # Tb - Ta t2 v * (meas[3] - meas[0]) # Td - Ta t3 v * (meas[2] - meas[0]) # Tc - Ta # 用A(0,0), B(L,0)得到的一条关系Db^2 - Da^2 L^2 - 2Lx # Db - Da t1配合可消去 Da 项 A_rows [] b_vals [] # A-B 对 A_rows.append([2*L, 0]); b_vals.append(L*L - t1*t1 - 2*t1*0) # A-D 对 A_rows.append([0, 2*W]); b_vals.append(W*W - t2*t2) # A-C 对角对辅助 A_rows.append([2*L, 2*W]); b_vals.append(L*L W*W - t3*t3) A np.array(A_rows, dtypefloat) b np.array(b_vals, dtypefloat) sol, *_ np.linalg.lstsq(A, b, rcondNone) # 最小二乘 return sol[0], sol[1]逻辑说明把三个距离差方程整理成2Lx 0*y b这类线性形式然后用最小二乘一次性解出x、y等价于对超定方程组求最优解精度比任取两式求平均更稳。参数说明v取340m/s是常温空气中的声速温度每变化1°C声速变化约0.6m/s如果测试环境有较大温差需要现场标定。rcondNone交给numpy自动判断奇异值阈值。4.3 采样同步与常见误用超定方程组能不能求出准的解关键不在算法而在四路数据是不是同一时刻采的。如果四个通道分时轮流采样彼此间隔几十微秒时间差测出来必然带系统性偏差。STM32F103的ADC只有一套采样保持电路四通道是轮流转换的所以严格来说并不是同时采样。工程上通常通过以下手段缓解提高采样率把通道间间隔压缩到可忽略的量级比如1us以内需采样率达1MHz做不到对500Hz的周期信号用多周期平均来平滑单周期的量化误差用互相关而非单点过零把时间差估计精度提升到亚采样级另一个常见坑是把两个声源同时开着正文提到有两个声源位置却不做频率区分或时间分片。两个500Hz源叠加后会形成拍频过零点漂移解出的坐标直接跳变。正确做法是一次只发一个源或者给两个源用不同频率。提示如果测出来的坐标总是偏向矩形某个角先别怀疑算法用示波器看四路滤波后的信号是否同相——通常是某一级滤波器的相位延迟比其他路大等于人为制造了一个固定的时间偏置。5. 验证方法从单频点扫频到坐标纸实测5.1 先验证模拟通路再验证算法把系统拆成两半分别验证是省时间的做法。模拟通路验证只需要信号发生器和示波器在话筒位置注入500Hz正弦波逐级观察555输出、AGC输出、低通输出、高通输出确认通带中心在500Hz、增益在期望范围内。这一步做完再上ADC采样看波形是否畸变。算法验证可以不依赖硬件在MATLAB或Python里随机生成若干个声源坐标正向算出理论时间差加一些高斯噪声再喂给解算函数看误差分布。这样能快速找出解算方程在哪些坐标区域病态。5.2 坐标纸上的误差来源定位正文附录里有实物图和坐标纸测试方法。实际做的时候把矩形四个角贴好拾音器声源放在纸面已知坐标点上逐个测。记录实测值和理论值的偏差画散点图。常见的误差模式和对症做法如下误差现象可能的来源排查手段中心区域误差大、四角小双曲线/方程组在中心区病态增加接收点或改用最小二乘精化整体坐标偏移固定量某一通道固定相位延迟用单点标定修正时间偏置远近误差差异大AGC未起效信号削顶示波器看AGC输出摆幅是否恒定随机跳变环境噪声或混响多次测量取中位数加强滤波5.3 一个具体的标定技巧标定的顺序应当是先固定声源在矩形中心正对一个已知距离记录四路的到达时间和绝对幅度然后保持声源不动仅改声源频率比如490、500、510Hz看时间差读数如何漂移。如果漂移量随频率近似线性说明滤波器的群延迟不均匀需要把两级滤波器的中心频率对准声源实际频率而不是理论值。另一个技巧是引入参考通道。把四个话筒其中一路当作基准只测另外三路与它的时间差这样滤波器的共模相位延迟互相抵消剩下的只是通道间的相对差异通常小一个数量级。这是从双通道到多通道TDOA测量里通用的降error手段值得在毕设之外的实际项目中保留。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门