If you are sorting through a bin of ceramic disc or MLCC capacitors, you will rarely see "10 nF" printed on the casing. Instead, you will see a three-digit code. The direct answer is that the 10 nF capacitor code is 103.

The first two digits (10) represent the significant figures, and the third digit (3) is the multiplier, indicating the number of zeros to add in picofarads (pF). Therefore, 10 × 10³ pF = 10,000 pF, which converts to 10 nF (or 0.01 µF). In this guide, we will break down the theory behind these codes, the RC time-constant math used to measure them, and build a complete ESP32-based capacitance meter to verify your components on the bench.

Capacitor Code Reference Chart

Before we build the tester, here is a quick reference table for common capacitor codes in the nanofarad range. This follows the IEC 60062 standard for marking passive components.

3-Digit Code Calculation (pF) Picofarads (pF) Nanofarads (nF) Microfarads (µF)
101 10 × 10¹ 100 pF 0.1 nF 0.0001 µF
102 10 × 10² 1,000 pF 1 nF 0.001 µF
103 10 × 10³ 10,000 pF 10 nF 0.01 µF
104 10 × 10⁴ 100,000 pF 100 nF 0.1 µF
105 10 × 10⁵ 1,000,000 pF 1,000 nF 1.0 µF

Project: ESP32 Capacitance Meter & Code Decoder

To verify if a "103" marked capacitor is actually 10 nF (and to decode unknown caps), we will build a meter using the RC charge-time method. This project targets the ESP32-WROOM-32 DevKit V1 (30-pin variant).

Difficulty Rating: 3/5 (Requires basic I2C wiring and uploading Arduino C++)
Time to Build: 45 minutes
Cost: ~$12 USD (assuming you already own a breadboard and jumper wires)

Parts List

  • Microcontroller: ESP32-WROOM-32 DevKit V1 (30-pin, Type-C USB)
  • Display: 0.96" SSD1306 I2C OLED (128x64, 4-pin header)
  • Charge Resistor: 10kΩ 1/4W Metal Film (1% tolerance)
  • Discharge Resistor: 220Ω 1/4W Metal Film
  • Test Subject: 103 (10 nF) Ceramic Capacitor
  • Hardware: Half-size breadboard, male-to-male jumper wires

Pin Mapping Table

Component Component Pin ESP32 GPIO Notes
SSD1306 OLED GND GND Common ground
SSD1306 OLED VCC 3V3 Do NOT use 5V (VIN)
SSD1306 OLED SCL GPIO 22 Default I2C Clock
SSD1306 OLED SDA GPIO 21 Default I2C Data
Charge Resistor (10k) Side A GPIO 27 Drives HIGH to charge cap
Charge Resistor (10k) Side B - Connects to Cap (+) and Sense Pin
Sense Wire - GPIO 26 Reads digital HIGH threshold
Discharge Resistor (220) Side A GPIO 25 Drives LOW to discharge cap
Discharge Resistor (220) Side B - Connects to Cap (+)
Capacitor Under Test Leg 1 (+) - Junction of R_charge, R_discharge, Sense
Capacitor Under Test Leg 2 (-) GND Common ground

Wiring and Charge-Time Measurement Theory

Standard multimeters struggle to accurately read small nanofarad values due to stray probe capacitance. Our ESP32 tester uses the ESP32's digital GPIO threshold and the RC time constant formula to measure the capacitor.

When a capacitor charges through a resistor, the voltage across it follows the equation:

V(t) = VCC × (1 - e-t/RC)

The ESP32 digital input registers a logic HIGH (VIH) at approximately 75% of VCC (0.75 × 3.3V = 2.475V). If we set V(t) to 0.75 VCC, the math simplifies beautifully:

0.75 = 1 - e-t/RC
e-t/RC = 0.25
-t/RC = ln(0.25) ≈ -1.3863
t = 1.3863 × R × C

By measuring the time (t) in microseconds it takes for GPIO 26 to read HIGH after GPIO 27 goes HIGH, we can solve for C: C = t / (1.3863 × R). For a 10kΩ resistor and a 10 nF (103) capacitor, the expected charge time is roughly 138.6 µs.

