写了两周 GCC-PHAT,跑出来的角度还不如人家一个模组上电瞬间给的值准。我心态有点崩,但我服了。
一、先说说我这两周在干嘛
项目要做一个声源跟随机器人。需求一句话:听到人声,转过去看人。
我,一个嵌入式工程师,天真地以为这是个小活。不就是双麦克风算个到达时间差嘛,大学信号处理学过。
然后我就掉坑里了。
第一周,我以为的路线:
麦克风采样 → FFT → 广义互相关(GCC-PHAT) → 峰值检测 → 时延 → 反三角算出角度
实际踩的坑:
- 麦克风标定:两颗麦克风灵敏度不一致,相位响应不一样,出来的时延全是偏的。先得做幅度校准、相位校准——对,还有温度影响。
- 采样同步:两颗麦必须同时刻采样,ADC 驱动稍微错几个时钟周期,时延就废了。
- 采样率:双麦间距 4cm,声速 343m/s,最大到达时间差才 116μs。16kHz 采样下采样周期 62.5μs,整个量程不到 2 个采样点,分辨率差到没法看。得上 48kHz 甚至 96kHz,还得做插值。
- GCC-PHAT 本身:互相关函数峰值找不准,多径反射一来,峰值直接指错方向。
- 环境噪音:车间里风扇声、机器声,全部叠加进相关性里,角度疯狂抖动。
两周后,我的"成果"是:安静房间、1 米距离、正对麦克风时,角度误差 ±20°,还时不时抽风跳到 180°。
二、同事甩给我一个模组:"你插上电试试"
同事看不下去了,扔过来一块小板子,说:"别写了,试试这个 AR1106,插上电就能出角度。"
我第一反应是:吹吧。
然后我看了眼规格书:
- 定位范围:正面 180°
- 定位精度:±10°
- 拾音距离:5 米
- 输出:串口 9600,16 进制角度值,一个字节
- 舵机:内置 SG90 驱动,PWM 脚直连
行,那就测。我找了块面包板,接了 5V、GND,串口 TX 拉到 USB 转 TTL,打开串口助手。全程没写一行代码。
按下复位键,串口安静。
我对着模组喊了一声"小智"。
5A
我查了下换算——0x5A = 90。它报的是 90°。我人正好站在模组正前方。
当时我后背就有点发凉了。
三、实测:±10° 到底是吹的还是真的
我不信邪,拿了个量角器,在模组正前方按角度摆了点,每个点喊一遍命令词,记录串口输出。
实际方位 | 串口输出 | 解码角度 | 误差 |
正前方 90° |
| 90° | 0° |
右前 135° |
| 136° | +1° |
左前 45° |
| 44° | -1° |
右 160° |
| 160° | 0° |
左 15° |
| 13° | -2° |
(注:0x88=136,0x2C=44,0xA0=160,0x0D=13)
近距误差在 ±2° 以内,拉远到 4-5 米,误差会放大到 ±10° 的边界,但从没出现过指向 180° 那种离谱的跳变。
我又做了个恶趣味测试:旁边放个音箱循环放音乐,人站在另一边喊命令词——模组只认命令词,音乐放着的时候串口一个字节都不吐。这防干扰,比我写的 200 行滤波代码管用多了。
四、把舵机接上,20 行代码让机器人"转头"
规格书说内置 SG90 驱动,我顺手把舵机信号线接到了 PWM 脚上——舵机自己就动了,跟着我的喊声转向,根本没经过我的程序。
想自己控也行,串口模式几十行代码:
#include <SoftwareSerial.h> #include <Servo.h> SoftwareSerial ar1106(10, 11); // RX, TX Servo head; void setup() { Serial.begin(9600); ar1106.begin(9600); head.attach(9); head.write(90); } void loop() { if (ar1106.available()) { uint8_t angle = ar1106.read(); // 一个字节就是角度,0x00~0xB4 angle = constrain(angle, 0, 180); head.write(angle); // 舵机转向声源 Serial.print("声源角度: "); Serial.println(angle); }从"接到任务"到"机器人会转头",我用 AR1106 只花了一个下午。其中半小时还是在等舵机快递。
五、冷静下来,说说 DSP 到底该不该自己写
吐槽归吐槽,我也得给自己两个星期一个交代。理清楚之后,结论其实很清晰:
什么情况必须自己写 DSP:
- 需要区分多个声源(比如会议场景分离几个人声);
- 需要1°~2° 级的高精度指向(远程定向拾音);
- 需要自定义声学处理链路(波束成形 + 降噪 + 识别一体);
- 成本敏感到连一颗模组的钱都省不下来,且团队有人能啃算法。
什么情况直接用 AR1106:
- 需求就是"声音从哪来,头转向哪";
- 180° 范围、5 米内、±10° 精度,恰好够用;
- 想要确定性:只认命令词,不误触发,现场演示不翻车;
- 想快点交付:即插即用,串口一个字节出角度。
我那个项目,最后用了 AR1106。自研版本被丢进 git 历史,就当交学费了。
六、最后说点掏心窝的
技术圈有个毛病,总觉得"自研"才显得有水平。但工程师的第一职责是交付,不是炫技。当现成方案 5 分钟出结果、自研要 5 个星期还不一定稳的时候,选现成方案不是偷懒,是清醒。
"还要写 DSP 算法?" —— 对,真不用。这玩意儿插上电,喊一声,角度就出来了。
本文实测基于 AR1106 声源定位模组规格书。关键参数:180° 定位范围 / ±10° 精度 / 5 米拾音 / 串口 9600 输出 16 进制角度(0x5A=90°)/ 内置 SG90 舵机驱动 / 仅响应预设命令词。详细咨询请私信公众号后台,期待与您交流。