You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派Pico通过ADC录制驻极体麦克风音频仅获白噪声问题排查

树莓派Pico ADC录制音频问题排查与解决

一、前置放大器搭建与测试

基于MCP6001运算放大器搭建驻极体麦克风前置电路,测试结果:

  • 两节AA电池供电:电源电压V_DD = 2.620(1)V,输出偏压V_out0 = 1.310(1)V,吹口哨时峰峰值信号V_out ~ 0.2-0.3V,信噪比良好;
  • Pico的ADC_VREF (GPIO 35)和AGND (GPIO 31)供电:电源电压V_DD = 3.2(1)V,输出偏压V_0 = 1.58(10)V,稳定性下降,但信噪比满足录音需求。

二、Pico ADC采样验证

将前置放大器输出连接至ADC0 (GPIO 26),在Thonny MicroPython Shell中测试采样:

>>> from machine import Pin, ADC
>>> mic = ADC(Pin(26))
>>> mic.read_u16()
32551
>>> mic.read_u16()
31911
>>> mic.read_u16()
31815

16位ADC最大值为2^16=65536,读数处于合理区间,说明ADC硬件连接正常。

三、原始录音代码的问题

编写的WAV录制代码生成的文件仅含白噪声,原代码如下:

from machine import Pin
import time

micPin = machine.ADC(Pin(26)) 
FILE_NAME = 'test17.wav'

sampleRate      = 44100 # 44.1 kHz - CD quality
bitsPerSample   = 16 
num_channels    = 1 # 1 - MONO, 2 -  STEREO

duration        = 3 # in seconds
bufferSize      = duration * sampleRate # 1/s * s

num_samples     = bufferSize

