# Introduction

The design presented is a capacitance meter, with three 7-segment display output. It can measure capacitances from 0.1nF up to 999µF.

# Main features

• 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

# Schematics

See download section for full PDF and eagle files

Clock generators

Counters and output registers

Display controller

Scale controller, clock syncronizer (and power supply)

# Design focus

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
• Gated clocks
• Delay lines
• 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 [1]:
• 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 [2] [3]:

RC oscillator based on Schmitt Trigger inverter

### The problem

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.

### The solution

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 design cost.

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 loop.
 Reference capacitor Range - low Range - high Resolution 100pF 0.1nF 99.9nF 0.1nF 1nF 100nF 999nF 1nF 100nF 1.0µF 99.9µF 0.1µF 1µF 10µF 999µF 1µF
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.

Overflow signal

Underflow signal

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.

Clock delay generator

## Tuning and notes

Later. :) But I promise.

### Simulation model

note: I have not yet updated the simulation model, so it might use different parts.
• VHDL tarball, to use with GHDL: download

### Pictures

Soon, I'm soo tired!

# References

All simulations were made with GHDL, and visualized with gtkwave.

# Contacts

You can contact me by email at alvieboy@alvie.com. I'll be glad to answer all your questions.