With all the different ways capacitors are labeled, figuring out the values of your capacitors can be challenging. Especially if you don’t have a digital multi-meter to test them. In this tutorial, I’ll show you how to build three different capacitance meters using an Arduino and a couple resistors. After finishing this project, you’ll be able to measure all of your capacitors and label them for future reference.

When I was testing these capacitance meters, I couldn’t find one that was able to accurately measure the full range of commonly used capacitors. One meter would accurately measure values in the 1000 μF range, but it would fail in the nF and pF range. Another capacitance meter was accurate in the nF and pF ranges, but failed in the μF range. So, I’ll show you three different meters that together will cover a range of about 10 pF to 3900 μF.

BONUS: I made a quick start guide for this tutorial that you can download and go back to later if you can’t set this up right now. It covers all of the steps, diagrams, and code you need to get started.

To compare the error in their measurements, I tested the output of each capacitance meter described below against capacitors of known values. This graph shows the range of values each capacitance meter is able to measure accurately:

Before we start building the circuits, let’s get a little background on how we can use the Arduino to measure capacitance…

How the Arduino Can Measure Capacitance

Each Arduino capacitance meter relies on a property of resistor capacitor (RC) circuits- the time constant. The time constant of an RC circuit is defined as the time it takes for the voltage across the capacitor to reach 63.2% of its voltage when fully charged:

Larger capacitors take longer to charge, and therefore will create larger time constants. The capacitance in an RC circuit is related to the time constant by the equation:

Rearranging the equation to solve for capacitance gives:

Each capacitance meter has an RC circuit with known resistor values and an unknown capacitor value. The Arduino will measure the voltage at the capacitor and record the time it takes to reach 63.2% of it’s voltage when fully charged (the time constant). Since the resistance value is already known, we can use the formula above in a program that will calculate the unknown capacitance.

Capacitance Meter for 1 uF to 3900 uF Capacitors

This capacitance meter is one I found on the Arduino.cc website. After testing it, I found that it can measure values from about 0.1 μF to 3900 μF (I didn’t test it above 3900 μF) with reasonable accuracy.

The Circuit

Follow this diagram to set it up:

R1 = 10K Ohms

R2 = 220 Ohms

The Code for Serial Monitor Output

To display the readings on the Arduino serial monitor, connect the Arduino to your PC, open the Arduino IDE and upload this code to it:

#define analogPin 0 #define chargePin 13 #define dischargePin 11 #define resistorValue 10000.0F unsigned long startTime; unsigned long elapsedTime; float microFarads; float nanoFarads; void setup(){ pinMode(chargePin, OUTPUT); digitalWrite(chargePin, LOW); Serial.begin(9600); } void loop(){ digitalWrite(chargePin, HIGH); startTime = millis(); while(analogRead(analogPin) < 648){ } elapsedTime= millis() - startTime; microFarads = ((float)elapsedTime / resistorValue) * 1000; Serial.print(elapsedTime); Serial.print(" mS "); if (microFarads > 1){ Serial.print((long)microFarads); Serial.println(" microFarads"); } else{ nanoFarads = microFarads * 1000.0; Serial.print((long)nanoFarads); Serial.println(" nanoFarads"); delay(500); } digitalWrite(chargePin, LOW); pinMode(dischargePin, OUTPUT); digitalWrite(dischargePin, LOW); while(analogRead(analogPin) > 0){ } pinMode(dischargePin, INPUT); }

The Code for LCD Output

To use this meter with an LCD screen, connect the LCD to your Arduino (see How to Set Up an LCD Display on an Arduino if you need instructions). Pin 11 will be used for the LCD, so wire the capacitance meter using pin 8 instead of pin 11. Here’s the code:

#define analogPin 0 #define chargePin 13 #define dischargePin 8 #define resistorValue 10000.0F #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); unsigned long startTime; unsigned long elapsedTime; float microFarads; float nanoFarads; void setup(){ pinMode(chargePin, OUTPUT); digitalWrite(chargePin, LOW); lcd.begin(16, 2); } void loop(){ digitalWrite(chargePin, HIGH); startTime = millis(); while(analogRead(analogPin) < 648){ } elapsedTime= millis() - startTime; microFarads = ((float)elapsedTime / resistorValue) * 1000; lcd.print(elapsedTime); lcd.print(" mS"); delay(2000); lcd.clear(); delay(500); if (microFarads > 1){ lcd.print(microFarads); lcd.print(" uF"); delay(2000); } else{ nanoFarads = microFarads * 1000.0; lcd.print(nanoFarads); lcd.print(" nF"); delay(2000); } lcd.clear(); digitalWrite(chargePin, LOW); pinMode(dischargePin, OUTPUT); digitalWrite(dischargePin, LOW); while(analogRead(analogPin) > 0){ } pinMode(dischargePin, INPUT); }

