RMS 计算 DC 偏置

RMS calculation DC offset

我需要在 MCU(微控制器,资源受限)中实现正弦波的 RMS 计算。 MCU 缺少 FPU(浮点单元),所以我更愿意留在整数领域。通过 10 位 ADC 进行离散捕获。

寻找解决方案,我在 Edgar Bonet 找到了这个很棒的解决方案:

看来完全符合我的需求。但是我有一些问题。

  1. 输入是 230 VAC,50 Hz 的电源。它通过硬件方式转换和偏移成为 0-1V(峰峰值)正弦波,我可以用 ADC 捕获它以获得 0-1023 读数。硬件经过校准,使 260 VRMS(即约 -368:+368 峰峰值)输入变为 0-1V 峰值输出。如果我也想保持在整数范围内,我如何 "restore" 返回原始波形 RMS 值?单位可以变化,mV 也可以。 我的第一个猜测是从输入样本(DC 偏移)中减去 512,然后像 Edgar Bonet 的回答那样进行 "magic" 偏移。但我意识到这是错误的,因为直流偏移不是固定的。相反,它偏向于从 0V 开始。 IE。 130 VAC 输入会产生 0-500 mV 的峰峰值输出(不是 250-750 mV,到目前为止还可以)。 使用实 RMS 减去直流偏移,我需要从平方和中减去样本的平方和。就像这个公式:

所以我得到了以下函数:

#define INITIAL 512
#define SAMPLES 1024
#define MAX_V 368UL // Maximum input peak in V ( 260*sqrt(2) )
/* K is defined based on equation, where 64 = 2^6,
 * i.e. 6 bits to add to 10-bit ADC to make it 16-bit 
 * and double it for whole range in -peak to +peak
 */
#define K (MAX_V*64*2)

uint16_t rms_filter(uint16_t sample)
{
    static int16_t rms = INITIAL;
    static uint32_t sum_squares = 1UL * SAMPLES * INITIAL * INITIAL;
    static uint32_t sum = 1UL * SAMPLES * INITIAL;

    sum_squares -= sum_squares / SAMPLES;
    sum_squares += (uint32_t) sample * sample;
    sum -= sum / SAMPLES;
    sum += sample;
    if (rms == 0) rms = 1;    /* do not divide by zero */
    rms = (rms + (((sum_squares / SAMPLES) - (sum/SAMPLES)*(sum/SAMPLES)) / rms)) / 2;
    return rms;
}

...
// Somewhere in a loop
getSample(&sample);
rms = rms_filter(sample);
...
// After getting at least N samples (SAMPLES * X?)
uint16_t vrms = (uint32_t)(rms*K) >> 16;
printf("Converted Vrms = %d V\r\n", vrms);

好看吗?还是我做错了什么?

  1. SAMPLES(window 大小?)数量与 F (50Hz) 和我的 ADC 捕获率(每秒采样数)有何关系? IE。如果我的捕获速度是 X sps,我需要向 rms_filter() 提供多少真实样本才能获得真实的 RMS 值?至少如何评估所需的最小样本数量?

我没有测试您的代码,但在我看来它应该可以正常工作。 就个人而言,我不会以这种方式实现该功能。我会 取而代之的是在 尝试之前移除了信号的直流部分 计算 RMS 值。可以通过发送原始数据来估计 DC 部分 通过低通滤波器的信号。在伪代码中,这将是

rms = sqrt(low_pass(square(x - low_pass(x))))

而你写的基本上是

rms = sqrt(low_pass(square(x)) - square(low_pass(x)))

不过应该不会有太大区别。第一个公式, 但是,为您节省了乘法。此外,通过去除直流分量 在计算平方之前,你最终乘以较小的数字, 这可能有助于为定点实现分配位。

无论如何,我建议您在计算机上测试过滤器 在提交给 MCU 之前合成数据。

How does SAMPLES (window size?) number relates to F (50Hz) and my ADC capture rate (samples per second)?

常数SAMPLES控制低通的截止频率 过滤器。这个截止点应该足够小,几乎可以完全去除 信号的 50 Hz 部分。另一方面,如果电源 供应不完全稳定,您测量的数量会 随着时间慢慢变化,你可能希望你的截止值足够高 捕捉这些变化。

这些单极点低通滤波器的传递函数是

H(z) = z / (SAMPLES * z + 1 − SAMPLES)

哪里

  • z = exp(i 2 π f / f₀),
  • i为虚数单位,
  • f 是信号频率并且
  • f₀为采样频率

如果 f₀ ≫ f(这对于良好的采样是可取的),您可以近似 这是模拟滤波器:

H(s) = 1/(1 + SAMPLES * s / f₀)

其中 s = i2πf,截止频率为 f₀/(2π*SAMPLES)。收获 在 f = 50 Hz 时

1/sqrt(1 + (2π * SAMPLES * f/f₀)²)

这里的相关参数是(SAMPLES * f/f₀),也就是数量 适合采样的 50 Hz 信号周期 window。 如果你适合一个周期,你会让大约 15% 的信号通过 过滤器。如果你适合两个时期等

如果您设计一个 在该特定频率使用 notch 进行过滤。如果你不想 深入研究数字滤波器设计理论,最简单的滤波器可能 是一个简单的移动平均线,它在一段时间内取平均值 20 毫秒。但是,这在 RAM 中有一个不小的成本,因为你必须 在循环缓冲区中保留完整的 20 毫秒样本。