I’m trying to calculate the impedance and phase angle of a capacitor in software for a microcontroller project I’m working on, and I’ve included a pic of what I mean (not to any scale). I’ve prototyped a simple Series RC circuit and I’m feeding a 1Khz sine wave onto it. Measuring across ‘R’ I’ve collected the data for current through the circuit, and measuring across ‘C’ I’ve collected the data for voltage across the capacitor.

I’m not sure of how to calculate Vp, Vq, Ip, and Iq, and after looking into various methods one idea was to start with the following:

Vp = sum(i = 0 to N-1) ADC(i) * cos(2 * PI * i / N)

Vq = sum(i = 0 to N-1) ADC(i) * sin(2 * PI * i / N)

and similarly:

Ip = sum(i = 0 to N-1) ADC(i) * cos(2 * PI * i / N)

Iq = sum(i = 0 to N-1) ADC(i) * sin(2 * PI * i / N)

Needless to say I'm not happy with the results, can anyone point me in the right direction on how to properly make these calculations.

thanks kvresto

enter image description here

  • \$\begingroup\$ Just to clarify, I'm looking for a method that can be implemented in a micro. A full blown FFT is I think overkill. \$\endgroup\$
    – kvresto
    Apr 30 '16 at 0:23
  • \$\begingroup\$ Well capacitive impedance is 1/(2pi*f) and if it's an AC signal, can you measure the zero crossing times of the current and voltage? then it's just time you have to work with, 360*(Tizero - Tvzero)/Tperiod or something to that effect \$\endgroup\$
    – Sam
    Apr 30 '16 at 1:09
  • \$\begingroup\$ What is Vp and Vq based on in your circuit? \$\endgroup\$
    – Andy aka
    Apr 30 '16 at 10:01
  • \$\begingroup\$ What kind of micro are you using because that might cause headaches when trying to implement the solution which @dmitryvm gave. Also what language are you programming in? \$\endgroup\$
    – crowie
    May 6 '16 at 8:54

This works for an ideal capacitor, i.e. if you can ignore ESR

Let \$I\$ = magnitude of the current through the circuit, \$U_C\$ = magnitude of the voltage across a capacitor, and \$X_C\$ = the reactance of a capacitor (all are the positive real numbers).

As the first step, you can find \$X_C\$: $$X_C = \frac{U_C}{I}$$

Then, using the following relation for the total impedance (as a complex number) $$Z = R - jX_C$$ where \$j\$ is the imaginary unit, you can find the phase angle for the voltage across a capacitor $$\varphi = -\arctan\left(\frac{X_C}{R}\right)$$

As for \$I\$ and \$U_C\$, you can find these magnitudes by averaging ADC samples over whole number of periods and scaling by \$\frac{\pi}{2}\$: $$I = \frac{\pi}{2N}\sum_{i=1}^N |I_i|$$ $$U = \frac{\pi}{2N}\sum_{i=1}^N |U_i|$$

The \$\frac{\pi}{2}\$ factor arises from the proportion between the magnitude and the average of the absolute value for a sine wave. By the way, you can just ignore this factor, since it will be cancelled out in \$X_C = \frac{U_C}{I}\$.

If you can not ignore ESR

Then you can compute the phase shift using linear algebra. For vectors \$\mathbf{v}\$ and \$\mathbf{w}\$

$$\cos(\varphi) = \frac{\mathbf{v}\cdot \mathbf{w}}{\|\mathbf{v}\|\|\mathbf{w}\|}$$

and you can treat the sampled signals as multidimentional vectors, using

$$\mathbf{v}\cdot \mathbf{w} = \sum_{i=1}^N v_i w_i$$ $$\|\mathbf{v}\| = \sqrt{\sum_{i=1}^N v_i^2}$$

(sampling over a whole number of periods)

Substitute \$v_i = U_i\$ and \$w_i = I_i\$ for the final formula

$$\varphi = \arccos\left(\frac{\mathbf{U}\cdot \mathbf{I}}{\|\mathbf{U}\|\|\mathbf{I}\|}\right)$$

where \$U_i\$ is the sampled voltage across a capacitor and \$I_i\$ is the sampled current through the circuit.


In MATLAB or Octave you can try the following:

>> t = linspace(0, 2*pi*10, 100);
>> x = sin(t);
>> y = sin(t + 0.123);
>> phase_shift = acos(dot(x, y)/(norm(x)*norm(y)))
phase_shift =  0.12422

There is some error (0.12422 vs 0.123) due to relatively small number of samples (100).

By the way, \$\cos(-x) = \cos(x)\$ (even function), so you can not determine the sign. This is not a problem, since for a capacitor the sign is always the same.

  • \$\begingroup\$ Ok, that's good, cant wait to get back to work on the method you suggest. As I'm still hazy on details. Your last equation is: phi = arcos ( (U (dot product) I) / (abs(U) * abs(I)) ) Its probably in my texts books when I look at them soon. \$\endgroup\$
    – kvresto
    Apr 30 '16 at 23:27
  • \$\begingroup\$ Or do you mean |U| or |I| = sqrt( sum(i=1, N) U(i)^2 ) \$\endgroup\$
    – kvresto
    May 1 '16 at 0:34
  • \$\begingroup\$ ||U|| means 2-norm, i.e. sqrt( sum(i=1, N) U(i)^2 ). I have wrote this formula in the answer for an abstract vector ||v|| = ... \$\endgroup\$
    – dmitryvm
    May 1 '16 at 9:20
  • \$\begingroup\$ I have edited the answer to include MATLAB/Octave example \$\endgroup\$
    – dmitryvm
    May 1 '16 at 9:35

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.