3
\$\begingroup\$

This question is about obtaining a true RMS voltage reading from a running sampling ADC. Does this give me a true RMS reading, or where did I made a mistake?

Construct a ring buffer of an large enough size and start writing ADC readings into it. The RMS of the signal is approximately the RMS of all numbers in that ring buffer.

-- EDIT --

Or is this a good idea:

Have a variable, n, as average of squares. Whenever a new sample \$k_i\$ comes this is calculated:

$$ n_{i+1} = \frac{2n_i + k_i^2}{2} $$

and RMS is calculated by taking square root of this number. (Taking square roots are more expensive than squareing it, even on a 12-core 2.5GHz Xeon)

Clarification

I am not talking about whether the ADC is RMS or not - actually my ADC captures instantaneous values. I am talking about how to take this instantaneous value and apply an algorithm to it, to approximate an RMS measurement.

I am also not talking about embedded programming with limited resources. The system in question, not relevant to this question, have a powerful server in it and it can (and will) be used to crunch the majority, if not all the numbers.

\$\endgroup\$
  • \$\begingroup\$ Maxthon, you should rephrase your question. For instance a DAC does not output true RMS. I know what you mean, but I advise you to rewrite it. And maybe you meant ADC too. \$\endgroup\$ – iggy Mar 1 '15 at 7:45
  • 1
    \$\begingroup\$ Do you mean 'running sampling ADC'? \$\endgroup\$ – diverger Mar 1 '15 at 13:59
  • \$\begingroup\$ @diverger Whoops \$\endgroup\$ – Maxthon Chan Mar 1 '15 at 17:56
  • \$\begingroup\$ @iggy I know that DAC output is not RMS - in fact the DAC in question captures instantaneous values. I am talking about taking those instantaneous values, and by applying some algorithms to them, to approximate an true RMS measurement. This is not even embedded programming. I have a 2-processor 12-core Xeon server with 128GB RAM available to crunch all those numbers. \$\endgroup\$ – Maxthon Chan Mar 1 '15 at 18:47
  • \$\begingroup\$ Your new formula is incorrect. If n already contains 100 previous squared samples then addding a single new squared value to it (k) means dividing by the new total by 101. You should also consider limiting the value n to contain a finite number of samples by removing the 1st sample when you add the latest. When you read my answer didn't you understand it? \$\endgroup\$ – Andy aka Mar 1 '15 at 21:58
5
\$\begingroup\$

One important thing to realize is that your buffer length must be much larger (order tens, hunderds or more times) than the period of the signal you want to measure, depending on the accuracy you want to achieve.

In this answer I will not detail the maths behind RMS, I got the impression from the question that the algorithm itself is clear, though the length of the buffer may introduce an interesting effect.

To get a feeling for the measurement error I want to discuss in this answer, imagine that your buffer is relatively short, filled with samples and it's content (for the sake of argument) is static. Say it fits just over 1.25 times of a whole cycle:

enter image description here

Then imagine you copy the contents of the buffer to its own end indefinitely. The wave form you get is the signal you're actually measuring.

enter image description here

Notice that the x-scale changes between the two plots.

In other words, you want your buffer to be much larger than the period of the signal you're trying to measure. That way the error will average out.

\$\endgroup\$
  • 1
    \$\begingroup\$ And perhaps filter the computed measurement as well? \$\endgroup\$ – copper.hat Mar 1 '15 at 7:54
  • 1
    \$\begingroup\$ How does this produce RMS of a signal? \$\endgroup\$ – Andy aka Mar 1 '15 at 11:40
  • \$\begingroup\$ @Andyaka I am describing a gotcha, not the actual RMS algorithm. I had the impression from the question that OP knows how to calculate RMS from a given number of samples. \$\endgroup\$ – jippie Mar 1 '15 at 11:42
  • 1
    \$\begingroup\$ Copying the buffer to make it longer will not produce an RMS value that is at all different to the numbers in the original buffer. The numbers need to be squared then totalized, the averaged to one value then square rooted for RMS. \$\endgroup\$ – Andy aka Mar 1 '15 at 11:50
  • 4
    \$\begingroup\$ @Andy: What jippie is trying to point out in his answer is that, if the time interval \$t\$ that you're collecting samples over is not an even multiple of the signal period \$\tau\$, then the measurement will have an error roughly proportional to \$\mathrm{abs}\left(\frac t\tau - \mathrm{round}\left(\frac t\tau\right)\right)\frac\tau t\$. Thus, you either want \$t \gg \tau\$, or you want to adjust \$t\$ to be an exact multiple of \$\tau\$ (which is easy enough if your signal is a simple sine wave, but potentially more difficult if it's a complex waveform with some low-frequency components). \$\endgroup\$ – Ilmari Karonen Mar 1 '15 at 14:29
4
\$\begingroup\$

This question is about obtaining a true RMS voltage reading from a running sampling DAC

Firstly I'm convinced you mean an ADC or analogue to digital converter rather than a Digital to analogue converter (DAC).

So, you have a series of samples coming from the ADC and you want to calculate RMS. In short: -

  1. Square each sample mathematically,
  2. Add a number of those squared samples together to get an accumulated number,
  3. Divide by the number of samples you accumulated then
  4. Take the square root of that accumulated number.

Here is an idea, for a sampled sinewave signal: -

enter image description here

Here are the values squared: -

enter image description here

The accumulated value is

0+0.146+0.5+0.854+1+0.854+0.5+0.146+0+0.146+0.5+0.854+1+0.854+0.5+0.146 = 8