Complete ESP32 Arduino Code

Flash this code using the Arduino IDE. Ensure you have the Adafruit_SSD1306 and Adafruit_GFX libraries installed via the Library Manager. This code includes I2C error handling and stray capacitance calibration.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// --- Pin Definitions ---
#define PIN_CHARGE   27
#define PIN_SENSE    26
#define PIN_DISCHARGE 25

// --- OLED Definitions ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET   -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// --- Measurement Constants ---
const float RESISTANCE_OHMS = 10000.0; // 10k charge resistor
const float TIME_CONSTANT = 1.38629;   // -ln(0.25)
const float CAL_FACTOR = 1.04;         // Calibrate for stray breadboard capacitance

void setup() {
  Serial.begin(115200);
  delay(500);

  // Initialize I2C OLED with error handling
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("[ERROR] SSD1306 allocation failed. Check I2C wiring."));
    while(true) { delay(100); } // Halt execution
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println("Capacitance Meter");
  display.println("Target: 103 (10nF)");
  display.display();

  // Configure GPIOs
  pinMode(PIN_CHARGE, OUTPUT);
  pinMode(PIN_DISCHARGE, OUTPUT);
  pinMode(PIN_SENSE, INPUT);
  
  digitalWrite(PIN_CHARGE, LOW);
  digitalWrite(PIN_DISCHARGE, LOW);
}

void loop() {
  // 1. Discharge the capacitor completely
  pinMode(PIN_DISCHARGE, OUTPUT);
  digitalWrite(PIN_DISCHARGE, LOW);
  pinMode(PIN_CHARGE, OUTPUT);
  digitalWrite(PIN_CHARGE, LOW);
  delay(5); // 5ms discharge settle time

  // 2. Start charging and timing
  unsigned long startTime = micros();
  digitalWrite(PIN_CHARGE, HIGH);
  
  // 3. Wait for sense pin to cross V_IH threshold (~75% VCC)
  while(digitalRead(PIN_SENSE) == LOW) {
    // Timeout protection for open circuits or massive caps
    if(micros() - startTime > 5000000) { 
      Serial.println("Timeout: Cap too large or missing.");
      break;
    }
  }
  unsigned long endTime = micros();
  unsigned long chargeTime = endTime - startTime;

  // 4. Calculate Capacitance
  float capacitance_f = (float)chargeTime / (TIME_CONSTANT * RESISTANCE_OHMS);
  capacitance_f *= CAL_FACTOR; // Apply stray cap calibration
  
  float capacitance_nf = capacitance_f * 1000000000.0; // Convert to nF
  
  // 5. Decode the 3-digit code
  int code = 0;
  if (capacitance_nf >= 1.0 && capacitance_nf < 100000.0) {
    int pF = (int)(capacitance_nf * 1000.0);
    int zeros = 0;
    while(pF >= 100) { pF /= 10; zeros++; }
    code = (pF * 10) + zeros;
  }

  // 6. Output to Serial and OLED
  Serial.printf("Time: %lu us | Cap: %.2f nF | Code: %d\n", chargeTime, capacitance_nf, code);
  
  display.clearDisplay();
  display.setCursor(0,0);
  display.setTextSize(1);
  display.println("Measured Value:");
  display.setTextSize(2);
  display.printf("%.1f nF\n", capacitance_nf);
  display.setTextSize(1);
  display.println("\nDecoded 3-Digit Code:");
  display.setTextSize(2);
  display.printf("%d\n", code);
  display.display();

  delay(1000);
}

Debugging: I2C Bus Lockups and ETIMEDOUT Errors

When working with I2C OLEDs on the ESP32, the most common point of failure is the I2C bus hanging during initialization. If your serial monitor outputs the following exact error string, your ESP32 has failed to communicate with the SSD1306 controller:

[E][Wire.cpp:498] requestFrom(): i2cWriteReadNonStop returned Error -1

