Capacitance measurement with AVR (simple, fast)
09 Jul 2020 - tsp
Last update 10 Jul 2020
6 mins
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
]
This leads to
[
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.
This article is tagged: Electronics, Measurement, Programming, AVR