The design presented is a capacitance meter, with three 7-segment display output.
It can measure capacitances from 0.1nF up to 999µF.
Wide range, from from 0.1nF up to 999µF.
Only three seven-segment displays
Automatic scale adjustment
Low value update frequency
Four individual scales:
0.1nF to 99.9nF
100nF to 999nF
1.0µF to 99.9µF
100µF to 999µF
See download section for full PDF and eagle files
Counters and output registers
Scale controller, clock syncronizer (and power supply)
This design focus on a few advanced digital/mixed-mode topics, which are important for those starting
in digital electronics:
Clock generation using Schmitt-Trigger inverters
RTL (Register-Tranfer Level)
Clock/pulse synchronization across domains
Signal delays and hazards
Multiplexing signals using high-impedance buses
Principle of operation
How to measure a capacitance
Measuring capacitances is a complex matter. There are a few approaches to this problem, here are some :
Use an RC charger circuit, and measure time.
Measure RC impedance for a specific frequency
In this design, we use a variant of the first approach, by using an RC oscillator based on a schmitt-trigger inverter
RC oscillator based on Schmitt Trigger inverter
We know that this oscillator will generate a square-wave output at frequency:
where K is some sort of constant, R is the resistor value in Ohm, and C the capacitance in Farad. So, if we can measure
the frequency of this oscillator, we have a value which is related to the capacitance measured:
Capacitor voltage and digital output. Taken with my Arduino Oscope
Note that the clock duty cycle is not 50% - that is because we are using an HCT device - it has TTL-compatible inputs, so low-to-high
transitions happen at very low voltage levels.
This constant K is device dependant (the schmitt trigger used) and varies with voltage supply and with temperature.
Also if we take a closer look at last equation, we seee that f is actually inverse proportional to C, so higher C values
give low frequency (f) values. Displaying the frequency will yield a value which is visually not very interesting.
So we have two problems here: the non-constantness of K, and the inverse relation of f in relation to C.
Now, imagine we do not have one oscillator, but two oscillators instead, based on same device (hence sharing almost the same
parameters). On this new oscillator we use the same resistor value, but a different (known) capacitance. We know that
it will oscillate at this given frequency:
Let's now assume we chose a C2 which is smaller than C, the one we want to measure. Say, we are measuring a 10nF capacitor, and
we use a 1nF capacitor as C2. We know then that our oscillators will generate the following frequencies:
They look very simlar, don't they ? What if we try to see how F2 relates to F (by dividing one by another):
Interesting: not only we eliminated K and R, we see something here which is very much useful: 10 - which actually is the value in nF
of the capacitor we want to measure! Here's an image of our clocks:
Overview of the two main clocks - simulation
Overview of the two main clocks - Arduino Oscope
In this image, INCLK is the clock generated by C (the 10nF), and REFCLK is the clock generated by C2 (the 1nF).
If you count the number of REFCLK pulses for a MCLK period, you'll see there are 10 in there. We're getting somewhere.
Now we need to figure out a way to count those 10 pulses. Here we employ a simple trick: we divide the measure clock by 2 (using
a flip-flop), and "gate" the reference clock (meaning, enabling the clock only when some signal is one or zero):
Divided and gated clock
The three clocks - Arduino Oscope
The gated clock - Arduino Oscope
Now we can clearly see the 10 clock pulses (negative) on REFCLKA, and we can also see that MCLK, the divided clock,
is set to one when there are pulses to count, and to zero when they are not.
This means we can use the "edges" of MCLK to reset the counter and to transfer the counter value to some
other place (so that we can count again). [there's another good, even better reason for us to do this, keep on reading - it relates to
letting the counters to settle down before reading them]
And that is exactly what we do.
Counters and output registers
Three 4-bit decimal counters are used to count the number of pulses. Those are synchronous counters, but they are
cascaded very much like a ripple counter (meaning an output from one counter is connected to the clock input of other
- see below for the implications of this king of design - Also note that the EN signal on these 4518 also act as a clock input).
These counters allow us to count from 0 to 999, a range that matches the three digit display we want to use.
In front of our counters we have three 4-bit registers. Those registers are used to "hold" the counter value so that
it can be transferred later to the display drivers.
Updating the display
Running at these high frequencies and updating the output whenever we finish a count is not feasible. The digits might
change very fast in some scenarios due to clock inaccuracies and due to clocks not being phase related - imagine a display
that is constantly changing from 199 to 200, many many times a second - you won't be able to see anything except almost
every segment lit. Due to this we only want to update the display at a lower frequency, so that you can get a clear view of
last measure. In order to accomplish this, we have another clock, which we call the update clock (UPDCLK).
This update clock acts as a pulse to move data from our counters into the registers. But we don't want to move this data while we are
still performing a count, so we need to move this pulse into the MCLK clock domain. The objective is to move data only when we finish
count and we got a update clock event.
The clock synchronization
When update clock falls, the UPDT output will be set to one. When we finish counting (meaning MCLK is falling) this '1' is moved into the
second flip flop, causing the /Q output to become '0'. Since this pin is connected to the first flip-flop reset, the first flip flop will be set to zero.
The outputs will not change until we see another falling edge of the update clock, and the process repeats.
Changing the timebase
As we can clearly see from the use of only 3 decimal counters, we are limited to count from 0 to 999. We want however to
have a very large range. There are a few options to this:
Add more counters
Change the timebase
Adding more counters would be expensive. To measure from 0.1nF to 999999.9nF would require 7 (seven!) counters,
plus we would have to either have also seven 7-segment displays, or to find a fancy way (using ripple blanking for example)
to choose which of those counters would be mapped to our three 7-segment. Tricky, confuse, and would increase a lot the
So we decided to change the timebase instead, meaning, change out reference clock. On typical systems, the user would be
required to switch this reference clock, as you change the voltage range on a classical multimeter. In order to change
the reference clock, we have a "capacitor chooser" circuit, which will place only and only one capacitor on the oscillator
Range - low
Range - high
But we don't want the user to switch the reference clock manually. We want all this to be automatic.
In order to do this, we use an underrun/overrrun detector on our counters. If, by the end of a count cycle (when MCLK is one)
we had an underflow (meaning the counter did not reach "100", in decimal) we try to increase our reference clock. If, on
the same situation, we detect an overflow situation (the counters passed "999") we try to decrease the reference clock.
There's a circuit in place that avoids switching the reference clock to invalid values.
To detect underflow and overflow we have Flip-Flops attached to the relevant lines of the counter, as well as to
MCLK signal. Whenever MCLK does low, we asynchrounously reset both flip flops. Note that underflow is connected to
the inverted output of the flip-flop, meaning that when we reset, underflow is set to "one". When the middle counter
overflows (this is detected when the uppermost signal [Q3] falls from one to zero) the output of underflow will be set to
zero, meaning that no overflow occurred. Similarly, when the highest counter overflows (again, when [Q3] output
of this counter falls from one to zero) we set the overflow flag to one.
To generate the several reference clocks, we use a 4555 demultiplexer, and use some transistors to choose which of the capacitors is to
be connected to the schmitt trigger inverter.
Reference clock generator and switch
In order to switch from one clock to another, we use a counter, from 0 to 3, and some logic to avoid going below zero or above three.
Choosing the right clock
Implications of ripple counter
Using a sort of ripple counter on this design has some implications. The propagation delay of the counters we use is around
240ns (worst case), so it will take a long time for this output to be propagated to the next counter clock.
In order not to miss the final value, we delay the clock a bit using two schmitt-triggers, a small capacitor and a small resistor.