Capacitance measurement with AVR (simple, fast)

09 Jul 2020 - tsp
Last update 10 Jul 2020

Just for reference - if you want to know how to calculate with frequency dependent impedance and where the complex terms used come from see Where does complex impedance come from?.

These days I’ve had the requirement to periodically measure some capacitance (or to be exact multiple capacitors in the range of about 10-500 pF) in a programmatic fashion. To perform measurement of capacitance there is a variety of possible solutions. The most common solutions are:

• Using a alternating current Wheatstone bridge. This is one of the most accurate and elegant solutions that can be done using either a voltage measurement or - by applying an variable capacitance or variable inductance - in an analog way by zeroing measured voltage in the middle tap of the bridge.
• Measuring the time constant of a simple RC network. This works pretty well as long as you’ve got accurate timing (which is easy for micro-controllers) and stable or temperature compensated resistors. The main problem with small capacitance is the rather low time constant as well as temperature drift of the used resistors.
• Voltage measurement inside a series connection of capacitors while applying DC voltage after stabilization.

Since the first method requires at least four components per channel, the second one requires high time resolution to detect small fluctuations and high precision for the ohmic resistance. The cheapest method available for this particular case was the series connection of two capacitors - or when exploiting parasitic capacitance even only the capacitance under test. It was also the easiest that could be implemented on an AVR microcontroller that required the least amount of external components.

Series connection of capacitors

First let’s look at the series connection of two capacitors. As one knows the capacitance $C$ is the proportional factor between the charge $Q(t)$ collected on a capacitor an the applied potential (voltage) $U(t)$.

[ Q(t)=C*U(t) ]

It’s also well known that current is the time derivative or the charge (i.e. a measure for the charge carriers flowing through a given volume in a given time):

[ \frac{\partial Q}{\partial t} = I(t) \\ \to Q(t) = \int I(t) \text{d}t \\ \to \int I(t) \text{d}t = C * U(t) ]

In a series connection of two capacitors the total voltage $U_g$ is the sum of both partial voltage $U_1$ and $U_2$ as with any conservative potential.

[ U_g = U_1 + U_2 ]

[ U_1(t) = \frac{1}{C_1} * \int I(t) \text{d}t \\ U_2(t) = \frac{1}{C_2} * \int I(t) \text{d}t \\ \to U_g = (\frac{1}{C_1} + \frac{1}{C_2}) * \int I(t) \text{d}t \\ \to \int I(t) \text{d}t = \frac{U_g}{\frac{1}{C_1} + \frac{1}{C_2}} \\ \to U_1(t) * C_1 = \frac{U_g}{\frac{1}{C_1} + \frac{1}{C_2}} \\ U_1 * C_1 = \frac{U_g}{\frac{C_2 + C_1}{C_1*C_2}} \\ U_1 * C_1 = \frac{C_1 * C_2}{C_2 + C_1} * U_g \\ U_1 = \frac{C_2}{C_2 + C_1} * U_g \\ \frac{U_1}{U_g} * (C_2 + C_1) = C_2 \\ \frac{U_1}{U_g} * C_2 + \frac{U_1}{U_g} * C_1 = C_2 \\ C_1 * \frac{U_1}{U_g} = C_2 - \frac{U_1}{U_g} * C_2 \\ C_1 * \frac{U_1}{U_g} = C_2 * (1 - \frac{U_1}{U_g}) \\ C_2 = C_1 * \frac{\frac{U_1}{U_g}}{1 - \frac{U_1}{U_g}} \\ C_2 = C_1 * \frac{U_1}{U_g - U_1} ]

As one can see one can simply use the measurement or knowledge of the total voltage $U_g$ and the tap voltage between both capacitors $U_1$.

This can easily be implemented using two analog ports of the AVR. Simply apply a known voltage to $A_2$, wait for stabilization and measure the voltage at $A_1$. With a well known value of $C_1$ the unknown capacitance $C_2$ can be measured. Unfortunately there is a drawback - the capacitance $C_1$ is of course not the only capacitance that’s connected in series to $C_2$. The analog input is a high impedance input but it of course also has some gate capacitance that one has to account for. And in case one uses analog ports of the same microcontroller there is additional coupling between both ports parallel to the test capacitance.

This parasitic capacitance in series can easily be compensated by simply calibrating the analogue ADC counts with some known capacitance if they’re available.

Reducing the number of components

Of course the parasitic capacitance leads to an interesting question - could this capacitor be used instead of $C_1$? The usage of the internal gate and board capacitance instead of a discrete component further reduces the amount of required parts.

Another modification would be the usage of an digital output pin to apply the total potential. On the other hand the usage of the internal capacitance leads to a symmetric layout so one can alternate the measurement direction easily - which can be interesting in case one has to use corroding electrodes (for example when using exposed metal electrodes in wet baths) or in case one tries to use different pairs of electrodes to form the capacitors.

Implementation

The basic measurement flow is thus:

• Set the input pin to input mode ($A_1$)
• Set the output pin to output mode ($A_2$)
• Apply supply voltage (near 5V when using an AVR) to the supply pin ($A_2$)
• Stabilize (Charging the capacitors). As each clock cycle on the AVR is 62.5ns long even at 16 MHz and each ADC clock cycle is 128 times that long - i.e. 125 kHz or 8 microseconds - one can assume that each 13 clock cycle taking measurement process takes about 100 microseconds. This should be more than sufficient for the charging process to stabilize. So one can simply perform the measurement immediately after configuring the output.

In case one wants to discharge the capacitor in a clean state:

• Set the output pin to low to discharge the capacitor
• Set the input pin ($A_1$) to output mode and set to low
• Set both pins to input mode

Of course depending on how one wants to implement measurement only swapping pin states that are needed is possible.