欢迎光临
我们一直在努力

声音方向识别系统(180° 四向)设计方案

项目内容描述
1.能识别180度范围内的4个方向
2.精度要求把180度分成4份,人站在不同位置能大概分辨出位置即可。

请从上面所给出的需求中,提供一个详细深入精确的设计方案,声音方向识别。
解析与方案库:完整设计方案,包括系统框图、关键器件选型、软件流程图;
用通俗易懂的实例详细深入精确地解析说明。


设计一个声音方向识别系统,能识别180度范围内的4个方向(即每个方向约45度范围)。精度要求不高,把人站在不同位置能大概分辨出位置即可。需要提供详细设计方案,包括系统框图、关键器件选型、软件流程图、UML建模、文件结构等。

任务:为“声音方向识别”提供一个详细深入精确的设计方案。需要覆盖完整的设计,包括系统框图、关键器件选型、软件流程图;用通俗易懂的实例详细深入精确地解析说明;并用UML建模并提供具体详尽深入的方案,用Markdown和Mermaid建立文档,建立项目文件结构组织,详细深入精确地概述整个设计开发过程中的机理、方法、步骤、方案。

首先分析需求:“能识别180度范围内的4个方向”意味着设备可以检测声音来源在左侧、左前、右前、右侧(例如),将180度划分为4个扇区,每个扇区45度。精度要求不高,只要能区分大致方向即可。

方法:可采用多个麦克风阵列(例如4个麦克风)通过声源定位算法(如TDOA,到达时间差,或简单的幅度比较)。由于精度要求低,可以使用幅度差(ILD)或粗略的时延估计。可选用低成本的MEMS麦克风,配合MCU(如STM32)进行信号处理。输出可以是4个LED指示方向,或通过串口上报。

设计内容应包括:

  • 系统框图:4个麦克风呈直线排列或十字形?180度覆盖,用2个麦克风只能分辨左右,要4个方向,可以3个麦克风等腰三角形?用4个麦克风呈180度圆弧排列,每个间隔45度,利用各麦克风接收到的信号强度来判断方向。简单有效:4个定向麦克风(或心形指向)安装在设备前方180度范围,分别朝向4个方向,然后比较哪个麦克风信号最强。但这样需要定向麦克风,不通用。另一种:使用4个全向麦克风组成的阵列,通过计算时延差估计方向。考虑到精度不高,可选用3个或4个麦克风等距直线阵列或圆形阵列。如3个麦克风等距直线(间距~5cm),可分辨左右,但前后?180度平面,可以用三个麦克风呈直角三角形或等边三角形?实际上二维定位需要至少3个麦克风。我们只需区分4个方向,可以在180度范围布置4个麦克风指向不同方向,通过比较能量大小,简单可靠。

设计实例:设备类似于一个基站,人站在180度范围内说话,设备上的4个LED灯指示方向。我们可以采用4个心形指向的麦克风(或全向麦加物理挡板形成指向性),分别对准前方0°、45°、90°、135°(右侧)。或者我们可以使用4个全向麦克风,通过波束成形(延迟求和)虚拟出4个方向的指向性。用STM32F407等MCU,4个ADC同步采样,做FFT计算能量,根据各通道能量大小判定方向。这种方法对算法要求低,适合低成本。