The mean of these values is 8/16 = 0.5

And the resulting RMS value is \$\sqrt{0.5}\$ =0.707

Pretty pictures taken from here

Interesting things to note - 16 samples were used but if 8 samples were taken I'd still get the same RMS result. For instance: -

0+0.146+0.5+0.854+1+0.854+0.5+0.146 = 4 and with only 8 samples the mean is still 0.5. The point here is that storing a bunch of numbers then repeating that set of numbers gets no benefit.

For that waveform I could take any consecutive 8 samples such as these: -

1+0.854+0.5+0.146+0+0.146+0.5+0.854 = 4 i.e same result. 0.5+0.854+1+0.854+0.5+0.146+0+0.146 = 4 ditto

This works because the mean of the original signal contained no dc offset and the accumulated period over which samples were taken (8 samples in this case) were enough to fully capture the "essence" of the sinewave. Any fewer than 8 and I would have errors.

This informs you that to calculate RMS you must take enough consecutive samples to satisfy the lowest frequency part of the spectrum of the original signal.

You still have to obey nyquist for the higher frequency components and, for instance, sampling an AC power current requires thousands of samples per second to get a reasonably accurate true RMS/power.

\$\endgroup\$
  • \$\begingroup\$ My signal will not be some simple sine waves - the entire setup is some VI gear have ADC on one machine and number crunching on another. Hint: I pushed the Raspberry Pi's I2S bus to its extremes in the term of frequency, and obviously the wimpy ARM1176 won't take it too well so I used a server (12-core Xeon) to crunch the numbers. \$\endgroup\$ – Maxthon Chan Mar 1 '15 at 18:04
  • \$\begingroup\$ Analysis by sinewave demonstrates my point about the number of samples needed to calculate true RMS. Providing you take enough samples to cover your lowest frequency and a high enough rate to not alias your highest frequency, the method I've shown works. \$\endgroup\$ – Andy aka Mar 1 '15 at 20:07
  • \$\begingroup\$ So the ring buffer is still a better solution then? With a big enough buffer length? \$\endgroup\$ – Maxthon Chan Mar 2 '15 at 4:07
  • \$\begingroup\$ A better solution than what? \$\endgroup\$ – Andy aka Mar 2 '15 at 7:07
1
\$\begingroup\$

If the square of your current estimate of the RMS value is \$s_i^2\$ (with time index \$i\$), and if \$x_i\$ is your current input signal, then with a buffer length of \$N\$ samples

$$s_i^2=\frac{1}{N}\sum_{k=i-N+1}^ix_k^2=\frac{1}{N}\sum_{k=i-N}^{i-1}x_k^2+\frac{1}{N}\left(x_i^2-x_{i-N}^2\right)=s_{i-1}^2+\frac{1}{N}\left(x_i^2-x_{i-N}^2\right)\tag{1}$$

Eq. (1) defines a recursion for \$s_i^2\$ computed from the previous squared RMS estimate \$s_{i-1}^2\$, the current input value \$x_i\$ and the last value in the buffer \$x_{i-N}\$. This is a recursive implementation of a moving average filter applied to the squares of the input signal.

If you want to get rid of the buffer you might also want to consider an exponentially weighted average defined by

$$s_i^2=\alpha x_i^2+(1-\alpha)s_{i-1}^2\tag{2}$$

where \$0<\alpha<1\$ defines the effective memory of the recursion. For \$\alpha\$ close to \$1\$, the memory is very short, whereas for \$\alpha\$ close to \$0\$ the past input values still have a relatively large effect on the current RMS estimate. Note that in Eq. (2) you just need the current input sample \$x_i\$ to update your estimate, and not the input sample \$x_{i-N}\$ as is the case with the moving average of Eq. (1)

\$\endgroup\$
1
\$\begingroup\$

One way or another, you want to low pass filter the squared readings, then take the square root of that whenever you want the latest RMS value.

Your first method "Construct a ring buffer of an large enough size and start writing ADC readings into it. The RMS of the signal is approximately the RMS of all numbers in that ring buffer" won't work. You can't perform RMS on individual readings, then low pass filter them to get the low pass filtered RMS. Note that RMS of a single reading is just the absolute value of that reading. Put another way, low pass filtering RMS readings doesn't get you another RMS reading with less bandwidth. The result is no longer RMS. You have to low pass filter in the squared-reading domain.

To get the RMS from a stream of reading:

  1. Square each reading.

  2. Low pass filter the result from #1.

  3. Take the square root of the result from #2.

Note that all this talk of buffers is just one particular way of performing a low pass filter. You don't need a buffer to perform a LPF. You could, for example, use one or more single pole filters such as:

  FILT <-- FILT + FF(NEW - FILT)

Which has been discussed many times here before, such as here.

The filter is a tradeoff between responding to a new RMS level fast enough, but not so fast that it responds to the individual half-cycles of the measured waveform. For a sine, the RMS goes to zero twice per line cycle.

For example, let's say you want to make a RMS voltage meter for 50 or 60 Hz line power. The instantaneous values will go up and down as low as 100 Hz just from the power waveform alone. However, that's still fast compared to human scale and how fast such a meter should respond. In that case, you might use two filters as above cascaded, each set to 4 Hz rolloff. 100 Hz would then be attenuated by a factor of 625, or 56 dB. That would support a RMS value with 9 bit accuracy, or better than 0.2%.

No matter what you do, you can't make the square root to get the final reading go away.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.