Skip to content

PWM输出接低通滤波的探讨

:beginner:一路PWM三阶RC滤波语音输出-噪声问题

项目场景:

很多MCU内部没有DAC,但是芯片应用在需要DAC的场景,此时需要用PWM波模拟DAC输出。

有一路PWM和多路PWM波实现方式,取决于项目要求以及MCU性能

单路PWM波:MCU主频相对较高,项目对DAC精度要求低。

多路PWM波,MCU主频相对较低,项目对DAC精度要求高。

问题描述

使用单路PWM输出时,有噪音输出。输出结构如下:

PWM波 -> RC滤波电路 -> 功放芯片/8002 -> 喇叭

PWM波:一路PWM,由一个8位定时器产生,频率在64K

RC滤波电路:使用三阶RC滤波,其中R1C1=R2C2=R3C3=RC,所以截止频率

f=\frac{1}{2*pi*RC}
功放芯片:使用8002

喇叭:8欧1W

原因分析:

噪声来源一:定时器输出频率波动 噪声来源二:功放输出不稳定 噪声来源三:滤波电路对PWM波处理有杂波

如果直接输出一段音频,有噪音的出现,此时无法很好的定位问题来源是哪一点。

这里采用一些方法来排除一些噪声源。

1.输出正弦波,通过示波器观察RC滤波后的波形,分析滤波电路对PWM波处理有杂波

PWM数据; img

示波器显示: img

RC滤波后: img

可以看出RC滤波后正弦波是正常的,稍微有点变形,但是并无异形和封底顶。

2.输出基准电平(50%的占空比方波),分析定时器输出频率波动和功放输出问题

    2.1查看语音wav转的bin文件,索引信息后数据都是0x80.

    2.2烧录文件和程序后,测量PWM输出,波形如下图,是正常的。此时喇叭周期性的有噪音输出。功放使能和PWM波同时输出。



    2.3 保持功放使能,循环播放语音。此时喇叭周期性的有噪音输出。

    检查发现采用FIFO方式在定时器里面读出并更新PWM,由于FIFO读出时间不稳定导致更新PWM波的频率有波动,从而产生噪音。

    解决方法:把FIFO读出数据放到外面,提前准备好,修改后喇叭周期性的噪音没有了。

    进一步测试发现上电时有一点噪音输出。

    2.4分析上电瞬间有噪音输出

    原因分析可能是PWM刚开始输出的跳变或者功放刚上电不稳定输出导致。

    进一步测试:

    1.上电后先输出PWM波5s后打开功放使能,此时功放使能瞬间有一个噪声

    2.上电后先打开功放使能5s后输出PWM波,此时有两个噪声,刚上电时以及5s后输出PWM时。

    通过波形和结果可以分析出:上电噪声有两个原因

    A.功放使能时功放内部输出的噪声。

    B.PWM波刚输出时产生一个跳变信号,从而产生的噪声。

功放的上电噪音可以在输出端加入滤波电容进行消除,因为这个和具体的功放有关系,可能有些功放没有上电噪音,没有进一步测试。

解决方案:

1.同过正弦波调整RC滤波,使得波形尽量如同正弦波 2.使用时先输出PWM波后在开功能使能,这样只有一个功放使能时内部噪声。

:beginner:软件实现低通滤波 未测试

一阶RC低通滤波算法是一种电路模拟滤波器,它通过将高频部分的信号衰减来消除噪声。这种滤波器由一个电阻和一个电容组成,因此被称为RC低通滤波器。

具体来说,低通滤波器通过将高频部分的信号衰减来消除噪声。高频部分的信号是指频率高于截止频率的信号,而截止频率是指滤波器对高频部分信号的衰减开始的频率。

低通滤波器的输入信号通过电阻传递到电容上,电容会滞后于电阻而导致信号衰减。在一阶RC低通滤波器中,截止频率是由电阻和电容共同决定的。 具体来说,截止频率 fc = 1 / (2πRC)。

以下是一个使用C语言编写的一阶RC低通滤波器的代码示例:

#include <stdio.h>
#define PI 3.14159265

float lowpass(float input, float output_prev, float RC, float dt) {
    float alpha = dt / (RC + dt);
    return output_prev + alpha * (input - output_prev);
}

int main() {
    float RC = 1 / (2 * PI * 1000);  // 1000 Hz cutoff frequency
    float dt = 1 / 44100;  // sample rate is 44.1 kHz
    float input = 0.5;  // input signal
    float output_prev = 0;  // previous output
    float output = lowpass(input, output_prev, RC, dt);
    printf("%f", output);
    return 0;
}

该代码示例定义了一个lowpass()函数,该函数接受输入信号,上一次输出,RC时间常数和采样时间间隔作为参数。在函数中,alpha被定义为dt / (RC + dt),用于计算新的输出值。

新的输出值是通过将上一次的输出与输入信号之间的差值乘以alpha来计算的。这样,如果输入信号与上一次的输出相同,则新的输出将与上一次的输出相同,否则新的输出将接近输入信号。

main()函数中,我们设置了截止频率为1000 Hz,采样率为44.1 kHz,输入信号为0.5。我们调用lowpass()函数,将上一次的输出设置为0。最后,我们打印出新的输出。

一阶RC低通滤波算法是一种简单而有效的滤波方法,可以有效消除高频噪声。但是需要注意的是,这种滤波方法有时会对信号的时域性能造成影响,因此需要根据具体应用场景进行权衡。

:beginner:PWM通过RC低通滤波器模拟DAC

当我们电路需要DAC而单片机并没有DAC外设时,则可采用PWM通过RC低通滤波器来模拟实现DAC功能。

RC低通滤波器 img

当采用低通滤波器模拟DAC时,PWM频率应远大于RC低通滤波电路的截止频率fc=1/2πRC(10倍以上)。输出电压为Vout=Vcc*Duty

在使用此电路时,应注意:

  1. 一般情况下,当电容C较小,电阻R较大时,输出电压损耗较小,纹波较大;当电容C较大,电阻R较小时,输出电压损耗较大,纹波较小。所以,为了获取线性度较高的精确DA转换,一般采用较小电容并尽量不要使用电解电容。

  2. 为了提高输出的驱动能力,一般会在RC低通滤波器器之后还会加一级高性能的电压跟随,并在跟随器输出的地方加上一个滤波用的电解电容,使输出电压进一步变得光滑。但是需要注意的是,这时的输出电压里可能含有较多的交流 谐波成分,如果处理不当,电压跟随器有可能自激。解决的办法就是使用一个小的去藕电容。而且这里电容的放置顺序必须是电解电容在前,去藕电容在后!

RC低通滤波器+电压跟随器 img

3、如果输出电压精度和线性度要求不高,但是对纹波要求却很高,或者这个电压比较固定时,可以使用电容较大的滤波组合。因为,虽然大电容的直流损耗较大,但是我们可以通过调节PWM占空比来达到要求的输出电压,或者通过一级AD转换的反馈来实现精确的固定电压输出。只是这里仍然要加一级电压跟随器,以便于后级采集电路使用,且AD采集点放置在跟随器输出处。

4、如果一级RC低通滤波器达不到效果,则可使用多级RC低通滤波器进一步提高输出平滑度。

下图为 二级RC低通滤波器

img

完结