Measurement

Now we’re ready to start measuring some capacitors. Insert an unknown capacitor into the breadboard as shown in the diagram above. Then open the serial monitor to see the time constant and capacitance values. These are the readings I got from a 470 μF electrolytic capacitor:

The first column shows the capacitor’s time constant, and the second column is the capacitance measurement. The units will change automatically from microFarads to nanoFarads. If you’re using an LCD to output the readings, the display will alternate between the time constant and the capacitance reading.

You’ll notice with larger capacitors that it takes longer for the Arduino to output a reading. That’s because larger capacitors have larger time constants and therefore take longer to reach 63.2% of their voltage when fully charged. For example, the 3900 μF capacitor I tested took several minutes between readings.

Capacitance Meter for 180 uF to 0.0047 uF Capacitors

This is a “high accuracy” capacitance meter developed by Nick Gammon.

The Circuit

Follow the diagram below to build it:

R1= 10K Ohm

R2= 3.1K Ohm

R3= 1.8K Ohm

The Code for Serial Monitor Output

To use this capacitance meter using the serial monitor for data output, connect the Arduino to your PC, open the Arduino IDE, and upload this code to the Arduino:

const byte pulsePin = 2; const unsigned long resistance = 10000; volatile boolean triggered; volatile boolean active; volatile unsigned long startTime; volatile unsigned long duration; ISR (ANALOG_COMP_vect){ unsigned long now = micros (); if (active){ duration = now - startTime; triggered = true; digitalWrite (pulsePin, LOW); } } void setup (){ pinMode(pulsePin, OUTPUT); digitalWrite(pulsePin, LOW); Serial.begin(9600); Serial.println("Started."); ADCSRB = 0; ACSR = _BV (ACI) | _BV (ACIE) | _BV (ACIS0) | _BV (ACIS1); } void loop (){ if (!active){ active = true; triggered = false; digitalWrite (pulsePin, HIGH); startTime = micros (); } if (active && triggered){ active = false; Serial.print ("Capacitance = "); Serial.print (duration * 1000 / resistance); Serial.println (" nF"); triggered = false; delay (3000); } }

The Code for LCD Output

To use this meter with an LCD output instead of the serial monitor, use the code below. Since the LCD uses pin 2, use pin 8 instead of pin 2 in the diagram above. Upload this code to the Arduino:

#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const byte pulsePin = 8; const unsigned long resistance = 10000; volatile boolean triggered; volatile boolean active; volatile unsigned long startTime; volatile unsigned long duration; ISR (ANALOG_COMP_vect){ unsigned long now = micros (); if (active){ duration = now - startTime; triggered = true; digitalWrite (pulsePin, LOW); } } void setup (){ pinMode(pulsePin, OUTPUT); digitalWrite(pulsePin, LOW); lcd.begin(16, 2); lcd.print("Starting"); delay(1000); lcd.clear(); ADCSRB = 0; ACSR = _BV (ACI) | _BV (ACIE) | _BV (ACIS0) | _BV (ACIS1); } void loop(){ if (!active){ active = true; triggered = false; digitalWrite (pulsePin, HIGH); startTime = micros (); } if (active && triggered){ active = false; lcd.print("Capacitance = "); lcd.setCursor(0,1); lcd.print(duration * 1000 / resistance); lcd.print(" nF"); triggered = false; delay (3000); lcd.clear(); } }

Measurement

This is the reading I got from a 10 nF (0.01 μF) polyester film capacitor:

The value always reads in nF, even with capacitors in the μF range.

Capacitance Meter for 470 uF to 18 pF Capacitors

This capacitance meter had the greatest range of the three I tested. It also had the highest accuracy with smaller capacitors. It’s very easy to make too, no resistors are needed and it only uses two pins from the Arduino.

The Circuit

Follow this diagram to build the meter:

Note: It’s important to make sure the positive lead of the unknown capacitor is connected to pin A2 of the Arduino.

The Code for Serial Monitor Output

This code will output the capacitance readings to the Arduino’s serial monitor:

const int OUT_PIN = A2; const int IN_PIN = A0; const float IN_STRAY_CAP_TO_GND = 24.48; const float IN_CAP_TO_GND = IN_STRAY_CAP_TO_GND; const float R_PULLUP = 34.8; const int MAX_ADC_VALUE = 1023; void setup(){ pinMode(OUT_PIN, OUTPUT); pinMode(IN_PIN, OUTPUT); Serial.begin(9600); } void loop(){ pinMode(IN_PIN, INPUT); digitalWrite(OUT_PIN, HIGH); int val = analogRead(IN_PIN); digitalWrite(OUT_PIN, LOW); if (val < 1000){ pinMode(IN_PIN, OUTPUT); float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val); Serial.print(F("Capacitance Value = ")); Serial.print(capacitance, 3); Serial.print(F(" pF (")); Serial.print(val); Serial.println(F(") ")); } else{ pinMode(IN_PIN, OUTPUT); delay(1); pinMode(OUT_PIN, INPUT_PULLUP); unsigned long u1 = micros(); unsigned long t; int digVal; do{ digVal = digitalRead(OUT_PIN); unsigned long u2 = micros(); t = u2 > u1 ? u2 - u1 : u1 - u2; } while ((digVal < 1) && (t < 400000L)); pinMode(OUT_PIN, INPUT); val = analogRead(OUT_PIN); digitalWrite(IN_PIN, HIGH); int dischargeTime = (int)(t / 1000L) * 5; delay(dischargeTime); pinMode(OUT_PIN, OUTPUT); digitalWrite(OUT_PIN, LOW); digitalWrite(IN_PIN, LOW); float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE); Serial.print(F("Capacitance Value = ")); if (capacitance > 1000.0){ Serial.print(capacitance / 1000.0, 2); Serial.print(F(" uF")); } else{ Serial.print(capacitance, 2); Serial.print(F(" nF")); } Serial.print(F(" (")); Serial.print(digVal == 1 ? F("Normal") : F("HighVal")); Serial.print(F(", t= ")); Serial.print(t); Serial.print(F(" us, ADC= ")); Serial.print(val); Serial.println(F(")")); } while (millis() % 1000 != 0); }

The Code for LCD Output

To output the values to an LCD display, use this code:

#include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const int OUT_PIN = A2; const int IN_PIN = A0; const float IN_STRAY_CAP_TO_GND = 24.48; const float IN_CAP_TO_GND = IN_STRAY_CAP_TO_GND; const float R_PULLUP = 34.8; const int MAX_ADC_VALUE = 1023; void setup(){ pinMode(OUT_PIN, OUTPUT); pinMode(IN_PIN, OUTPUT); lcd.begin(16, 2); } void loop(){ pinMode(IN_PIN, INPUT); digitalWrite(OUT_PIN, HIGH); int val = analogRead(IN_PIN); digitalWrite(OUT_PIN, LOW); if (val < 1000){ pinMode(IN_PIN, OUTPUT); float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val); lcd.setCursor(0,0); lcd.print(F("Capacitance = ")); lcd.setCursor(0,1); lcd.print(capacitance, 3); lcd.print(F("pF ")); lcd.print(val); lcd.print("mS"); } else{ pinMode(IN_PIN, OUTPUT); delay(1); pinMode(OUT_PIN, INPUT_PULLUP); unsigned long u1 = micros(); unsigned long t; int digVal; do{ digVal = digitalRead(OUT_PIN); unsigned long u2 = micros(); t = u2 > u1 ? u2 - u1 : u1 - u2; } while ((digVal < 1) && (t < 400000L)); pinMode(OUT_PIN, INPUT); val = analogRead(OUT_PIN); digitalWrite(IN_PIN, HIGH); int dischargeTime = (int)(t / 1000L) * 5; delay(dischargeTime); pinMode(OUT_PIN, OUTPUT); digitalWrite(OUT_PIN, LOW); digitalWrite(IN_PIN, LOW); float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE); lcd.setCursor(0,0); lcd.print(F("Capacitance = ")); if (capacitance > 1000.0){ lcd.setCursor(0,1); lcd.print(capacitance / 1000.0, 2); lcd.print(F("uF ")); lcd.print(val); lcd.print("mS"); } else{ lcd.setCursor(0,1); lcd.print(capacitance, 2); lcd.print(F("nF ")); lcd.print(val); lcd.print("mS"); } } while (millis() % 1000 != 0); }

Measurement

These are the readings I got from a 22 pF ceramic disc capacitor:

The units will change automatically between pF, nF and μF. The values in parentheses are the time constants for each reading (in milliseconds).

Here’s a video of this tutorial, so you can watch me set up the capacitance meters and see the Arduino measure capacitance in real time:

That’s about all there is to it! I hope you found this project as useful as I did. We also have another tutorial on building an ohm meter with the Arduino. It’s just as useful at this one, so check that out if you’re interested…

Just let me know in the comments if you have any questions or need help setting it up. Also, don’t forget to subscribe to keep updated on all of our future posts!