Ranked Causes for Error -1

  1. Missing I2C Pull-up Resistors: Many cheap, generic SSD1306 breakout boards omit the required 4.7kΩ pull-up resistors on SDA and SCL. The ESP32's internal pull-ups are too weak to drive the bus capacitance reliably.
  2. 5V VCC on a 3.3V Logic Bus: Wiring the OLED VCC to the ESP32's 5V (VIN) pin while the SDA/SCL lines remain at 3.3V logic can cause the OLED's internal logic to lock up or back-feed the ESP32 GPIOs, triggering a brownout.
  3. Incorrect GPIO Assignment: Using GPIOs that are tied to the ESP32's internal flash SPI (e.g., GPIO 6-11) or strapping pins that are pulled low at boot.

The First Three Things to Check When It Fails

  1. Verify VCC Voltage: Ensure the OLED VCC is wired to the ESP32's 3V3 pin, not VIN or 5V.
  2. Run an I2C Scanner: Upload a standard "I2C Scanner" sketch. If the scanner also hangs or returns no devices, your hardware wiring is at fault, not the capacitance meter code.
  3. Add External Pull-ups: Solder or breadboard two 4.7kΩ resistors between SDA and 3.3V, and SCL and 3.3V. This resolves 90% of ESP32 I2C Error -1 issues.

Extending and Simplifying the Build

How to Simplify: If you do not have an SSD1306 OLED on hand, simply delete the Adafruit_SSD1306 includes, remove the display.* calls from the code, and rely entirely on the Serial.printf() output in the Arduino IDE Serial Monitor. The core measurement logic remains identical.

How to Extend: This current build uses a fixed 10kΩ resistor, making it highly accurate for the 1 nF to 100 nF range (including our 103 target). To build an auto-ranging meter capable of measuring from 10 pF up to 1000 µF, replace the single charge resistor with a CD4051 analog multiplexer. You can use three ESP32 GPIOs to switch between 1kΩ, 100kΩ, and 1MΩ resistors on the fly, adjusting the RESISTANCE_OHMS variable in code based on the measured charge time.

Frequently Asked Questions

Is a 103 capacitor always exactly 10 nF?

No. The "103" code only dictates the nominal value. The actual capacitance depends on the tolerance and dielectric material. A standard Y5V or Z5U ceramic capacitor might have a tolerance of -20% to +80%, meaning your 10 nF cap could measure anywhere from 8 nF to 18 nF. For precision timing or filtering circuits, always look for C0G (NP0) dielectric capacitors, which hold a strict ±5% tolerance and remain stable across temperature variations, as noted in Murata's MLCC specifications.

What does the letter after the 103 code mean?

You will often see markings like "103K" or "103M". This letter indicates the tolerance of the capacitor. "K" stands for ±10%, "M" stands for ±20%, and "J" stands for ±5%. If you are building an RC oscillator where the 10 nF capacitor sets the frequency, a 103J is vastly superior to a 103M.

Why do I see 10 nF (103) capacitors on ESP32 I2C lines?

You should never use a 10 nF capacitor as an I2C pull-up (pull-ups must be resistors). However, hardware engineers sometimes place a 10 nF (103) capacitor between the SDA/SCL lines and GND to act as a low-pass filter, suppressing high-frequency EMI noise. Be warned: the I2C specification limits total bus capacitance to 400 pF. Adding a 10,000 pF (10 nF) capacitor to an I2C bus will completely destroy the signal rise times, causing the exact Error -1 I2C lockups discussed above. Keep 103 caps on power rails, not data lines.

Can I measure a 103 capacitor with a standard multimeter?

Most basic handheld multimeters (like the standard Fluke 115 or cheap ANENG models) do not have a dedicated capacitance setting, or if they do, the lowest range is usually 10 nF or 100 nF with poor resolution. Measuring a 10 nF capacitor on a standard DMM often yields wildly inaccurate readings due to the capacitance of the test leads themselves (which can easily be 50-100 pF). The ESP32 charge-time method outlined in this project bypasses lead capacitance issues by measuring the component directly on the breadboard junction.