I have an SAR ADC to measure the RMS value of an AC signal. My present method is to use a timer to trigger the conversion and store the conversion result. When I've sampled a whole cycle of points, I subtract the DC level (the average of all points) from the signal then use the well-known RMS algorithm to get the RMS value.

I wonder if there is any method to "distribute" the calculation work to samples. For example, if I need to calculate the mean value of the cycled signal, I can add the conversion result to a global variable "sum" after a conversion is done. When the conversion of the last sample is done, I only need to divide the "sum" by the sample count. In this method, I only need one global variable, there's no need to store all the samples. But for my RMS measurement, what is difficult for me is that I need to subtract the DC level, but the DC level can only be gotten after I've done a whole cycle sampling.

I think you can understand me. Any suggestion is appreciated.


Thanks for all you who have gave me answers and suggestions. And some answers are acceptable for me. After some searching and thinking, I've an ideal too. But not very sure.

As known,

$$ V_{RMS(total)} = \sqrt{V_{D}^2 + V_{1RMS}^2 + V_{2RMS}^2 + \cdots + V_{nRMS}^2} $$

Assume a perfect whole cycle sampling, and omit the higher harmonics,

$$ V_{1RMS} = \sqrt{V_{RMS(total)}^2 - V_{D}^2} $$

So, I can use running-averaging to get \$V_{D}\$, and running-rms to get \$V_{RMS(total)}\$ (without removing the DC), then finally do a subtraction and sqrt to get the RMS value of the fundamental wave signal. Certainly, there will some error when my sampling is not a perfect whole cycle one.

I need someone to confirm this, thanks.

  • \$\begingroup\$ Is your signal a single tone with dc offset? Or something more complicated? \$\endgroup\$ – The Photon Dec 30 '14 at 6:08
  • \$\begingroup\$ Depending on the nature of the AC signal you might be able to work with its differential, which inherently removes any DC component. \$\endgroup\$ – markt Dec 30 '14 at 6:33
  • \$\begingroup\$ @The Photon: Yes, it's nearly single tone, with dc offset. \$\endgroup\$ – diverger Dec 30 '14 at 6:35
  • \$\begingroup\$ @markt: You mean use differential measurement? But I'm afraid it always has some DC there. I want to add a software method to remove the DC to make sure there is no DC. \$\endgroup\$ – diverger Dec 30 '14 at 6:37
  • \$\begingroup\$ No time to make a complete answer now, but could you create an IIR filter to estimate the dc component and then subtract that off before calculating the RMS? \$\endgroup\$ – The Photon Dec 30 '14 at 6:54

Keep the data stored in a circular buffer, and keep a pointer to the current value. Keep a running squared total. At each sample, subtract the squared value that "falls off" your buffer, and add the squared value that adds on. To get the new sum squared, its then two squarings, and add and a subtract, regardless of how big your buffer is. You're still on the hook for the square root, though.

For efficiency in the modulo math for the circular buffer, I suggest a buffer size of a power of 2.

  • 1
    \$\begingroup\$ Can't say I understand the downvotes. It's the framework for a running rms algorithm, like what was requested. \$\endgroup\$ – Scott Seidman Dec 31 '14 at 3:14
  • \$\begingroup\$ Thanks for your answer. What about the DC level, my main problem is about the removing of the DC level. \$\endgroup\$ – diverger Dec 31 '14 at 14:50
  • \$\begingroup\$ @diverger -- If your buffer is big enough, the rms will be the DC level (or at least approximately). Alternatively, you can do the same thing, and DON'T square, and you'll get the mean \$\endgroup\$ – Scott Seidman Dec 31 '14 at 15:06
  • \$\begingroup\$ Umm, can't understand you yet. Every data enter the RMS algorithm is like this \$D_{sample} - DC\$, but the the DC can only be determined when all sample are done, it's the mean of a full cycle of samples. \$\endgroup\$ – diverger Dec 31 '14 at 15:15
  • 1
    \$\begingroup\$ Ahh, I got it. I need at least one cycle delay to get the estimate of the DC level, so my buffer should be at least the size of two cycles. It's acceptable for me. \$\endgroup\$ – diverger Dec 31 '14 at 15:22

