RMS计算DC偏移

问题描述 投票:0回答:1

我需要在单片机(单片机,资源有限)中实现正弦波的有效值计算。单片机缺乏FPU(浮点单元),所以我更希望留在整数领域。采集是通过10位ADC离散的。

为了寻找解决方案,我在这里找到了Edgar Bonet的这个伟大的解决方案。https: /stackoverflow.coma288123018264292

似乎完全符合我的需求。但我有一些问题。

  1. 输入是230VAC,50Hz的电源。它的转换&偏移通过硬件手段成为0-1V(峰值到峰值)的正弦波,我可以捕捉与ADC得到0-1023读数。硬件校准后,260 VRMS(即约-368:+368峰峰值)输入变成0-1V峰值输出。如果我也想保持在整数领域,我如何 "还原 "回原始的波形RMS值?单位可以不同,mV也可以。我的第一个猜测是从输入样本中减去512(直流偏移),然后像Edgar Bonet的答案那样做这个 "神奇 "的转变。但我意识到这是错误的,因为DC偏移不是固定的。相反,它的偏置是从0V开始的。即130 VAC输入会产生0-500 mV的峰峰值输出(而不是250-750 mV,到目前为止还能用).用实际有效值减去直流偏移,我需要从平方和中减去样本的平方和。就像这个公式一样。RMS formula

所以我最后用了下面的函数。

#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(窗口大小?)数字与F(50Hz)和我的ADC捕获率(每秒采样数)有什么关系? 例如,在我的捕获速度为X sps的情况下,我需要向rms_filter()提供多少实际样本才能得到真正的RMS值?至少如何评估所需的最小样本数?
c microcontroller adc square-root
1个回答
1
投票

我没有测试你的代码,但在我看来它应该可以正常工作.就个人而言,我不会以这种方式实现该功能。我不会用这种方式实现函数,而是去掉信号的直流部分。之前 试图计算RMS值。直流部分可以通过将rawsignal送过一个低通滤波器来估计。在伪代码中,这将是

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

而你所写的基本上是

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

不过应该不会有太大的区别。然而,第一个公式可以省去一个乘法。另外,通过在计算平方之前去掉直流分量,你可以乘以更小的数字,这可能有助于为定点计算分配比特。

在任何情况下,我都建议你在电脑上用合成数据测试该滤波器,然后再提交给MCU。

SAMPLES(窗口大小?)数字与F(50Hz)和ADC捕获率(每秒采样数)有什么关系?

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

这些单极低通滤波器的传递功能是:------。

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=50Hz的增益为

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

这里的相关参数是(SAMPLES * ff₀),也就是50Hz信号中适合你的采样窗口内的周期数,如果你适合一个周期,你就会让15%的信号通过滤波器。如果你适合一个周期,你将有15%的信号通过滤波器,如果你适合两个周期,则是一半,等等。

如果你设计了一个滤波器,你可以得到完美的50Hz信号的抑制。槽口 在这个特定的频率上。如果你不想钻研数字滤波器的设计理论,最简单的滤波器也许是一个简单的移动平均数,在20毫秒的时间内进行平均。不过这在RAM中的成本并不低,因为你必须在一个循环缓冲区中保存整整20毫秒的样本。

© www.soinside.com 2019 - 2024. All rights reserved.