简介:这份资料围绕声音传感器原理图与应用说明展开,面向电子设计初学者、硬件工程师及需要快速选型与电路参考的开发者,帮助理解声电转换原理、常见麦克风类型及典型应用场景。压缩包共22个文件,约583KB,包含6个txt说明、4个doc技术文档、4个db数据文件,以及jpg、bmp图片、htm原理图页面和xml配置等,兼顾电路图查阅、产品使用说明与设计选型参考。已有633人学习下载。内容围绕电容式、压电式与MEMS麦克风的工作机制,延伸到语音识别、噪声监测、安防、医疗与工业监测等应用,并整理频率响应、灵敏度、噪声性能、动态范围及供电兼容等选型要点。读者可据此对照原理图与说明文档,快速建立声音传感电路的整体认识,为方案评估、器件选型和产品设计提供可落地的参考。
1. 声音传感器原理图:从一颗驻极体麦克风到一根中断线
三块五一个的声音传感器模块,四根针脚,接上电就能吐出高低电平。新手第一次拿它做拍手开关,十有八九会遇到同一个场面:安静房间里 DO 自己抖个不停,真拍手它反倒没反应。问题基本不出在模块,而出在没人认真读过那张原理图。声音传感器的原理图拆开看只有三级——驻极体麦克风的偏置、一级放大、一级比较器,元件加起来不到二十个;但每一级的工作点、增益、回差怎么定,直接决定它是能分辨一段说话,还是只认得一声脆响。这篇按原理图逐级拆,再落到应用说明:3.3V 单电源下怎么自己画一版稳定的电路,阈值怎么标定,怎么把开关量升级成能互相比较的声压读数。
2. 拆原理图:驻极体偏置、放大、比较器三级里,每一级在决定什么
一张声音传感器原理图看着元件不少,真正干活的只有三件事:把声压变成电压、把几毫伏的电压抬到伏级、再把模拟波形切成一刀干净的数字沿。这三件事分别归偏置电路、放大级、比较器管。搞清楚每一级的输入输出量级,改参数时才知道自己动的是哪颗螺丝,而不是把电位器来回拧一百遍碰运气。
2.1 从空气振动到 MCU 引脚:四级链路各自的电压量级
驻极体麦克风的内核是一个电容:一层驻极体振膜加一块背极板,声压推动振膜改变极板间距,电容跟着变,在电荷近似守恒的条件下端电压就变了。麻烦在于这个电容只有几十皮法,源阻抗高到 GΩ 量级,直接往外接任何负载都会被吃干净。所以商用驻极体话筒里都封了一颗结型场效应管做阻抗变换,三根引脚分别是漏极、源极和外壳地。
最常见的接法是源极接地、漏极经一只偏置电阻 Rd 接电源,信号从漏极取出。Rd 既是负载也是限流,它决定了管内场效应管的工作电流。取小了电流大、灵敏度下降;取大了漏极电压被顶到接近电源,波形下半周先削掉。经验上让漏极静态电压落在电源的 1/2 到 2/3 之间最稳,5V 系统常用 10k,3.3V 系统我一般取 2.2k~4.7k。
麦克风出来的信号幅度比多数人想的小。正常说话、距离 10cm,漏极上大约只有 5~30mVpp;小声说话可能只有 2mVpp;而拍手、关门这类瞬态能冲到 100mVpp 以上。这个跨度就是后面所有麻烦的根源——增益按说话设,拍手就削顶;增益按拍手设,说话永远触发不了。
| 节点 | 安静室内 | 正常说话 10cm | 拍手 30cm |
|---|---|---|---|
| 麦克风漏极 | 0.5~1mVpp | 5~30mVpp | 50~150mVpp |
| 放大级输出(增益 100) | 10~50mVpp,以底噪为主 | 0.5~2.5Vpp | 削顶成方波 |
| 比较器同相端 | 同上 | 同上 | 同上 |
隔直电容紧跟在漏极后面。它和放大级的输入阻抗构成一个高通,截止频率 f = 1/(2πRC)。输入阻抗 10k 时配 0.1µF 得到 159Hz,配 1µF 得到 15.9Hz。语音基频最低到 100Hz 左右,取 0.47~1µF 比较稳妥;取 0.01µF 那种,男声的低频成分被砍掉一大截,表现出来就是“女声能触发、男声不触发”这种看着很玄学的现象。
放大级通常是同相放大,增益 A = 1 + Rf/Rg。业界模块常用 100k/1k,也就是 101 倍,把 10mVpp 抬到 1Vpp 上下。单电源供电时运放不能处理负半周,所以放大级的同相端必须抬到 VCC/2 的中点,靠两只等值电阻分压再加一只电容旁路到地。这个中点如果脏,后面所有判决都是错的。
比较器负责最后一刀。放大后的信号进同相端,电位器分压出来的参考电压进反相端,输出开漏,需要外接上拉电阻。信号高于参考,输出被拉低(开漏管导通);信号低于参考,输出被上拉拉高。这也是为什么很多人发现自己模块“安静时是高电平、拍手变低电平”,跟直觉相反,其实是拓扑决定的,不是模块坏了。
2.2 三种常见声音传感器原理图的取舍
市面上能买到的声音传感器板子,原理图基本落在三种形态里,选型前先想清楚自己要做的是“判有无”还是“量大小”。
第一种是只有 AO 的裸板:麦克风、偏置电阻、隔直电容,输出直接引出来。它最便宜,也不会引入放大级带来的失真,但输出只有几毫伏到几十毫伏,必须外接放大,或者用带 PGA 的高分辨率 ADC 去接。做频谱分析、做声纹特征提取这类要保波形原样的场景,我优先选它;缺点是长线一拉就吃噪声,杜邦线超过 20cm 就开始飘。
第二种是比较器型四针模块,也是最常见的那种:麦克风 + 偏置 + 一级运放 + 电位器 + 比较器 + 开漏输出 + 一颗指示灯。DO 给开关量,AO 一般接在运放输出上。它的好处是 MCU 一个中断脚就够用,缺点是几乎没有回差、增益写死、阈值靠一只单圈电位器,重复性差——你这次拧到的位置,下次拆装就找不回来了。
第三种是带自动增益控制的麦克风放大模块:运放加 AGC,输出是带中点偏置的模拟信号,可以直接进 ADC。动态范围大,拍手不容易削顶;但 AGC 的启动和释放时间会把短促声音的幅度判低,做瞬态检测时要留意这个边界。
| 形态 | 典型增益 | 输出 | 适合 | 主要短板 |
|---|---|---|---|---|
| 裸麦克风偏置 | 1 | 几 mV~几十 mV | 频谱、波形分析 | 幅度太小,易受干扰 |
| 比较器型模块 | 约 100 | DO + AO | 有无判断、触发 | 无回差,阈值不可复现 |
| AGC 放大模块 | 自动 | 中点偏置模拟量 | 声压分级、录音前端 | 瞬态被压,需软件补偿 |
选型这件事上我的判断很直接:做产品就自己画第二类的改进版(加回差、固定阈值),做实验先用第三类省事,做算法验证用第一类保真。三种混着用最容易翻车,因为你对信号幅度的直觉会一直是错的。
2.3 四个算式定元件:偏置电阻、耦合电容、增益、回差
参数不用试出来,四个式子就够。
偏置电阻按工作点算:Rd = (VCC − Vd) / Id,Vd 取电源的一半到三分之二,Id 查话筒规格常见 0.3~0.5mA。3.3V 下 (3.3 − 2.0)/0.5mA = 2.6k,取标称 2.2k 或 3.3k 都行。
耦合电容按高通算:C ≥ 1/(2π × R_in × f_c)。要保住 150Hz 以上、输入阻抗 10k,得 C ≥ 0.1µF,实际取 0.47µF 留三倍余量。
增益按目标摆幅算:A = Vout_pp / Vin_pp。想把 20mVpp 的说话声做到 1.5Vpp,A = 75;考虑 3.3V 单电源下中点偏置只有 ±1.6V 的余量,A 取 80~120 之间比较合适,再大就只能听拍手了。带宽顺手核一下:GBW/A 要大于 4kHz,通用运放 GBW 在 1MHz 量级,100 倍时剩 10kHz,够用但不宽裕。
回差按正反馈分压算:ΔV ≈ Vswing × Rs / (Rs + Rh)。Rs 是信号源到同相端的串联电阻,Rh 是从输出接回同相端的反馈电阻。3.3V 摆幅、Rs = 10k、Rh = 1M,回差约 33mV;底噪峰峰值如果是 10mV,这个量刚好压住抖动而不会漏掉轻声音。
| 参数 | 算式 | 3.3V 下取值 | 决定了什么 |
|---|---|---|---|
| Rd | (VCC − Vd)/Id | 2.2k~4.7k | 麦克风工作点、最大不失真摆幅 |
| C1 | 1/(2πR_in f_c) | 0.47µF | 低频截止,男女声是否一致 |
| Rf/Rg | A = 1 + Rf/Rg | 100k / 1k | 灵敏度与削顶边界 |
| Rh | ΔV ≈ Vswing·Rs/(Rs+Rh) | 1M | 边沿抖动与误触发率 |
注意:加了正反馈之后,比较器的实际阈值会往信号方向偏移大约半个回差,电位器要重新调一遍,别拿旧位置直接上电。
3. 自己画一版:3.3V 单电源声音传感器的四个设计动作
照着现成模块抄一版能跑,但要跑得稳,有四个动作必须自己重做:中点偏置、放大级增益与带宽、比较器回差、输出接口。这一章按画板的顺序走一遍,每一步给取值和理由,元件都是常用件,不涉及难买的型号。
3.1 先把中点偏置做干净:分压、去耦与地线怎么走
单电源下所有模拟信号都骑在一个直流电平上,这个电平就是中点。中点脏,等于给整条链路加了一个随电源波动的共模干扰,比较器会跟着电源纹波一起跳。
做法是两只 10k 电阻从 VCC 分压到地,中点节点并一只 10µF 钽电容或陶瓷电容再到地,再并一只 100nF 管高频。10k/10k 分压的输出阻抗是 5k,对运放同相端来说偏高,所以中点不要直接当参考源用,最好再经一级运放做电压跟随器缓冲。省掉跟随器也能跑,但电位器一动、负载一变,中点就跟着漂,这是很多“调好了过两天又不灵”的根源。
地线走法上,模拟部分(麦克风、偏置、运放)和数字部分(比较器输出、MCU)各走各的地,最后在电源入口处单点汇合。麦克风的偏置走线尽量短,远离任何时钟线或 PWM 线;比较器输出那条线不要和麦克风输入并排走,否则输出跳变会耦合回输入,形成自激。
供电入口放 10µF + 100nF 两颗,如果有电机、继电器这类负载共电源,再串一只 10Ω 电阻加 100µF 电容做一级 RC 滤波,截止频率压在 160Hz 以下。这一步在电池供电时看不出差别,一上电机就知道值不值。
3.2 放大级:同相增益、带宽核算与耦合电容选值
放大级用同相结构,输入阻抗高,不会把麦克风那点信号吃掉。反相端到地接 Rg = 1k,反馈电阻 Rf = 100k,增益 101;如果希望增益可调,把 Rg 换成 1k 固定电阻串一只 10k 电位器,增益范围就是 11~101,调的时候从小往大拧,别一上来就拉满。
同相端接中点,隔直电容 C1 = 0.47µF 串在麦克风漏极和同相端之间。这里有个容易忽略的细节:C1 和中点分压电阻、运放输入偏置电流共同决定上电建立时间,0.47µF 配 5k 的时间常数约 2.4ms,上电后给 50ms 稳定时间足够;若把 C1 加到 10µF 想保低频,建立时间会拉到 50ms 以上,加上电延时别省。
带宽核算不能只看增益。通用运放在增益 100 时闭环带宽只剩 10kHz 左右,语音够用,但如果你要做 8kHz 采样的频谱分析,17kHz 的奈奎斯特频率已经超出运放带宽,高频段幅度会被压。这种场景把增益降到 30~50,剩下的增益交给 ADC 前的第二级或者软件。
输出串一只 1k 电阻再进比较器,一是限流保护,二是和比较器输入电容构成低通,顺手滤掉一点高频毛刺。这只电阻同时也决定了后面回差计算里的 Rs,别随手改。
3.3 比较器加迟滞:把抖动的边沿变成一根干净的中断线
没有回差的比较器就是个噪声放大器。信号爬到阈值附近时,几毫伏的底噪就能让它来回翻几十次,MCU 收到一串中断,表现出来就是“一次拍手记了十几次”。
加回差的办法是从输出接一只电阻 Rh 回同相端。开漏输出配上拉电阻,输出在 0 和 3.3V 之间摆,Rh 把这部分摆幅按 Rs/(Rs+Rh) 的比例正反馈到同相端。Rs 是 3.2 节里那只 1k 串联电阻加上前级输出阻抗,实际按 10k 估(如果你把串联电阻改成 10k,就按 10k 算),Rh 取 1M,回差约 33mV。
阈值调节用电位器:VCC 经 10k 电位器分压,滑臂接反相端,两端各串一只 1k 限流,防止拧到头直接把电源短路到地。调的时候用示波器双通道,一路看放大输出,一路看比较器输出,慢慢拧到正好能压住底噪、又不漏掉目标声音的位置,然后把电位器换成两个固定电阻——这是我最推荐的一步,模块上的单圈电位器是整块板子最不可复现的元件。
比较器输出是开漏,上拉电阻取 4.7k~10k,上拉到 MCU 的 IO 电压,不要上拉到 5V 再进 3.3V 的引脚。输出端串一只 100Ω 电阻,配合 MCU 内部上拉或外部 100nF 到地,能压掉长线带来的振铃。
3.4 输出与接口:开漏上拉、限流电阻与布板三条规矩
接口这部分经常被当成小事,实际翻车不少。DO 是开漏,天然适合做电平转换,但上拉电阻的位置很关键:上拉要放在 MCU 一侧而不是模块一侧,这样长线走的是低阻的灌电流路径,抗干扰好一些。上拉阻值太小功耗上去了,太大上升沿变慢,4.7k 是个折中。
AO 输出如果直接进 ADC,中间串 1k 加 100nF 到地做一级 RC,截止 1.6kHz,压掉开关电源的高频噪声;但如果你要做频谱,把它去掉,改用软件滤波。
布板上三条规矩:麦克风开孔正对板边、不要被外壳闷住;麦克风底下铺地但要留隔离槽,别把数字地噪声引到振膜下面;比较器输出线远离麦克风偏置线至少 3 倍线宽。
| 元件 | 取值 | 作用 |
|---|---|---|
| Rd | 2.2k | 麦克风偏置,决定工作点 |
| C1 | 0.47µF | 隔直,决定低频截止 |
| Rf / Rg | 100k / 1k | 增益 101 |
| 中点分压 | 10k / 10k + 10µF | 单电源中点 |
| 比较器上拉 | 4.7k | 开漏输出电平 |
| Rh | 1M | 回差约 33mV |
4. 打样之后的验证:静态点、底噪、阈值三组数怎么量出来
板子回来别急着写代码,先拿万用表和示波器把三组数量出来。这三组数不对,后面所有软件调试都是在给硬件擦屁股,越调越乱。
4.1 上电三步测量:静态工作点、底噪、最大不削顶输出
第一步量静态工作点。不接任何声源,安静房间,万用表直流挡依次量:电源 3.3V ± 5%;中点节点 1.65V ± 0.1V;运放输出 1.65V ± 0.05V;麦克风漏极 1.0~2.2V。四个数有一个偏出范围,先查分压电阻和偏置电阻,不要往下走。漏极电压接近 3.3V 说明 Rd 太大或话筒没插好,接近 0 说明短路。
第二步量底噪。示波器 AC 耦合、20mV/div、时基 5ms,探头接地弹簧别用长地线夹。安静房间下读放大级输出的峰峰值,要求小于 20mVpp;如果看到 50Hz 或 100Hz 的规则正弦,那是电源纹波,回去查去耦和地线;如果是一片毛刺,多半是增益过高把前级噪声放大了。
第三步量最大不削顶输出。在 10cm 处放一段稳定音源(手机放 1kHz 正弦就行),从小到大加音量,看运放输出的峰峰值,直到波形顶部或底部开始变平,记录削顶前的最大幅度。这个值除以增益,就是你能处理的最大输入,也就是动态范围的上限。增益 101、中点 1.65V 的话,理论最大输出约 3.0Vpp,实际留 20% 余量按 2.4Vpp 算,对应输入 24mVpp——正好卡在正常说话的上沿,拍手必然削顶。知道这个数,你就知道该不该降增益。
4.2 用 8kHz 采样跑一次 RMS 与 dBFS 计算
模拟链路调好之后,把 AO 接进 ADC,用 8kHz 采样、50ms 窗口算一次 RMS。窗口长度不是随便定的:50ms 对应 20Hz 的频率分辨率,语音基频在 100Hz 以上,够用;想看清 50Hz 工频干扰就得把窗口拉到 200ms 以上,但那样瞬态响应会变钝。
#define FS 8000 /* 采样率 8kHz,语音够用 */ #define WIN (FS / 20) /* 50ms 窗口 = 400 点 */ #define ADC_FS 4096.0f /* 12 位 ADC 满量程 */ static int16_t buf[WIN]; float window_dbfs(void) { int i; int32_t sum = 0; int16_t vmin = 32767, vmax = -32768; for (i = 0; i < WIN; i++) { buf[i] = adc_read(); /* 读一次转换结果,0~4095 */ if (buf[i] < vmin) vmin = buf[i]; if (buf[i] > vmax) vmax = buf[i]; } /* 用窗内 (max+min)/2 估中点,避免直流漂移把 RMS 抬起来 */ int32_t mid = ((int32_t)vmax + vmin) / 2; for (i = 0; i < WIN; i++) { int32_t d = buf[i] - mid; /* 去直流 */ sum += d * d; } float rms = sqrtf((float)sum / WIN); /* 以 ADC 满量程为 0dB 参考,工程上只要求前后一致 */ return 20.0f * log10f(rms / ADC_FS + 1e-9f); }这段代码有三个地方值得说。窗内估中点而不是用固定 2048,是因为中点分压会随电源和温度缓慢漂,固定值会让安静时的读数虚高。累加用 int32 而不是 float,400 个点的平方和在 12 位量级下最大约 6.7×10⁹,已经超 int32,实际用 12 位数据时先把采样值减中点再平方,最大约 4×10⁶×400 = 1.6×10⁹,刚好在范围内;如果换成 16 位 ADC,这里必须换 int64 或 float,否则溢出后读数会莫名其妙地周期性跳变,这种黑匣子问题很难查。最后 dBFS 的参考取的是满量程峰值而不是满量程正弦的有效值,比标准定义差 3dB,但只要全系统统一,做相对比较完全没问题。
调用频率上,50ms 窗、步进 25ms(半窗重叠)是比较实用的配置,既能跟上拍手这种几十毫秒的瞬态,又不会让 CPU 一直忙着算平方和。
4.3 阈值标定表:把电位器位置变成可复现的数字
标定的目的是把“拧到差不多”变成“第 37 个数”。做法分两步:先在安静环境采 30 秒,记录 dBFS 的最大值和标准差;再在目标场景下采 30 秒,记录峰值分布。两组的间隔就是判决门限的可用区间。
我一般按下面的表来定,具体数值随增益变,逻辑不变:
| 场景 | 安静底噪 dBFS | 目标声源峰值 dBFS | DO 阈值 | 软件门限 |
|---|---|---|---|---|
| 室内拍手开关 | −62 | −28 | 底噪 + 20dB | −45dBFS,持续 30ms |
| 房间噪声监测 | −58 | −35 | 底噪 + 12dB | −46dBFS,持续 500ms |
| 设备异响报警 | −70 | −40 | 底噪 + 15dB | −52dBFS,持续 100ms |
表里“持续时长”这一列最容易被忽略。门限只解决幅度,持续时长解决“是不是一次事件”:拍手是 10~30ms 的宽带瞬态,关门是 50~100ms 的低频冲击,人说话则有几百毫秒的起伏。把幅度和时长两个条件串起来,误报能降一个数量级。
没有声级计怎么做绝对标定?退一步用相对标定:拿一台手机上的声级计做参考,在 0.5m、1m 两个距离各测 5 个点,把 dBFS 和参考声压级做线性拟合,斜率应该接近 1,截距就是你的系统偏移量。残差超过 3dB 说明链路里有削顶或者底噪太高,先回去查硬件,别硬拟。
import numpy as np import pandas as pd # calib.csv 两列:spl_ref 为参考声级计读数,dbfs 为本机窗口读数 df = pd.read_csv("calib.csv") x = df["dbfs"].to_numpy(float) y = df["spl_ref"].to_numpy(float) A = np.vstack([x, np.ones_like(x)]).T k, b = np.linalg.lstsq(A, y, rcond=None)[0] resid = y - (k * x + b) print(f"SPL ≈ {k:.2f} * dBFS + {b:.2f}") print(f"残差 RMS = {resid.std():.2f} dB,最大 = {np.abs(resid).max():.2f} dB") # 斜率明显偏离 1,说明中段削顶或底噪抬高,先修硬件再重标斜率 k 在 0.9~1.1 之间才算正常。k 明显小于 1,说明大声时读数被压缩,多半是放大级削顶;k 明显大于 1,说明小声段被底噪托住了。残差里如果出现两段明显分离的簇,回头查是不是两个不同距离的数据混在一起了。
5. 排查清单:声音传感器最常翻车的 5 个现场
下面五条是这些年被问得最多的,每条按“看到什么、为什么、怎么办”写。遇到问题先对号入座,比漫无目的地换元件快得多。
5.1 触发类问题:上电就抖、极性反了
现象一:上电之后 DO 不停地翻转,手靠近板子会停一下,手拿开又抖。原因通常有两条叠加:比较器没有回差,阈值又被电位器调到了底噪中间,任何一点干扰都能翻过去;同时电源去耦不足,3.3V 稳压器后面只有一颗 100nF,负载一变中点就动。解决分三步:按 3.3 节加 1M 正反馈电阻把回差做到 30mV 量级;把电源入口补到 10µF + 100nF;软件上对 DO 中断做 20ms 消抖,三件事同时做,单做任何一件都只能缓解。
现象二:安静时 DO 一直是高电平,拍手反而拉低,跟预期完全相反。这不是故障,是比较器的拓扑决定的——信号进同相端、参考进反相端,信号超过参考时输出管导通,把 DO 拉到地。要么在软件里把有效电平反过来,要么把信号和参考对调接入。后者要注意运放输出阻抗和比较器输入偏置电流的配合,别为了改极性把回差算错了。
现象三:调好的阈值,换一块板子就不灵。原因是没有回差加单圈电位器,阈值位置本身就不可复现,±50mV 的偏差在增益 100 的链路里对应 0.5mV 的输入差,早就淹没在器件离散性里了。解决办法是把调好的电位器位置量出上下臂电阻,换成 1% 精度的固定电阻,同一批板子用同一组值,差异立刻收敛。
5.2 波形类问题:说话不触发、削顶、读数不动
现象四:拍手能触发,正常说话死活不行。示波器量放大输出,说话时只有 100mVpp 上下。原因一般是耦合电容取小了,低频被切掉;或者麦克风偏置电阻取太大,工作点被顶到接近电源,负半周先削掉,有效幅度只剩一半。把 C1 从 0.1µF 换到 0.47µF、Rd 从 10k 换到 2.2k,重新量一遍,说话时的摆幅通常能翻两倍。
现象五:AO 接 ADC,读数一直卡在中间不动。先量 AO 引脚到底是接在运放输出还是接在比较器输入,很多模块的 AO 是接在电位器分压点之后的,信号已经被衰减到几毫伏。如果确实是运放输出,再看是不是被 ADC 的输入阻抗拉低了——有些 MCU 的 ADC 采样保持电容不小,前面没有缓冲运放,采样瞬间会把信号拉塌。加一级电压跟随器,问题立刻消失。
现象六:想用 AO 做声压分级,但大声时读数永远停在同一个值。这是削顶,不是算法问题。回去看 4.1 节量到的最大不削顶输出,如果目标声源已经超过它,只有两条路:降增益,或者换带 AGC 的模块。指望软件把削顶的方波还原成原始幅度是不可能的,波形已经被切掉了,信息不可逆。
5.3 供电与布局类问题:电池正常、一上电机就乱
现象七:用电池供电一切正常,接上电机或者继电器之后 DO 疯狂误触发。原因是共地阻抗。电机启动瞬间几百毫安的电流在地线上产生几十毫伏的压降,这个压降直接叠加到比较器的参考电压上,等于阈值自己在跳。解决:电机和传感器分开供电,或者至少各走各的地,在电源入口单点汇合;模拟部分前面串 10Ω + 100µF 的 RC;比较器参考端并 1µF 到地,把瞬间波动压住。这三条做完还没好,就把比较器换成带内部迟滞的型号,或者干脆用软件在数字域做二次判决。
现象八:板子装在金属外壳里,灵敏度掉了一大半。麦克风需要前后腔的气压差,开孔被闷住或者开孔太小,等于给它加了个低通。开孔面积不小于麦克风振膜面积的 1/4,孔深尽量小于孔径,麦克风背面留 2mm 以上的空腔,别让外壳直接贴住背面焊盘。
提示:每次改硬件只改一个参数,改完立刻用同一段声源复测。一次改三个地方,最后不知道是哪个起的作用,这类血泪经验值得记一下。
6. 从开关量到声压级:把 DO 升级成可比较的 dB 读数
DO 只能告诉你“有没有超过某个值”,一旦换了场景,那个值就作废了。真正能跨场景复用的做法,是把 4.2 节的窗口 dBFS 做成时间序列,再在序列上做判决。这套东西不复杂,但几个细节决定了它能不能用。
第一件事是包络。原始 dBFS 序列抖动很大,直接做阈值比较会碎成一片。软件上做两条一阶低通:快包络时间常数 20ms,慢包络 500ms。慢包络跟的是环境底噪,快包络跟的是事件。判决条件写成“快包络 − 慢包络 > 10dB 且持续超过 60ms”,比固定阈值稳得多,换房间不用重新标。
/* 一阶包络跟随:alpha = 1 - exp(-1/(fs*tau)),fs 为 dBFS 输出频率 40Hz */ float env_fast = -90.0f, env_slow = -90.0f; const float a_fast = 0.71f; /* tau ≈ 20ms */ const float a_slow = 0.05f; /* tau ≈ 500ms */ void env_update(float dbfs) { env_fast += a_fast * (dbfs - env_fast); env_slow += a_slow * (dbfs - env_slow); if ((env_fast - env_slow) > 10.0f) event_ms += 25; /* 步进 25ms */ else event_ms = 0; if (event_ms >= 60) { trigger(); event_ms = 0; } }参数的含义要清楚:a_fast = 0.71 对应 40Hz 更新率下约 20ms 的时间常数,能跟上拍手;a_slow = 0.05 对应约 500ms,跟得上人走进房间这种缓慢变化,但不会跟着一次关门就抬起来。10dB 的差值门限是经验值,安静办公室里误报很少,工厂车间要提到 12~15dB。
第二件事是别迷信绝对声压级。没有校准过的麦克风,读数只能做相对比较。真要做 dB SPL,得用一台参考声级计在至少三个距离点上做拟合,而且每次换增益都要重标。做产品时我会把校准系数写进 EEPROM,出厂标一次,用户端只做单点零点校正。
第三件事是频域能省很多事。8kHz 采样、256 点 FFT,分辨率 31.25Hz,看 300~3000Hz 频段能量占总能量的比例,拍手这种宽带瞬态在低频段也有大量能量,人声则集中在谐波上。加一个简单的频段占比判据,能把敲桌子和说话分开,误报再降一档。
我自己踩得最深的一个坑,是早期花了整整两天调软件阈值,最后发现是运放同相端的中点电阻虚焊,中点漂到了 2.8V,波形下半周全被切掉。从那以后我的习惯固定下来:任何声音传感器板子到手,先量四个直流点,再上电听声音,最后才动代码。硬件是黑匣子的时候,软件调参只是在猜。希望帮到你。
本文还有配套的精品资源,点击获取