From your description you are subtracting an already determined DC offset correct? probably calculated via some accumulator averager.

Do you need the DC-coupled signal?

What I would do (well what I do do - not for RMS calculations but other DC-sensitive signals: resolvers, CT's etc...) is use a lossy HP filter

\$ H = \frac{1}{D}\frac{1- z^{-D}}{1-z^{-1}} \$


This topology is really good at removing DC offset (just be mindful of the lowest freq and the size of the intermediate register)

Now do you calculate the cycle RMS and then provide an accumulator w.r.t. "rolling rms" or do you provide two calculation steams - rolling rms & cycle rms is downto resources

  • \$\begingroup\$ Thanks for your answer. The DC offset is not constant. \$\endgroup\$ – diverger Dec 31 '14 at 12:20
  • \$\begingroup\$ That is the beauty of this filter. As long as the variability of the DC offset is significantly lower freq than the frequency of interest (ie falls below the corner freq in the link) it will still be removed \$\endgroup\$ – JonRB Dec 31 '14 at 13:18

(Following on from my comment).

If you take a signal composed of a sinusoid plus a DC offset, it can be described as:

$$ f(t) = Asin(\omega t) + B $$

Where \$Asin(\omega t)\$ is the sinusoid and B is the DC offset.

If you differentiate wrt t:

$$ g(t) = \frac{df(t)}{dt} = A \cdot \omega \cdot cos(\omega t) + 0 = A \cdot \omega \cdot cos(\omega t) $$

That is, the output of the differentiation is a phase-shifted copy of the sinusoid component of the input signal, with amplitude scaled by the frequency of the input signal. The DC component is entirely gone, neutralized by the magic of mathematics.

If you want to remove (most of) the phase shift, you can re-integrate the differentiated signal:

$$ \int^T_0 g(t) = A \cdot \omega \cdot sin(\omega t)/ \omega + C, $$

where C is the initial value (the DC offset), which you can set to zero.

In practice this will result in a slight phase shift caused by the processing time required to differentiate and then integrate the signal.

A good analogue analogy for the process is a series capacitor - it differentiates an AC signal and blocks DC.

  • \$\begingroup\$ Umm, numerical differentiation? I'm a little worried about the noise. But I'll try this. Thanks. \$\endgroup\$ – diverger Dec 30 '14 at 7:39
  • \$\begingroup\$ You could run the differentiated signal through an LPF to reduce noise, but that's expensive in terms of CPU cycles and (depending on your application) may be unnecessary. \$\endgroup\$ – markt Dec 30 '14 at 7:45
  • \$\begingroup\$ Your answer is useful, I do some editing with the equations, and change "x" to "t". Please check it's not conflict with your original meaning. \$\endgroup\$ – diverger Dec 31 '14 at 15:46

The definition of RMS is like this:

$$ V_{rms}(t)=\sqrt{\frac{\int_0^t V^2(t) \mathrm{d}t}t} $$

So reverse it:

$$ V(t)=\sqrt{\frac{\mathrm{d}(t \centerdot V_{rms}^2(t))}{\mathrm{d}t}} $$

  • \$\begingroup\$ I don't see how this answers the question. The OP wants to calculate \$V_{RMS}\$ on the fly from the samples as they come in. How does your transformation help with that? \$\endgroup\$ – Dave Tweed Dec 30 '14 at 12:37
  • 1
    \$\begingroup\$ @DaveTweed You should know that this integration or differentiation is trivial to implement on a MCU over discrete time. And I have seen that you are being caustic on this question. \$\endgroup\$ – Maxthon Chan Dec 30 '14 at 12:47
  • 2
    \$\begingroup\$ I'm not being caustic; I'm just trying to help you write an answer that's both relevant and useful. All you've done is written the definition of RMS in two different forms, without explaining how this addresses the OP's question about implementation. \$\endgroup\$ – Dave Tweed Dec 30 '14 at 14:43

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.