详细方案:

  • 系统框图:4路MEMS麦克风 → 模拟放大 → STM32 ADC同步采样 → 数字带通滤波(人声频段300-3400Hz)→ 计算各通道能量 → 比较能量 → 输出方向。

  • 关键器件:MEMS麦克风(如INMP441,数字I2S接口,可以简化采样,但需要4个I2S接口,MCU可能不够)。模拟麦克风如MAX9814带AGC,然后STM32多通道ADC。

    • 可选:SPH0645LM4H-B(I2S数字麦克风),可通过I2S多通道或TDM方式,MCU如STM32H7有多个I2S。或者使用4个模拟麦克风+4个ADC通道,STM32F4有3个独立ADC,可同时采样。
  • 软件流程图:初始化 → 定时采集音频(例如每10ms采集2048点) → FFT/能量计算 → 峰值检测 → 方向逻辑判断 → 输出LED/UART。

  • UML建模:类图、序列图、状态图。

  • 项目文件结构。

  • 提供一个通俗易懂的实例:比如一个圆盘底座,面向用户180度,有4个LED指示灯。当人站在左侧说话,左侧LED亮;左前、右前、右侧分别对应。技术上如何实现。

    需要给出机理、方法、步骤、方案。

    因此回答内容要包括:

    • 项目概述

    • 设计思路

    • 系统架构框图(Mermaid)

    • 关键器件选型表

    • 软件流程图(Mermaid)

    • UML建模(用例图、类图、序列图、状态图)

    • 核心机理深度解析(波束形成、能量比较法、TDOA)

    • 项目文件结构组织

    • 开发步骤与方法

    • 总结

    因为问题要求“声音方向识别”,以基于能量比较的麦克风阵列方案为主,因为要求精度不高,且能识别4个方向。

    也会提及可以用声达时间差(TDOA)方法但更复杂,而能量法更简单。

    方案具体、详尽。


    声音方向识别系统(180° 四向)设计方案

    1. 项目概述与典型实例

    本方案设计一个低成本声音方向识别模块,能检测 180° 范围内声源所在的四个大致方向(每 45° 一个扇区),精度要求不高。系统通过四路心形麦克风阵列,利用能量比较法判断声源位置,结果通过 LED 指示或串口输出。

    典型实例:
    一个智能家居控制面板,平放在桌面,前方 180° 范围内有用户说话。设备表面的四个 LED 灯分别代表左后、左前、右前、右后四个方向。当用户站在左前方说“开灯”,对应的 LED 点亮,系统可联动转向该区域照明。
    不需要精确到度,只需知道是哪个扇区。

    2. 系统总体设计

    2.1 设计思路

    采用 四只心形指向模拟麦克风,物理上分别对准 0°(正前)、45°(左前)、90°(左侧)、135°(左后)。每只麦克风接收信号经放大、带通滤波后,由 MCU 四路 ADC 同步采样。对每路信号计算语音频段(300~3400Hz)的能量,能量最强的通道即为声源方向。

    为什么用心形麦克风?
    心形指向对正前方声音灵敏,对背面和侧面衰减大,天然具备方向选择能力,硬件上简化算法。若使用全向麦克风,则需通过阵列时延求和(波束成形)软实现指向,MCU 开销大。精度要求不高,心形麦是最佳选择。

    2.2 硬件系统框图

    #mermaid-svg-XfbcD6RdfQKvDTm4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-XfbcD6RdfQKvDTm4 .error-icon{fill:#552222;}#mermaid-svg-XfbcD6RdfQKvDTm4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XfbcD6RdfQKvDTm4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .marker.cross{stroke:#333333;}#mermaid-svg-XfbcD6RdfQKvDTm4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XfbcD6RdfQKvDTm4 p{margin:0;}#mermaid-svg-XfbcD6RdfQKvDTm4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster-label text{fill:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster-label span{color:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster-label span p{background-color:transparent;}#mermaid-svg-XfbcD6RdfQKvDTm4 .label text,#mermaid-svg-XfbcD6RdfQKvDTm4 span{fill:#333;color:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .node rect,#mermaid-svg-XfbcD6RdfQKvDTm4 .node circle,#mermaid-svg-XfbcD6RdfQKvDTm4 .node ellipse,#mermaid-svg-XfbcD6RdfQKvDTm4 .node polygon,#mermaid-svg-XfbcD6RdfQKvDTm4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .rough-node .label text,#mermaid-svg-XfbcD6RdfQKvDTm4 .node .label text,#mermaid-svg-XfbcD6RdfQKvDTm4 .image-shape .label,#mermaid-svg-XfbcD6RdfQKvDTm4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-XfbcD6RdfQKvDTm4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .rough-node .label,#mermaid-svg-XfbcD6RdfQKvDTm4 .node .label,#mermaid-svg-XfbcD6RdfQKvDTm4 .image-shape .label,#mermaid-svg-XfbcD6RdfQKvDTm4 .icon-shape .label{text-align:center;}#mermaid-svg-XfbcD6RdfQKvDTm4 .node.clickable{cursor:pointer;}#mermaid-svg-XfbcD6RdfQKvDTm4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .arrowheadPath{fill:#333333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfbcD6RdfQKvDTm4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-XfbcD6RdfQKvDTm4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfbcD6RdfQKvDTm4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster text{fill:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 .cluster span{color:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XfbcD6RdfQKvDTm4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-XfbcD6RdfQKvDTm4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-XfbcD6RdfQKvDTm4 .icon-shape,#mermaid-svg-XfbcD6RdfQKvDTm4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-XfbcD6RdfQKvDTm4 .icon-shape p,#mermaid-svg-XfbcD6RdfQKvDTm4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-XfbcD6RdfQKvDTm4 .icon-shape .label rect,#mermaid-svg-XfbcD6RdfQKvDTm4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-XfbcD6RdfQKvDTm4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-XfbcD6RdfQKvDTm4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-XfbcD6RdfQKvDTm4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    STM32F407VET6

    4路心形麦克风阵列

    电源

    USB 5V

    AMS1117-3.3V

    麦克风0朝0°

    放大 MAX9814

    麦克风45°

    放大 MAX9814

    麦克风90°

    放大 MAX9814

    麦克风135°

    放大 MAX9814

    ADC1_CH0

    ADC1_CH1

    ADC2_CH2

    ADC3_CH3

    Cortex-M4 168MHz

    定时器触发同步采样

    4路DMA传输

    数字带通滤波+能量计算

    方向判断逻辑

    4方向LED指示

    串口输出

    解释:四只指向性麦克风分别朝向 0°、45°、90°、135°(覆盖 180°),信号经放大后送入 STM32 的四个独立 ADC 通道(利用 3 个 ADC 模块同时采样),DMA 循环搬运数据。MCU 运行语音频段滤波与能量计算,实时比较各通道能量,能量最大者即为当前声源方向。

    2.3 关键器件选型

    功能域器件型号选型理由
    麦克风 驻极体心形指向咪头 (9.7mm) 成本低,心形特性明显,灵敏度 -42dB,频率响应 50-16kHz
    麦克风放大器 MAX9814 (AGC 可关闭) 集成低噪声放大器,可调增益,2.7-5.5V 供电,输出可直接送 ADC
    主控 MCU STM32F407VET6 3 个 12-bit ADC (各 2.4Msps),4 个通道可同时采样(规则并行模式),168MHz,DMA,适合实时音频处理
    电源 AMS1117-3.3V 5V→3.3V,1A,稳定可靠
    LED 指示 高亮 LED ×4(不同颜色) 直观显示方向
    串口 USB 转 TTL (CH340) 调试及上报方向数据

    3. 软件流程图

    3.1 主程序流程

    #mermaid-svg-PbzvtE8C7BOjIUuv{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PbzvtE8C7BOjIUuv .error-icon{fill:#552222;}#mermaid-svg-PbzvtE8C7BOjIUuv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PbzvtE8C7BOjIUuv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PbzvtE8C7BOjIUuv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PbzvtE8C7BOjIUuv .marker.cross{stroke:#333333;}#mermaid-svg-PbzvtE8C7BOjIUuv svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PbzvtE8C7BOjIUuv p{margin:0;}#mermaid-svg-PbzvtE8C7BOjIUuv .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster-label text{fill:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster-label span{color:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster-label span p{background-color:transparent;}#mermaid-svg-PbzvtE8C7BOjIUuv .label text,#mermaid-svg-PbzvtE8C7BOjIUuv span{fill:#333;color:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv .node rect,#mermaid-svg-PbzvtE8C7BOjIUuv .node circle,#mermaid-svg-PbzvtE8C7BOjIUuv .node ellipse,#mermaid-svg-PbzvtE8C7BOjIUuv .node polygon,#mermaid-svg-PbzvtE8C7BOjIUuv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PbzvtE8C7BOjIUuv .rough-node .label text,#mermaid-svg-PbzvtE8C7BOjIUuv .node .label text,#mermaid-svg-PbzvtE8C7BOjIUuv .image-shape .label,#mermaid-svg-PbzvtE8C7BOjIUuv .icon-shape .label{text-anchor:middle;}#mermaid-svg-PbzvtE8C7BOjIUuv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PbzvtE8C7BOjIUuv .rough-node .label,#mermaid-svg-PbzvtE8C7BOjIUuv .node .label,#mermaid-svg-PbzvtE8C7BOjIUuv .image-shape .label,#mermaid-svg-PbzvtE8C7BOjIUuv .icon-shape .label{text-align:center;}#mermaid-svg-PbzvtE8C7BOjIUuv .node.clickable{cursor:pointer;}#mermaid-svg-PbzvtE8C7BOjIUuv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PbzvtE8C7BOjIUuv .arrowheadPath{fill:#333333;}#mermaid-svg-PbzvtE8C7BOjIUuv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PbzvtE8C7BOjIUuv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PbzvtE8C7BOjIUuv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PbzvtE8C7BOjIUuv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PbzvtE8C7BOjIUuv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PbzvtE8C7BOjIUuv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster text{fill:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv .cluster span{color:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PbzvtE8C7BOjIUuv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PbzvtE8C7BOjIUuv rect.text{fill:none;stroke-width:0;}#mermaid-svg-PbzvtE8C7BOjIUuv .icon-shape,#mermaid-svg-PbzvtE8C7BOjIUuv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PbzvtE8C7BOjIUuv .icon-shape p,#mermaid-svg-PbzvtE8C7BOjIUuv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PbzvtE8C7BOjIUuv .icon-shape .label rect,#mermaid-svg-PbzvtE8C7BOjIUuv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PbzvtE8C7BOjIUuv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PbzvtE8C7BOjIUuv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PbzvtE8C7BOjIUuv :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    每隔 100ms

    上电

    初始化: 时钟, ADC, DMA, 定时器, LED

    采集静音噪声基底

    启动 ADC 定时采样, 10kHz 每通道

    主循环

    已采集 1024 点?

    每个通道做带通滤波 300-3400Hz

    计算每通道 RMS 能量

    找出能量最大的通道

    最大能量 > 阈值?

    判定无有效声源

    点亮对应方向 LED串口发送方向码

    清除缓存, 继续采集

    说明:采样率 10kHz,每 100ms 处理 1024 点,满足人声频段(<4kHz)且足够快。阈值用于排除环境噪声。

    3.2 带通滤波器实现

    采用 双二阶 IIR 带通滤波器,中心频率 1.5kHz,Q=0.7,覆盖人声主要能量区。代码如下(伪):

    b = [0.2, 0, -0.2]
    a = [1, -1.5, 0.7]

    在中断或主循环中调用直接Ⅰ型结构,计算量小。

    3.3 能量计算与方向判定

    每个通道的 RMS = sqrt( sum(samples^2) / N )。比较四个 RMS,取最大值索引。加入滞后:为防止频繁跳变,只有当新方向连续 3 次胜出才更新输出。

    4. UML 建模

    4.1 用例图

    #mermaid-svg-ZFi6AoSQ6Ak10siz{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZFi6AoSQ6Ak10siz .error-icon{fill:#552222;}#mermaid-svg-ZFi6AoSQ6Ak10siz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZFi6AoSQ6Ak10siz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .marker.cross{stroke:#333333;}#mermaid-svg-ZFi6AoSQ6Ak10siz svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZFi6AoSQ6Ak10siz p{margin:0;}#mermaid-svg-ZFi6AoSQ6Ak10siz .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster-label text{fill:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster-label span{color:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster-label span p{background-color:transparent;}#mermaid-svg-ZFi6AoSQ6Ak10siz .label text,#mermaid-svg-ZFi6AoSQ6Ak10siz span{fill:#333;color:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .node rect,#mermaid-svg-ZFi6AoSQ6Ak10siz .node circle,#mermaid-svg-ZFi6AoSQ6Ak10siz .node ellipse,#mermaid-svg-ZFi6AoSQ6Ak10siz .node polygon,#mermaid-svg-ZFi6AoSQ6Ak10siz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .rough-node .label text,#mermaid-svg-ZFi6AoSQ6Ak10siz .node .label text,#mermaid-svg-ZFi6AoSQ6Ak10siz .image-shape .label,#mermaid-svg-ZFi6AoSQ6Ak10siz .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZFi6AoSQ6Ak10siz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .rough-node .label,#mermaid-svg-ZFi6AoSQ6Ak10siz .node .label,#mermaid-svg-ZFi6AoSQ6Ak10siz .image-shape .label,#mermaid-svg-ZFi6AoSQ6Ak10siz .icon-shape .label{text-align:center;}#mermaid-svg-ZFi6AoSQ6Ak10siz .node.clickable{cursor:pointer;}#mermaid-svg-ZFi6AoSQ6Ak10siz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .arrowheadPath{fill:#333333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZFi6AoSQ6Ak10siz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZFi6AoSQ6Ak10siz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZFi6AoSQ6Ak10siz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster text{fill:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz .cluster span{color:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZFi6AoSQ6Ak10siz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZFi6AoSQ6Ak10siz rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZFi6AoSQ6Ak10siz .icon-shape,#mermaid-svg-ZFi6AoSQ6Ak10siz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZFi6AoSQ6Ak10siz .icon-shape p,#mermaid-svg-ZFi6AoSQ6Ak10siz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZFi6AoSQ6Ak10siz .icon-shape .label rect,#mermaid-svg-ZFi6AoSQ6Ak10siz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZFi6AoSQ6Ak10siz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZFi6AoSQ6Ak10siz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZFi6AoSQ6Ak10siz :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    使用者

    发出声音

    声音方向识别模块

    检测并指示声音方向

    通过串口输出方向数据

    上位机

    4.2 核心类图(C++ 抽象)

    #mermaid-svg-0HC40tnSlEmYfRWL{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0HC40tnSlEmYfRWL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0HC40tnSlEmYfRWL .error-icon{fill:#552222;}#mermaid-svg-0HC40tnSlEmYfRWL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0HC40tnSlEmYfRWL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0HC40tnSlEmYfRWL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0HC40tnSlEmYfRWL .marker.cross{stroke:#333333;}#mermaid-svg-0HC40tnSlEmYfRWL svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0HC40tnSlEmYfRWL p{margin:0;}#mermaid-svg-0HC40tnSlEmYfRWL g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-0HC40tnSlEmYfRWL g.classGroup text .title{font-weight:bolder;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster-label text{fill:#333;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster-label span{color:#333;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster-label span p{background-color:transparent;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster text{fill:#333;}#mermaid-svg-0HC40tnSlEmYfRWL .cluster span{color:#333;}#mermaid-svg-0HC40tnSlEmYfRWL .nodeLabel,#mermaid-svg-0HC40tnSlEmYfRWL .edgeLabel{color:#131300;}#mermaid-svg-0HC40tnSlEmYfRWL .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-0HC40tnSlEmYfRWL .label text{fill:#131300;}#mermaid-svg-0HC40tnSlEmYfRWL .labelBkg{background:#ECECFF;}#mermaid-svg-0HC40tnSlEmYfRWL .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-0HC40tnSlEmYfRWL .classTitle{font-weight:bolder;}#mermaid-svg-0HC40tnSlEmYfRWL .node rect,#mermaid-svg-0HC40tnSlEmYfRWL .node circle,#mermaid-svg-0HC40tnSlEmYfRWL .node ellipse,#mermaid-svg-0HC40tnSlEmYfRWL .node polygon,#mermaid-svg-0HC40tnSlEmYfRWL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0HC40tnSlEmYfRWL .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL g.clickable{cursor:pointer;}#mermaid-svg-0HC40tnSlEmYfRWL g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-0HC40tnSlEmYfRWL g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-0HC40tnSlEmYfRWL .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-0HC40tnSlEmYfRWL .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-0HC40tnSlEmYfRWL .dashed-line{stroke-dasharray:3;}#mermaid-svg-0HC40tnSlEmYfRWL .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-0HC40tnSlEmYfRWL #compositionStart,#mermaid-svg-0HC40tnSlEmYfRWL .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #compositionEnd,#mermaid-svg-0HC40tnSlEmYfRWL .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #dependencyStart,#mermaid-svg-0HC40tnSlEmYfRWL .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #dependencyStart,#mermaid-svg-0HC40tnSlEmYfRWL .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #extensionStart,#mermaid-svg-0HC40tnSlEmYfRWL .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #extensionEnd,#mermaid-svg-0HC40tnSlEmYfRWL .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #aggregationStart,#mermaid-svg-0HC40tnSlEmYfRWL .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #aggregationEnd,#mermaid-svg-0HC40tnSlEmYfRWL .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #lollipopStart,#mermaid-svg-0HC40tnSlEmYfRWL .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL #lollipopEnd,#mermaid-svg-0HC40tnSlEmYfRWL .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-0HC40tnSlEmYfRWL .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-0HC40tnSlEmYfRWL .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0HC40tnSlEmYfRWL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0HC40tnSlEmYfRWL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0HC40tnSlEmYfRWL :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    DirectionDetector

    – MicChannel channels[4]

    – FIRFilter filter

    – int currentDirection

    + update()

    + getDirection() : int

    MicChannel

    – ADC_Driver* adc

    – float buffer[1024]

    + collectSamples()

    + getRMS() : float

    FIRFilter

    – float coeff_b[3], coeff_a[3]

    + apply(input, output)

    4.3 序列图:一次方向检测

    LED指示DirectionDetectorMicChannel定时器LED指示DirectionDetectorMicChannel定时器#mermaid-svg-cThmtyVvTQ5HRtXu{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cThmtyVvTQ5HRtXu .error-icon{fill:#552222;}#mermaid-svg-cThmtyVvTQ5HRtXu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cThmtyVvTQ5HRtXu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cThmtyVvTQ5HRtXu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cThmtyVvTQ5HRtXu .marker.cross{stroke:#333333;}#mermaid-svg-cThmtyVvTQ5HRtXu svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cThmtyVvTQ5HRtXu p{margin:0;}#mermaid-svg-cThmtyVvTQ5HRtXu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cThmtyVvTQ5HRtXu text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cThmtyVvTQ5HRtXu .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-cThmtyVvTQ5HRtXu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-cThmtyVvTQ5HRtXu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-cThmtyVvTQ5HRtXu .sequenceNumber{fill:white;}#mermaid-svg-cThmtyVvTQ5HRtXu #sequencenumber{fill:#333;}#mermaid-svg-cThmtyVvTQ5HRtXu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-cThmtyVvTQ5HRtXu .messageText{fill:#333;stroke:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cThmtyVvTQ5HRtXu .labelText,#mermaid-svg-cThmtyVvTQ5HRtXu .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .loopText,#mermaid-svg-cThmtyVvTQ5HRtXu .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-cThmtyVvTQ5HRtXu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-cThmtyVvTQ5HRtXu .noteText,#mermaid-svg-cThmtyVvTQ5HRtXu .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-cThmtyVvTQ5HRtXu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cThmtyVvTQ5HRtXu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cThmtyVvTQ5HRtXu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-cThmtyVvTQ5HRtXu .actorPopupMenu{position:absolute;}#mermaid-svg-cThmtyVvTQ5HRtXu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-cThmtyVvTQ5HRtXu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-cThmtyVvTQ5HRtXu .actor-man circle,#mermaid-svg-cThmtyVvTQ5HRtXu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-cThmtyVvTQ5HRtXu :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}触发采样DMA 接收 1024 点通知数据就绪获取4通道RMS比较能量,选出最大点亮对应方向LED

    4.4 方向状态机

    #mermaid-svg-hMKUOlk1nm2X6Eia{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hMKUOlk1nm2X6Eia .error-icon{fill:#552222;}#mermaid-svg-hMKUOlk1nm2X6Eia .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hMKUOlk1nm2X6Eia .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hMKUOlk1nm2X6Eia .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia .marker.cross{stroke:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hMKUOlk1nm2X6Eia p{margin:0;}#mermaid-svg-hMKUOlk1nm2X6Eia defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-hMKUOlk1nm2X6Eia g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-hMKUOlk1nm2X6Eia g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-hMKUOlk1nm2X6Eia g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-hMKUOlk1nm2X6Eia g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-hMKUOlk1nm2X6Eia .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-hMKUOlk1nm2X6Eia .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-hMKUOlk1nm2X6Eia .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-hMKUOlk1nm2X6Eia .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-hMKUOlk1nm2X6Eia .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-hMKUOlk1nm2X6Eia .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hMKUOlk1nm2X6Eia .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hMKUOlk1nm2X6Eia .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hMKUOlk1nm2X6Eia .edgeLabel .label text{fill:#333;}#mermaid-svg-hMKUOlk1nm2X6Eia .label div .edgeLabel{color:#333;}#mermaid-svg-hMKUOlk1nm2X6Eia .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-hMKUOlk1nm2X6Eia .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-hMKUOlk1nm2X6Eia .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-hMKUOlk1nm2X6Eia .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia #statediagram-barbEnd{fill:#333333;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hMKUOlk1nm2X6Eia .cluster-label,#mermaid-svg-hMKUOlk1nm2X6Eia .nodeLabel{color:#131300;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-hMKUOlk1nm2X6Eia .note-edge{stroke-dasharray:5;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-note text{fill:black;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram-note .nodeLabel{color:black;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagram .edgeLabel{color:red;}#mermaid-svg-hMKUOlk1nm2X6Eia #dependencyStart,#mermaid-svg-hMKUOlk1nm2X6Eia #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-hMKUOlk1nm2X6Eia .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hMKUOlk1nm2X6Eia :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    Ch0能量最大

    Ch1能量最大

    Ch2能量最大

    Ch3能量最大

    无足够能量

    Silence

    Dir0

    Dir1

    Dir2

    Dir3

    5. 核心机理深度解析

    5.1 心形麦克风指向性原理

    心形指向 = 全向 + 双向 的合成。正面灵敏度高,180° 背面灵敏度极低。四只麦克风物理安装如图:

    背面
    麦克3(135°) 麦克0(0°)
    \\ /
    \\ 设备 /
    \\ /
    \\ /
    中心
    / \\
    / \\
    麦克2(90°) 麦克1(45°)
    右侧 右前

    实际 180° 范围被划分为:左后 (135°~180°),左前 (90°~135°),右前 (45°~90°),右侧 (0°~45°)。每个麦克风主瓣对应一个扇区。由于心形曲线在主瓣附近灵敏度相近,当人站在 45° 附近时,麦克 1 和麦克 0 可能都有输出,但麦克 1 相对能量更强,仍可正确识别。

    5.2 能量比较与干扰滤除

    • 语音频段滤波:人声能量集中在 300~3400Hz,用 IIR 带通滤波可滤除低频风噪、高频电路噪声。
    • 静音阈值:根据静音时的噪声基底设定阈值,低于阈值视为无有效声源。
    • 去毛刺:能量比较后,连续多帧一致才确认方向,防止瞬间干扰。

    5.3 采样同步

    STM32F407 有 3 个独立 ADC,可配置为 双重/三重同步模式。本设计需 4 个通道,可启用 ADC1+ADC2 同步(各两通道),或 ADC1 注入通道与 ADC2/3 配合,确保所有通道严格对齐采样时刻,避免时延导致能量偏差。

    6. 项目文件结构组织

    sound_direction_detector/
    ├── hardware/
    │ ├── schematic/ # 原理图 (AD)
    │ │ ├── mic_array.sch
    │ │ ├── mcu_board.sch
    │ └── pcb/ # PCB 文件
    │ └── bom/ # 物料清单
    ├── firmware/
    │ ├── Core/
    │ │ ├── Inc/ # 头文件
    │ │ └── Src/
    │ │ ├── main.c
    │ │ ├── adc_drv.c/h
    │ │ ├── fir_filter.c/h
    │ │ ├── direction_detect.c/h
    │ │ └── led_uart.c/h
    │ ├── Drivers/
    │ │ └── STM32F4xx_HAL/
    │ └── MDK-ARM/ # Keil 工程
    ├── docs/
    │ ├── system_design.md # 本设计文档
    │ ├── uml/ # UML 源文件
    │ └── user_manual.pdf
    ├── test/
    │ └── pyaudio_test.py # 上位机模拟测试脚本
    └── README.md

    7. 开发方法与步骤

    阶段 1:硬件搭建(1 周)

    • 焊接 4 个心形麦克风及 MAX9814 模块,调至适当增益(测试输出幅值 1Vpp 左右)。
    • 连接至 STM32F407 开发板对应 ADC 引脚。
    • 烧录测试程序,用示波器观察各路音频波形。

    阶段 2:信号采集与处理(1 周)

    • 配置 ADC 同步采样、DMA 循环缓冲。
    • 实现双二阶 IIR 带通滤波,调试系数。
    • 计算 RMS 能量,串口打印四路能量值。

    阶段 3:方向判定算法(0.5 周)

    • 添加阈值判定、滞后逻辑。
    • 编写 LED 指示和串口输出。
    • 在不同位置说话,验证方向识别正确率。

    阶段 4:优化与测试(0.5 周)

    • 噪声环境下测试(风扇、空调),调整阈值。
    • 多角度测试,绘制识别正确率图。
    • 编写技术文档。

    8. 总结

    本方案采用 4 只心形指向麦克风 + STM32F407 同步采样 的方式,以极简的硬件和算法实现了 180° 四向声源定位。相比复杂的麦克风阵列波束成形,利用物理指向性大幅降低成本和开发难度,同时满足“精度不高,能分辨大致方向”的需求。完整的 UML 建模和软件流程为项目的快速落地提供了清晰指导。# 声音方向识别系统(180° 四向)设计方案

    1. 项目概述与典型实例

    本项目实现一个 低成本声音方向识别模块,能将 180° 平面内的声源定位到 4 个大致方向(每个扇区约 45°),精度要求不高。系统通过 4 路心形指向麦克风 物理区分方向,利用 能量比较法 判断声源所在扇区,结果通过 LED 或串口输出。

    通俗实例:
    一个智能音箱放在电视柜上,正面 180° 范围内有人说话。音箱上有 4 颗 LED,分别代表“左后方、左前方、右前方、右后方”。当人站在左前方说“播放音乐”,对应的 LED 点亮,音箱可以据此调整语音唤醒的灵敏度方向或联动其他智能设备。不需要精确角度,只要知道是哪个大概区域就行。


    2. 系统总体架构

    2.1 设计思路

    使用 4 个心形指向驻极体麦克风,物理上分别对准 0°、45°、90°、135°(覆盖 180°)。每个麦克风后的放大电路将信号调理到合适幅度,然后送入 STM32F407 的 4 个 ADC 通道进行同步采样。MCU 对每路信号做 人声频段带通滤波,实时计算 短时能量,能量最强的通道即为当前声音方向。这种方案天然利用麦克风的物理指向性,算法简单,抗干扰能力强。

    2.2 系统框图

    #mermaid-svg-uUP9d0VQRlvvFOoE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uUP9d0VQRlvvFOoE .error-icon{fill:#552222;}#mermaid-svg-uUP9d0VQRlvvFOoE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uUP9d0VQRlvvFOoE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uUP9d0VQRlvvFOoE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uUP9d0VQRlvvFOoE .marker.cross{stroke:#333333;}#mermaid-svg-uUP9d0VQRlvvFOoE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uUP9d0VQRlvvFOoE p{margin:0;}#mermaid-svg-uUP9d0VQRlvvFOoE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster-label text{fill:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster-label span{color:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster-label span p{background-color:transparent;}#mermaid-svg-uUP9d0VQRlvvFOoE .label text,#mermaid-svg-uUP9d0VQRlvvFOoE span{fill:#333;color:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE .node rect,#mermaid-svg-uUP9d0VQRlvvFOoE .node circle,#mermaid-svg-uUP9d0VQRlvvFOoE .node ellipse,#mermaid-svg-uUP9d0VQRlvvFOoE .node polygon,#mermaid-svg-uUP9d0VQRlvvFOoE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uUP9d0VQRlvvFOoE .rough-node .label text,#mermaid-svg-uUP9d0VQRlvvFOoE .node .label text,#mermaid-svg-uUP9d0VQRlvvFOoE .image-shape .label,#mermaid-svg-uUP9d0VQRlvvFOoE .icon-shape .label{text-anchor:middle;}#mermaid-svg-uUP9d0VQRlvvFOoE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uUP9d0VQRlvvFOoE .rough-node .label,#mermaid-svg-uUP9d0VQRlvvFOoE .node .label,#mermaid-svg-uUP9d0VQRlvvFOoE .image-shape .label,#mermaid-svg-uUP9d0VQRlvvFOoE .icon-shape .label{text-align:center;}#mermaid-svg-uUP9d0VQRlvvFOoE .node.clickable{cursor:pointer;}#mermaid-svg-uUP9d0VQRlvvFOoE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uUP9d0VQRlvvFOoE .arrowheadPath{fill:#333333;}#mermaid-svg-uUP9d0VQRlvvFOoE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uUP9d0VQRlvvFOoE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uUP9d0VQRlvvFOoE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUP9d0VQRlvvFOoE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uUP9d0VQRlvvFOoE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUP9d0VQRlvvFOoE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster text{fill:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE .cluster span{color:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uUP9d0VQRlvvFOoE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uUP9d0VQRlvvFOoE rect.text{fill:none;stroke-width:0;}#mermaid-svg-uUP9d0VQRlvvFOoE .icon-shape,#mermaid-svg-uUP9d0VQRlvvFOoE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uUP9d0VQRlvvFOoE .icon-shape p,#mermaid-svg-uUP9d0VQRlvvFOoE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uUP9d0VQRlvvFOoE .icon-shape .label rect,#mermaid-svg-uUP9d0VQRlvvFOoE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uUP9d0VQRlvvFOoE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uUP9d0VQRlvvFOoE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uUP9d0VQRlvvFOoE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    STM32F407VET6

    心形麦克风阵列

    麦克风0朝向0°

    MAX9814

    麦克风45°

    MAX9814

    麦克风90°

    MAX9814

    麦克风135°

    MAX9814

    ADC1_IN0

    ADC1_IN1

    ADC2_IN2

    ADC3_IN3

    Cortex-M4 168MHz

    定时器触发采样

    4通道DMA

    带通滤波+能量计算

    方向判定逻辑

    4路LED指示

    串口输出方向

    USB 5V

    AMS1117-3.3V

    解释:麦克风拾取的音频信号经 MAX9814 放大后(增益可调),输出 0~3.3V 模拟电压。STM32 的 3 个独立 ADC 模块配置为同步规则模式,实现 4 路信号严格同时采样,避免时延误差。采集到的数据通过 DMA 存入缓冲区,CPU 在主循环中处理。

    2.3 关键器件选型

    器件型号/规格选型理由
    麦克风 心形指向驻极体咪头 (9.7mm) -42dB 灵敏度,心形特性明显,50~16kHz,价格低
    放大器 MAX9814 (模块) 内置低噪放,增益可调,2.7~5.5V供电,输出可直接接 ADC
    主控MCU STM32F407VET6 3 个独立 ADC,每个 2.4Msps,支持同步采样,168MHz,DMA,适合实时处理
    电源 AMS1117-3.3V 5V转3.3V,1A,简单可靠
    LED 高亮 LED ×4(红绿蓝黄) 指示方向
    串口 USB-TTL(CH340) 调试及上报

    3. 软件流程图

    3.1 主程序流程

    #mermaid-svg-8AUMkrWm1jOvnyoj{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8AUMkrWm1jOvnyoj .error-icon{fill:#552222;}#mermaid-svg-8AUMkrWm1jOvnyoj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8AUMkrWm1jOvnyoj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8AUMkrWm1jOvnyoj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8AUMkrWm1jOvnyoj .marker.cross{stroke:#333333;}#mermaid-svg-8AUMkrWm1jOvnyoj svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8AUMkrWm1jOvnyoj p{margin:0;}#mermaid-svg-8AUMkrWm1jOvnyoj .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster-label text{fill:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster-label span{color:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster-label span p{background-color:transparent;}#mermaid-svg-8AUMkrWm1jOvnyoj .label text,#mermaid-svg-8AUMkrWm1jOvnyoj span{fill:#333;color:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj .node rect,#mermaid-svg-8AUMkrWm1jOvnyoj .node circle,#mermaid-svg-8AUMkrWm1jOvnyoj .node ellipse,#mermaid-svg-8AUMkrWm1jOvnyoj .node polygon,#mermaid-svg-8AUMkrWm1jOvnyoj .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8AUMkrWm1jOvnyoj .rough-node .label text,#mermaid-svg-8AUMkrWm1jOvnyoj .node .label text,#mermaid-svg-8AUMkrWm1jOvnyoj .image-shape .label,#mermaid-svg-8AUMkrWm1jOvnyoj .icon-shape .label{text-anchor:middle;}#mermaid-svg-8AUMkrWm1jOvnyoj .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8AUMkrWm1jOvnyoj .rough-node .label,#mermaid-svg-8AUMkrWm1jOvnyoj .node .label,#mermaid-svg-8AUMkrWm1jOvnyoj .image-shape .label,#mermaid-svg-8AUMkrWm1jOvnyoj .icon-shape .label{text-align:center;}#mermaid-svg-8AUMkrWm1jOvnyoj .node.clickable{cursor:pointer;}#mermaid-svg-8AUMkrWm1jOvnyoj .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8AUMkrWm1jOvnyoj .arrowheadPath{fill:#333333;}#mermaid-svg-8AUMkrWm1jOvnyoj .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8AUMkrWm1jOvnyoj .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8AUMkrWm1jOvnyoj .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8AUMkrWm1jOvnyoj .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8AUMkrWm1jOvnyoj .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8AUMkrWm1jOvnyoj .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster text{fill:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj .cluster span{color:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8AUMkrWm1jOvnyoj .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8AUMkrWm1jOvnyoj rect.text{fill:none;stroke-width:0;}#mermaid-svg-8AUMkrWm1jOvnyoj .icon-shape,#mermaid-svg-8AUMkrWm1jOvnyoj .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8AUMkrWm1jOvnyoj .icon-shape p,#mermaid-svg-8AUMkrWm1jOvnyoj .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8AUMkrWm1jOvnyoj .icon-shape .label rect,#mermaid-svg-8AUMkrWm1jOvnyoj .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8AUMkrWm1jOvnyoj .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8AUMkrWm1jOvnyoj .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8AUMkrWm1jOvnyoj :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    每100ms

    上电初始化

    配置时钟,ADC,DMA,定时器

    采集静音噪声基底

    启动定时器触发ADC采样

    主循环

    采集够1024点?

    4路分别带通滤波 300-3400Hz

    计算各通道短时能量(RMS)

    找出能量最大的通道

    最大能量 > 噪声阈值?

    判定无有效声源, LED全灭

    连续3帧方向一致?

    更新缓存, 不清除输出

    点亮对应LED, 串口发送方向码

    清空缓冲, 继续采集

    3.2 数字带通滤波器

    采用 IIR 双二阶带通,中心频率 1.5kHz,Q=0.7,系数:

    b = [0.1367, 0, -0.1367]
    a = [1, -1.483, 0.7265]

    实现采用直接Ⅰ型结构,每个采样点只需 5 次乘加,4 路完全可实时。

    3.3 能量计算与方向判定

    每帧 1024 点,计算 RMS:

    rms = sqrt( sum(sample^2) / 1024 )

    比较四路 RMS,最大值索引即为方向候选。加入滞后:只有当连续 3 次胜出才更新输出,避免因环境反射导致频繁跳变。


    4. UML 建模

    4.1 用例图

    #mermaid-svg-hKros0GCZfAgwYk4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-hKros0GCZfAgwYk4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-hKros0GCZfAgwYk4 .error-icon{fill:#552222;}#mermaid-svg-hKros0GCZfAgwYk4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-hKros0GCZfAgwYk4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-hKros0GCZfAgwYk4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-hKros0GCZfAgwYk4 .marker.cross{stroke:#333333;}#mermaid-svg-hKros0GCZfAgwYk4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-hKros0GCZfAgwYk4 p{margin:0;}#mermaid-svg-hKros0GCZfAgwYk4 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-hKros0GCZfAgwYk4 .cluster-label text{fill:#333;}#mermaid-svg-hKros0GCZfAgwYk4 .cluster-label span{color:#333;}#mermaid-svg-hKros0GCZfAgwYk4 .cluster-label span p{background-color:transparent;}#mermaid-svg-hKros0GCZfAgwYk4 .label text,#mermaid-svg-hKros0GCZfAgwYk4 span{fill:#333;color:#333;}#mermaid-svg-hKros0GCZfAgwYk4 .node rect,#mermaid-svg-hKros0GCZfAgwYk4 .node circle,#mermaid-svg-hKros0GCZfAgwYk4 .node ellipse,#mermaid-svg-hKros0GCZfAgwYk4 .node polygon,#mermaid-svg-hKros0GCZfAgwYk4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-hKros0GCZfAgwYk4 .rough-node .label text,#mermaid-svg-hKros0GCZfAgwYk4 .node .label text,#mermaid-svg-hKros0GCZfAgwYk4 .image-shape .label,#mermaid-svg-hKros0GCZfAgwYk4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-hKros0GCZfAgwYk4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-hKros0GCZfAgwYk4 .rough-node .label,#mermaid-svg-hKros0GCZfAgwYk4 .node .label,#mermaid-svg-hKros0GCZfAgwYk4 .image-shape .label,#mermaid-svg-hKros0GCZfAgwYk4 .icon-shape .label{text-align:center;}#mermaid-svg-hKros0GCZfAgwYk4 .node.clickable{cursor:pointer;}#mermaid-svg-hKros0GCZfAgwYk4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-hKros0GCZfAgwYk4 .arrowheadPath{fill:#333333;}#mermaid-svg-hKros0GCZfAgwYk4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-hKros0GCZfAgwYk4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-hKros0GCZfAgwYk4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hKros0GCZfAgwYk4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-hKros0GCZfAgwYk4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hKros0GCZfAgwYk4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-hKros0GCZfAgwYk4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-hKros0GCZfAgwYk4 .cluster text{fill:#333;}#mermaid-svg-hKros0GCZfAgwYk4 .cluster span{color:#333;}#mermaid-svg-hKros0GCZfAgwYk4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-hKros0GCZfAgwYk4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-hKros0GCZfAgwYk4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-hKros0GCZfAgwYk4 .icon-shape,#mermaid-svg-hKros0GCZfAgwYk4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-hKros0GCZfAgwYk4 .icon-shape p,#mermaid-svg-hKros0GCZfAgwYk4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-hKros0GCZfAgwYk4 .icon-shape .label rect,#mermaid-svg-hKros0GCZfAgwYk4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-hKros0GCZfAgwYk4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-hKros0GCZfAgwYk4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-hKros0GCZfAgwYk4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    用户

    发出声音

    方向识别系统

    检测声音方向

    通过LED指示方向

    串口上报方向数据

    上位机

    4.2 类图(固件抽象)

    #mermaid-svg-eBf5KAPgbBSjo159{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-eBf5KAPgbBSjo159 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-eBf5KAPgbBSjo159 .error-icon{fill:#552222;}#mermaid-svg-eBf5KAPgbBSjo159 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-eBf5KAPgbBSjo159 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-eBf5KAPgbBSjo159 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-eBf5KAPgbBSjo159 .marker.cross{stroke:#333333;}#mermaid-svg-eBf5KAPgbBSjo159 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-eBf5KAPgbBSjo159 p{margin:0;}#mermaid-svg-eBf5KAPgbBSjo159 g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-eBf5KAPgbBSjo159 g.classGroup text .title{font-weight:bolder;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster-label text{fill:#333;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster-label span{color:#333;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster-label span p{background-color:transparent;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster text{fill:#333;}#mermaid-svg-eBf5KAPgbBSjo159 .cluster span{color:#333;}#mermaid-svg-eBf5KAPgbBSjo159 .nodeLabel,#mermaid-svg-eBf5KAPgbBSjo159 .edgeLabel{color:#131300;}#mermaid-svg-eBf5KAPgbBSjo159 .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-eBf5KAPgbBSjo159 .label text{fill:#131300;}#mermaid-svg-eBf5KAPgbBSjo159 .labelBkg{background:#ECECFF;}#mermaid-svg-eBf5KAPgbBSjo159 .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-eBf5KAPgbBSjo159 .classTitle{font-weight:bolder;}#mermaid-svg-eBf5KAPgbBSjo159 .node rect,#mermaid-svg-eBf5KAPgbBSjo159 .node circle,#mermaid-svg-eBf5KAPgbBSjo159 .node ellipse,#mermaid-svg-eBf5KAPgbBSjo159 .node polygon,#mermaid-svg-eBf5KAPgbBSjo159 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-eBf5KAPgbBSjo159 .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 g.clickable{cursor:pointer;}#mermaid-svg-eBf5KAPgbBSjo159 g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-eBf5KAPgbBSjo159 g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-eBf5KAPgbBSjo159 .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-eBf5KAPgbBSjo159 .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-eBf5KAPgbBSjo159 .dashed-line{stroke-dasharray:3;}#mermaid-svg-eBf5KAPgbBSjo159 .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-eBf5KAPgbBSjo159 #compositionStart,#mermaid-svg-eBf5KAPgbBSjo159 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #compositionEnd,#mermaid-svg-eBf5KAPgbBSjo159 .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #dependencyStart,#mermaid-svg-eBf5KAPgbBSjo159 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #dependencyStart,#mermaid-svg-eBf5KAPgbBSjo159 .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #extensionStart,#mermaid-svg-eBf5KAPgbBSjo159 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #extensionEnd,#mermaid-svg-eBf5KAPgbBSjo159 .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #aggregationStart,#mermaid-svg-eBf5KAPgbBSjo159 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #aggregationEnd,#mermaid-svg-eBf5KAPgbBSjo159 .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #lollipopStart,#mermaid-svg-eBf5KAPgbBSjo159 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 #lollipopEnd,#mermaid-svg-eBf5KAPgbBSjo159 .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-eBf5KAPgbBSjo159 .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-eBf5KAPgbBSjo159 .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-eBf5KAPgbBSjo159 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-eBf5KAPgbBSjo159 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-eBf5KAPgbBSjo159 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    uses

    DirectionDetector

    – MicChannel channels[4]

    – IIRFilter filter

    – int currentDirection

    + update()

    + getDirection() : int

    MicChannel

    – ADC_HandleTypeDef* hadc

    – float buffer[1024]

    + collect()

    + getRMS() : float

    IIRFilter

    – float b[3], a[3]

    + apply(input) : float

    LEDIndicator

    + showDirection(int dir)

    + clear()

    4.3 序列图:一次方向检测

    UARTLEDIndicatorDirectionDetector4xMicChannel定时器UARTLEDIndicatorDirectionDetector4xMicChannel定时器#mermaid-svg-PmEIMqzaePbX8du8{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PmEIMqzaePbX8du8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PmEIMqzaePbX8du8 .error-icon{fill:#552222;}#mermaid-svg-PmEIMqzaePbX8du8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PmEIMqzaePbX8du8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PmEIMqzaePbX8du8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PmEIMqzaePbX8du8 .marker.cross{stroke:#333333;}#mermaid-svg-PmEIMqzaePbX8du8 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PmEIMqzaePbX8du8 p{margin:0;}#mermaid-svg-PmEIMqzaePbX8du8 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PmEIMqzaePbX8du8 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-PmEIMqzaePbX8du8 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PmEIMqzaePbX8du8 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-PmEIMqzaePbX8du8 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-PmEIMqzaePbX8du8 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-PmEIMqzaePbX8du8 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-PmEIMqzaePbX8du8 .sequenceNumber{fill:white;}#mermaid-svg-PmEIMqzaePbX8du8 #sequencenumber{fill:#333;}#mermaid-svg-PmEIMqzaePbX8du8 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-PmEIMqzaePbX8du8 .messageText{fill:#333;stroke:none;}#mermaid-svg-PmEIMqzaePbX8du8 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PmEIMqzaePbX8du8 .labelText,#mermaid-svg-PmEIMqzaePbX8du8 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-PmEIMqzaePbX8du8 .loopText,#mermaid-svg-PmEIMqzaePbX8du8 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-PmEIMqzaePbX8du8 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-PmEIMqzaePbX8du8 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-PmEIMqzaePbX8du8 .noteText,#mermaid-svg-PmEIMqzaePbX8du8 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-PmEIMqzaePbX8du8 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PmEIMqzaePbX8du8 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PmEIMqzaePbX8du8 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-PmEIMqzaePbX8du8 .actorPopupMenu{position:absolute;}#mermaid-svg-PmEIMqzaePbX8du8 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-PmEIMqzaePbX8du8 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-PmEIMqzaePbX8du8 .actor-man circle,#mermaid-svg-PmEIMqzaePbX8du8 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-PmEIMqzaePbX8du8 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}触发同步采样DMA 接收1024点通知数据就绪获取4通道RMS带通滤波+比较能量点亮对应方向LED串口输出方向码

    4.4 方向状态机

    #mermaid-svg-TpT1TUox2VzgSSol{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TpT1TUox2VzgSSol .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TpT1TUox2VzgSSol .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TpT1TUox2VzgSSol .error-icon{fill:#552222;}#mermaid-svg-TpT1TUox2VzgSSol .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TpT1TUox2VzgSSol .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TpT1TUox2VzgSSol .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TpT1TUox2VzgSSol .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TpT1TUox2VzgSSol .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TpT1TUox2VzgSSol .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TpT1TUox2VzgSSol .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TpT1TUox2VzgSSol .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TpT1TUox2VzgSSol .marker.cross{stroke:#333333;}#mermaid-svg-TpT1TUox2VzgSSol svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TpT1TUox2VzgSSol p{margin:0;}#mermaid-svg-TpT1TUox2VzgSSol defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-TpT1TUox2VzgSSol g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-TpT1TUox2VzgSSol g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-TpT1TUox2VzgSSol g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-TpT1TUox2VzgSSol g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-TpT1TUox2VzgSSol g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-TpT1TUox2VzgSSol .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-TpT1TUox2VzgSSol .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-TpT1TUox2VzgSSol .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-TpT1TUox2VzgSSol .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-TpT1TUox2VzgSSol .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-TpT1TUox2VzgSSol .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-TpT1TUox2VzgSSol .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-TpT1TUox2VzgSSol .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TpT1TUox2VzgSSol .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TpT1TUox2VzgSSol .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TpT1TUox2VzgSSol .edgeLabel .label text{fill:#333;}#mermaid-svg-TpT1TUox2VzgSSol .label div .edgeLabel{color:#333;}#mermaid-svg-TpT1TUox2VzgSSol .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-TpT1TUox2VzgSSol .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-TpT1TUox2VzgSSol .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-TpT1TUox2VzgSSol .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-TpT1TUox2VzgSSol .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-TpT1TUox2VzgSSol .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TpT1TUox2VzgSSol .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TpT1TUox2VzgSSol #statediagram-barbEnd{fill:#333333;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TpT1TUox2VzgSSol .cluster-label,#mermaid-svg-TpT1TUox2VzgSSol .nodeLabel{color:#131300;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-TpT1TUox2VzgSSol .note-edge{stroke-dasharray:5;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-note text{fill:black;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram-note .nodeLabel{color:black;}#mermaid-svg-TpT1TUox2VzgSSol .statediagram .edgeLabel{color:red;}#mermaid-svg-TpT1TUox2VzgSSol #dependencyStart,#mermaid-svg-TpT1TUox2VzgSSol #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-TpT1TUox2VzgSSol .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TpT1TUox2VzgSSol :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    通道3能量最大

    通道2能量最大

    通道1能量最大

    通道0能量最大

    能量低于阈值

    Silence

    Dir_LeftRear

    Dir_LeftFront

    Dir_RightFront

    Dir_Right


    5. 核心机理深度解析

    5.1 为什么用心形麦克风?

    心形指向 = 全向 + 双向,对正面灵敏,对侧面衰减 6dB,对背面衰减 20dB 以上。四只麦克风按特定角度安装,自然形成四个重叠较少的敏感扇区。即使不做复杂阵列处理,仅凭幅度大小即可区分方向,极大降低算法复杂度。

    安装示意图:

    背面 (设备后方)
    麦克3(135°) 麦克0(0°) 正前
    \\ /
    \\ 设备 /
    \\ /
    \\ /
    \\ /
    麦克2(90°) 麦克1(45°)
    左侧 左前/右前

    扇区分配:

    • 通道 0(0°):覆盖 -22.5° ~ 22.5°(正前偏右)
    • 通道 1(45°):覆盖 22.5° ~ 67.5°(右前)
    • 通道 2(90°):覆盖 67.5° ~ 112.5°(右侧)
    • 通道 3(135°):覆盖 112.5° ~ 180°(右后/左后)

    如果需要严格对称 180°,可调整安装角度为 0°, 60°, 120°, 180°,按需修改。

    5.2 能量比较与抗干扰

    • 语音频段滤波:滤除 300Hz 以下的空调噪声、风声,滤除 3400Hz 以上的电路高频噪声。
    • 噪声基底自适应:开机后采集 2 秒静音数据,取平均 RMS 作为阈值基准。
    • 连续确认:防止瞬间冲击声(如关门)引起误触发。
    • AGC 关闭:MAX9814 自动增益控制关闭,以免压缩幅度差异。

    5.3 ADC 同步采样

    STM32F407 有 3 个独立 ADC,可配置为 三重同步模式。实际 4 个通道可分配为:

    • ADC1 的 IN0、IN1
    • ADC2 的 IN2、IN3
      启动后由同一触发信号同步开始转换,DMA 同时搬运两个 ADC 的结果。这样各通道采样时刻相差在纳秒级,能量比较不受相位影响。

    6. 项目文件结构组织

    sound_direction_4way/
    ├── hardware/
    │ ├── mic_amp_sch.pdf # 4路麦克风放大原理图
    │ ├── mainboard.PcbDoc # PCB文件
    │ └── BOM.xlsx
    ├── firmware/
    │ ├── Core/
    │ │ ├── Inc/
    │ │ │ ├── adc_sync.h
    │ │ │ ├── iir_filter.h
    │ │ │ ├── direction_detect.h
    │ │ │ └── led_uart.h
    │ │ └── Src/
    │ │ ├── main.c
    │ │ ├── adc_sync.c
    │ │ ├── iir_filter.c
    │ │ ├── direction_detect.c
    │ │ └── led_uart.c
    │ ├── Drivers/ # HAL库
    │ └── MDK-ARM/ # Keil工程
    ├── docs/
    │ ├── system_design.md
    │ ├── uml/ # UML源文件
    │ └── calibration_guide.md
    ├── test/
    │ └── pc_plot.py # 串口能量显示工具
    └── README.md


    7. 开发方法与步骤(约2周)

    阶段任务时间
    1 硬件搭建:焊接4路麦克风+放大模块,连接STM32开发板,验证波形 2天
    2 驱动开发:配置ADC同步采样、DMA,实现实时采集,串口打印原始波形 2天
    3 滤波与能量算法:编写IIR带通滤波器,计算RMS,观察四通道能量分布 2天
    4 方向判定逻辑:加入阈值、滞后、LED指示,多角度实测 2天
    5 优化与文档:抗噪声测试,参数微调,编写设计文档及使用说明 2天

    校准步骤:

  • 将设备置于静音环境中,运行静音采集代码,记录四通道噪声RMS。
  • 在正前方(0°)说话,调整 MAX9814 增益使通道 0 能量明显高于其他通道,同时不削波。
  • 在其他 3 个方向重复,确保交叉最少。

  • 8. 总结

    本方案利用 4 路心形指向麦克风的物理方向性,结合 STM32F407 同步采样与简单能量比较算法,在极低成本下实现了 180° 四向声音识别。

    无需复杂阵列处理,软件逻辑清晰,开发周期短,非常适合智能家居、语音控制面板等对精度要求不高的场景。

    全套设计文档和 UML 模型为快速工程化提供了完整支撑。

    赞(0)
    未经允许不得转载:171主机测评 » 声音方向识别系统(180° 四向)设计方案
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址