Use Arduino to measure time constant of a RC circuit with known resistor. Compute capacitance from 500 pF to more than 10,000 uF.
A capacitance meter is an useful test gear. And since my multimeter is too crappy to get a constant reading, I decided to make my own meter, especially for large capacitances. With an Arduino development board, a display and some resistors, the capacitance meter was almost built. It needed proper software to charge and discharge the capacitor, then measure time constant and compute capacitance. A capacitor's value can be determined by placing it either into an L-C oscillator and measuring frequency, either in R-C circuit and measuring time constant. While the first method requires some additional parts and it is difficult in terms of software, it is able to measure small capacitances and also inductors (by using a known value capacitor and calculating the inductor).
This project uses the second method, with RC circuit. If a voltage is applied to a series resistor - capacitor circuit, the latter tends to reach supply voltage at its pins (it charges). The charging needs a time dependant on series resistor and capacitor value. It should be noted that the capacitor draws current as it modifies the voltage across its pins. The following circuit performs both charging and discharging of capacitors. However, measurements are performed only during charging. The discharge function allows Arduino to make multiple measurements of the same capacitor without taking it out of this circuit.
Capacitance meter wired on the breadboard
Although Arduino will charge and discharge the capacitor, do not place charged capacitors in the circuit. They will break the ATmega microcontroller if they hold voltages above 5V or of opposite polarity. Properly discharge your capacitors before measuring them. Let's have a look at the schematic.
Schematic of the Arduino capacitance meter
This is how I wired things. But there is no constraint in maintaining the same wiring scheme. Except for the 10 k resistor that must go to an analog pin, all the other resistors and the display can be wired to any digital pin of the Arduino.
The 220 ohm resistor is only for discharging the capacitor. The lower the value, the faster the discharge is. But this means greater current. With the 5 V supply, the discharge current is maximum 22 mA, which is safe for the microcontroller pin. Do not use a smaller resistor! The 1 kilo ohm resistor is used to charge big (microfarad) capacitors. If this charging happens in less than 1 millisecond, the capacitor is discharged through the 220 ohm resistor. A second attempt to measure the capacitor takes place after disabling the 1 kilo-ohm resistor and enabling 1 mega-ohm resistor. This is suitable for small (nanofarad) capacitors. Again, if charging needs less than 500 microseconds, the most probable cause is that there is no capacitor connected (or less than 500 pF capacitor). It should be noted the loop that checks the analog reading of the pin takes 116 to 128 microseconds on ATmega328. This delay is sampled when there is no capacitor connected and used as correction factor when measuring a capacitor.
The sketch contains a function that charges the capacitor. It sets the corresponding resistor pin as output, high. Then it stores the current micros()
. It enters a while()
loop until capacitor voltage reaches 63.14 percent of supply voltage (that's 646
from a maximum of 1023
). After the loop breaks, the time is stored and the difference between this and the start time is calculated as chargingTime
in microseconds. Charging resistor is disabled and the function returns the adjusted chargingTime
.
long chargeCapacitor(byte resistorPin) { unsigned long startTime = 0; unsigned long stopTime = 0; // display charging sign lcd.setCursor(15, 0); lcd.write(byte(1)); // set charging resistor pinMode(resistorPin, OUTPUT); digitalWrite(resistorPin, HIGH); // start measuring startTime = micros(); while (analogRead(A0) < 646) ; stopTime = micros(); long chargingTime = stopTime - startTime; // disconnect resistor pinMode(resistorPin, INPUT); // set time adjustment if (chargingTime < 500) adjustment = 0 - chargingTime; // clear charging sign lcd.setCursor(15, 0); lcd.write(' '); return (chargingTime + adjustment); }
The adjustment factor for charging time is calculated after each measuring attempt with no capacitor connected. Sampling the analog pin takes more than 100 microseconds. Measuring and autoranging are performed in another function.
void performMeasurement(float &capacity, char &unit) { long chTime = 0; capacity = 0; unit = 'u'; // attempt to charge with the smaller resistor chTime = chargeCapacitor(PIN_UF); // if charging was too fast if (chTime < 1000) { // perform quick discharge pinMode(PIN_DIS, OUTPUT); digitalWrite(PIN_DIS, LOW); // capacitor must be smaller than 1uF // C < 1 uF, R = 330 => Tdis < 5 * 330 * 0.000001 = 1.65 ms // complete discharge occurs in less than 2 ms; let's wait 10 delay(10); pinMode(PIN_DIS, INPUT); // try with the bigger resistor chTime = chargeCapacitor(PIN_NF); unit = 'n'; // switch to nanofarads if (chTime < 500) { // below 500 pF measurement is unreliable adjustment = 0 - chTime; return; } } if (unit == 'u') capacity = chTime / K_RESISTOR; else capacity = chTime / M_RESISTOR; }
Presuming a capacitor is connected to the circuit, an attempt to charge it with the 1 k resistor is made. If it charges in less than 1000 microseconds, maybe it is a nanofarad capacitor. Therefore, it is discharged by setting the discharge resistor pin output, low. With the 220 ohm resistor, five time constants (5T) take less than 2 milliseconds. The function waits 10 milliseconds though, for a complete discharge. The discharge resistor is disabled and a second charge attempt takes place, this time with the 1 M resistor. If charging takes less than 500 microsceonds, then it is presumed no capacitor is connected.
The sketch also contains a discharge function and an average computing function. The averaging takes last 10 measurements and displays average capacitance on the second row of the display.
You know the minimum capacitor value that can be measured: 0.5 nF. But what's the maximum? Charging time is measured using the micros()
function. The value returned by this function overflows in about 70 minutes. Therefore the capacitance meter can count safely times up to a few minutes. The disadvantage is that you have to wait for the measurement to take place. As you test different capacitors, you will notice that the time to measure is proportional with capacitance. For example, a 4700 uF capacitor will charge to 63 percent in 4.7 seconds with the 1 k resistor. And it will discharge a few seconds with the 220 ohm resistor. Add the 0.5 seconds delay between measurements and it means you have to wait a while for a measurement cycle.
The display shows you what is happening to the capacitor. When it's charging you'll see an up arrow displayed in the right. After this, the capacitance is shown. Then a down arrow appears, signifying discharge. And the cycle repeats. For nanofarad capacitors the arrows may not be visible since times are very low.
Since I don't expect the charging resistor to have exact values, I added correction factors. Those are the definitions for M_RESISTOR
and K_RESISTOR
. You will write there the resistor values in megaohms for the first and kiloohms for the second, multiplied by 1000
. These numbers must be float
type, so declare them with a decimal point.
// set here correction factors (resistor value in M and k * 1000.0) #define M_RESISTOR 1055.0 // the value of 1M resistor #define K_RESISTOR 1042.5 // the value of 1k resistor
This project is inspired from an Arduino tutorial. Nick Gammon used different time counting methods to improve the accuracy of the meter. My sketch is available on GitHub.
Hi!
ReplyDeleteWhat is the minimum / maximum value measured by this capacitor?
Do measurement differences occur depending on the electrolytic or fixed capacitor model?
Minimum is 500 pF and there is no limit for maximum as long as you wait for charging. For example, a 10000 uF capacitor charges in 10 seconds and this is the measuring time. There shouldn't be differences between capacitor types.
Delete
DeleteIt looks like an excellent project. I'll test it and keep you up to date.
Good luck in the future!
Thank you. You may read about this project in Romanian language at https://ro.onetransistor.eu/2018/12/capacimetru-cu-functie-de-autoscalare.html.
Delete