def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples):
    datasize = num_samples * num_channels * bitsPerSample // 8
    o = bytes("RIFF", "ascii")  # 1-4 (4byte) Marks file as RIFF
    o += (datasize + 36).to_bytes(
        4, "little"
    )  # 5-8 (4byte) File size in bytes excluding this and RIFF marker
    o += bytes("WAVE", "ascii")  # 9-12 (4bytes) File type
    o += bytes("fmt ", "ascii")  # 13-16 (4bytes) Format Chunk Marker, trailing 0
    o += (16).to_bytes(4, "little")  # 17-20 (4bytes) Length of above format data
    o += (1).to_bytes(2, "little")  # 21-22 (2bytes) Format type (1 - PCM)
    o += (num_channels).to_bytes(2, "little")  # 23-24 (2bytes)
    o += (sampleRate).to_bytes(4, "little")  # 25-28 (4bytes)
    o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little")  # 29-32 (4bytes)
    o += (num_channels * bitsPerSample // 8).to_bytes(2, "little")  # 33-34 (2bytes)
    o += (bitsPerSample).to_bytes(2, "little")  # 35-36 (2bytes)
    o += bytes("data", "ascii")  # 37-40 (4bytes) Data Chunk Marker
    o += (datasize).to_bytes(4, "little")  # 41-44 (4bytes) Data size in bytes
    return o


try:
    with open('/'+FILE_NAME, 'wb') as recFile:
        
        wav_header = create_wav_header(
            sampleRate,
            bitsPerSample,
            num_channels,
            num_samples
            )
        recFile.write(wav_header)
    
    with open('/'+FILE_NAME, 'ab') as recFile:    
        
        buffer = bytearray(bufferSize)

        for i in range(bufferSize):
            buffer[i] = micPin.read_u16()
#            print(buffer[i])
            time.sleep(1/sampleRate) 
    
        recFile.write(buffer)
        
except (KeyboardInterrupt, Exception) as e:
    print("caught exception {} {}".format(type(e).__name__, e))

问题根源:micPin.read_u16()返回16位无符号整数,但bytearray的每个元素仅能存储8位数据,赋值时会自动截断高8位,只保留低8位,导致音频数据完全失真,表现为白噪声。取消注释print(buffer[i])后输出值远低于正常ADC读数,也验证了高位数据丢失的问题。

四、修复后的代码验证

修改代码,将16位ADC值通过amplitude.to_bytes(2,'little')转换为两个字节后存入缓冲区,测试用正弦波可生成正常音频文件,修复后代码:

from machine import Pin, ADC
import time
import math # for sine wave

micPin = ADC(Pin(26)) 
FILE_NAME = 'test_sine.wav'

sampleRate      = 44100 # 44.1 kHz - CD quality
bitsPerSample   = 16 
num_channels    = 1 # 1 - MONO, 2 -  STEREO

duration        = 3 # in seconds
recordSize      = duration * sampleRate # 1/s * s
bufferSize      = 1000 

num_samples     = recordSize

def create_wav_header(sampleRate, bitsPerSample, num_channels, num_samples):
    datasize = num_samples * num_channels * bitsPerSample // 8
    o = bytes("RIFF", "ascii")  # 1-4 (4byte) Marks file as RIFF
    o += (datasize + 36).to_bytes(
        4, "little"
    )  # 5-8 (4byte) File size in bytes excluding this and RIFF marker
    o += bytes("WAVE", "ascii")  # 9-12 (4bytes) File type
    o += bytes("fmt ", "ascii")  # 13-16 (4bytes) Format Chunk Marker, trailing 0
    o += (16).to_bytes(4, "little")  # 17-20 (4bytes) Length of above format data
    o += (1).to_bytes(2, "little")  # 21-22 (2bytes) Format type (1 - PCM)
    o += (num_channels).to_bytes(2, "little")  # 23-24 (2bytes)
    o += (sampleRate).to_bytes(4, "little")  # 25-28 (4bytes)
    o += (sampleRate * num_channels * bitsPerSample // 8).to_bytes(4, "little")  # 29-32 (4bytes)
    o += (num_channels * bitsPerSample // 8).to_bytes(2, "little")  # 33-34 (2bytes)
    o += (bitsPerSample).to_bytes(2, "little")  # 35-36 (2bytes)
    o += bytes("data", "ascii")  # 37-40 (4bytes) Data Chunk Marker
    o += (datasize).to_bytes(4, "little")  # 41-44 (4bytes) Data size in bytes
    return o


try:
    with open('/'+FILE_NAME, 'wb') as recFile:
        
        wav_header = create_wav_header(
            sampleRate,
            bitsPerSample,
            num_channels,
            num_samples
            )
        recFile.write(wav_header)
        print('Header written')
        
    with open('/'+FILE_NAME, 'ab') as recFile:
        
        buffer = bytearray()
        
        # sine wave creation
        for i in range(recordSize):

            x = (2 * math.pi) / 1000    # devide by an arbitray number
                                        # to create steps
            y = math.sin(i * x)
            amplitude = math.floor((2**16-1//2) + ((2**16-1)//2)*y)
            
            if i%bufferSize==0:
                # write buffer to file and empty it
                recFile.write(buffer)
#                print('buffer written')
                buffer = bytearray()
                buffer.extend(amplitude.to_bytes(2,'little'))
            else:
                buffer.extend(amplitude.to_bytes(2,'little'))        

except (KeyboardInterrupt, Exception) as e:
    print("caught exception {} {}".format(type(e).__name__, e))

后续只需将正弦波生成部分替换为真实麦克风ADC读数的转换即可正常录音。

五、录音项目优化建议

  • 采样率调整:44.1kHz的采样率对MicroPython运行环境压力较大,建议降低至22050Hz或16000Hz,提升采样稳定性,同时满足语音录音需求;
  • 硬件供电优化:给前置放大器使用独立电源,避免Pico电源波动导致的偏压不稳定,进一步提升信噪比;
  • 缓冲区优化:预分配固定大小的bytearray(如bytearray(bufferSize*2)),避免频繁创建和清空缓冲区,提升写入效率;
  • 数据格式校准:WAV标准的16位PCM为有符号整数,需将Pico ADC的无符号读数(065535)转换为有符号值(-3276832767),即adc_value - 32768,再转换为小端字节流,确保音频播放正常。

内容的提问来源于stack exchange,提问作者tinker.toadie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:12:03