The standard 3-digit EIA marking code for a 0.1 uF capacitor is 104. This translates to 10 × 10⁴ picofarads (pF), which equals 100,000 pF, or 100 nanofarads (nF), or 0.1 microfarads (µF). While memorizing the 104 code is a rite of passage for every bench technician, relying on memory fails when you are sorting a mixed bin of unmarked or faded components.

In this guide, we will break down the EIA 3-digit capacitor coding system and build a dedicated ESP32-based RC capacitance meter. This tool will not only measure the actual capacitance of your components but also reverse-calculate and display the correct 3-digit EIA code on an OLED screen, eliminating guesswork on the workbench.

The EIA 3-Digit System and the "104" Standard

Ceramic capacitors are too small to print full values like "0.1 µF" on their epoxy coating. Instead, manufacturers use the Electronic Industries Alliance (EIA) 3-digit code. The first two digits represent the significant figures, and the third digit is the multiplier (number of zeros to add), with the base unit always being picofarads (pF).

Bench Rule of Thumb: If the third digit is 4, you are in the 0.1 µF range. If it is 3, you are in the 0.01 µF (10 nF) range. If it is 2, you are in the 1 nF range.
Common EIA Capacitor Codes
EIA Code Calculation (pF) Value in pF Value in nF Value in µ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
224 22 × 10⁴ 220,000 pF 220 nF 0.22 µF
105 10 × 10⁵ 1,000,000 pF 1,000 nF 1.0 µF

For a deeper dive into standard component markings and tolerance tables, the Electronics Tutorials capacitor code guide is an excellent bench reference.

Project Build: ESP32 Capacitance Meter & Code Decoder

We will build a meter using the RC (Resistor-Capacitor) charge time method. The ESP32 drives a GPIO pin HIGH through a known resistor to charge the capacitor. A second GPIO pin configured as an analog input monitors the voltage. By measuring the time it takes to reach 63.2% of the supply voltage (one time constant, τ = R × C), we can calculate the exact capacitance.

Build Specifications

  • Difficulty: Intermediate (Requires basic soldering and Arduino IDE setup)
  • Time to Build: 45 minutes
  • Target Board: ESP32-WROOM-32 DevKit v1 (30-pin or 38-pin variant)

Parts List

  • 1x ESP32-WROOM-32 DevKit v1 (e.g., HiLetgo or NodeMCU-32S)
  • 1x 0.1 µF Ceramic Capacitor (Code 104) for testing
  • 1x 10 kΩ Resistor (1/4W, 1% tolerance) – Charge resistor
  • 1x 1 kΩ Resistor (1/4W, 1% tolerance) – Discharge protection
  • 1x SSD1306 128x64 I2C OLED Display (0.96 inch)
  • Jumper wires and a half-size breadboard

Pin Mapping Table

Component ESP32 GPIO Pin Function
Charge Resistor (10kΩ) GPIO 27 Digital Output (Drives HIGH to charge)
Discharge Resistor (1kΩ) GPIO 26 Digital Output (Drives LOW to discharge)
Capacitor Sense Node GPIO 34 Analog Input (ADC1_CH6)
OLED SDA GPIO 21 I2C Data
OLED SCL GPIO 22 I2C Clock

Step-by-Step Wiring and Assembly

  1. Prepare the Discharge Path: Connect GPIO 26 to the 1 kΩ resistor. Connect the other end of the 1 kΩ resistor to the common sense node on the breadboard.
  2. Prepare the Charge Path: Connect GPIO 27 to the 10 kΩ resistor. Connect the other end of the 10 kΩ resistor to the same common sense node.
  3. Connect the Sense Pin: Run a jumper wire from the common sense node to GPIO 34. Note: GPIO 34 is input-only on the ESP32, making it perfect for ADC readings without internal pull-up interference.
  4. Connect the Capacitor Under Test: Insert one leg of your 104 (0.1 µF) capacitor into the common sense node, and the other leg into the breadboard ground rail.
  5. Wire the OLED: Connect VCC to 3.3V, GND to GND, SDA to GPIO 21, and SCL to GPIO 22.
  6. Verify Connections: Use a multimeter in continuity mode to ensure the sense node is not shorted to ground or 3.3V before applying power.

Complete ESP32 Arduino Code

This code targets the ESP32-WROOM-32 DevKit v1 using the Arduino framework. It utilizes the Adafruit_SSD1306 and Adafruit_GFX libraries for the display. Ensure you have these installed via the Library Manager.

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

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

// --- Display Setup ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// --- RC Constants ---
const float R_CHARGE = 10000.0; // 10k ohms
const float VCC = 3.3;
const int ADC_MAX = 4095;       // ESP32 12-bit ADC
const int THRESHOLD = 2588;     // 63.2% of 4095 (1 time constant)
const unsigned long TIMEOUT_US = 5000000; // 5 second max timeout

void setup() {
  Serial.begin(115200);
  pinMode(PIN_CHARGE, OUTPUT);
  pinMode(PIN_DISCHARGE, OUTPUT);
  
  // Ensure capacitor is discharged at boot
  digitalWrite(PIN_CHARGE, LOW);
  digitalWrite(PIN_DISCHARGE, LOW);
  
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Halt if display fails
  }
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.display();
}

void loop() {
  // 1. Discharge phase
  pinMode(PIN_DISCHARGE, OUTPUT);
  digitalWrite(PIN_DISCHARGE, LOW);
  digitalWrite(PIN_CHARGE, LOW);
  delay(100); // Allow time to fully drain

  // 2. Charge phase and timing
  pinMode(PIN_DISCHARGE, INPUT); // High-Z to avoid parallel resistance
  unsigned long startTime = micros();
  digitalWrite(PIN_CHARGE, HIGH);
  
  int adcVal = 0;
  unsigned long elapsed = 0;
  bool timeout = false;

  while (adcVal < THRESHOLD) {
    adcVal = analogRead(PIN_SENSE);
    elapsed = micros() - startTime;
    if (elapsed > TIMEOUT_US) {
      timeout = true;
      break;
    }
  }

  // 3. Calculate Capacitance
  float capacitance_nF = 0;
  String eiaCode = "---";

  if (timeout || adcVal < 10) {
    Serial.println("Error: ADC read timeout or open circuit.");
    displayError();
  } else {
    // C = t / R  (Result in Farads if t is seconds and R is ohms)
    float time_seconds = (float)elapsed / 1000000.0;
    float capacitance_F = time_seconds / R_CHARGE;
    capacitance_nF = capacitance_F * 1e9;
    
    eiaCode = calculateEIACode(capacitance_nF);
    
    Serial.printf("Measured: %.2f nF | EIA Code: %s\n", capacitance_nF, eiaCode.c_str());
    updateDisplay(capacitance_nF, eiaCode);
  }

  delay(1000); // Wait before next reading
}

String calculateEIACode(float nF) {
  // Convert nF to pF for EIA calculation
  float pF = nF * 1000.0;
  if (pF < 10) return "---";
  
  int multiplier = 0;
  while (pF >= 100) {
    pF /= 10.0;
    multiplier++;
  }
  
  // Round to nearest integer for the first two digits
  int sigFigs = round(pF);
  if (sigFigs > 99) {
      sigFigs /= 10;
      multiplier++;
  }
  
  char code[4];
  snprintf(code, sizeof(code), "%02d%d", sigFigs, multiplier);
  return String(code);
}

void updateDisplay(float nF, String code) {
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Capacitance Meter");
  
  display.setTextSize(2);
  display.setCursor(0, 20);
  char buf[20];
  dtostrf(nF, 5, 1, buf);
  display.print(buf);
  display.println(" nF");
  
  display.setCursor(0, 45);
  display.print("Code: ");
  display.println(code);
  display.display();
}

void displayError() {
  display.clearDisplay();
  display.setTextSize(2);
  display.setCursor(0, 20);
  display.println("TIMEOUT");
  display.setTextSize(1);
  display.setCursor(0, 45);
  display.println("Check Connections");
  display.display();
}

Debugging: First Three Things to Check When It Fails

Capacitance meters are highly sensitive to parasitic capacitance and GPIO state changes. If your meter reads erratically or fails to compile, follow this decision path.

Exact Compilation Error:
error: 'touchRead' was not declared in this scope; did you mean 'touch_pad_read'?

Ranked Causes and Fixes:

  1. ESP32 Arduino Core v3.0.0 API Changes (Most Likely): Many older tutorials use the ESP32's internal touch pins (touchRead()) to measure capacitance. In Core v3.x, Espressif overhauled the touch driver. Fix: The code provided in this article uses the GPIO RC charge method, which completely bypasses the touch API and is immune to this error. If you must use touch pins, you need to migrate to the new touch_pad_read() API and initialize the touch pad driver manually.
  2. ADC Non-Linearity on GPIO 34: The ESP32 ADC is notoriously non-linear near the rails (0V and 3.3V). If your readings are off by 15-20%, you are hitting the ADC deadzones. Fix: Ensure your threshold (63.2%) falls in the linear mid-range of the ADC (which our 2588 threshold does). For higher precision, add a 0.1 µF bypass capacitor directly across the ESP32's 3.3V and GND pins on the breadboard to stabilize the reference voltage.
  3. Parasitic Breadboard Capacitance: Breadboards add roughly 2pF to 5pF of stray capacitance per row. Fix: For measuring very small capacitors (under 100pF), you must subtract a baseline offset in the code. For our 104 (0.1 µF / 100 nF) target, 5pF is mathematically negligible (0.005% error) and can be ignored.

For official documentation on ESP32 ADC behavior and limitations, refer to the Espressif Arduino ADC API documentation.

Extending and Simplifying the Build

How to Extend (Auto-Ranging): The current build uses a fixed 10 kΩ resistor, making it ideal for the 1 nF to 10 µF range. To measure electrolytic capacitors up to 1000 µF, add a relay module or a MOSFET (like the 2N7000) to switch in a 100 Ω charge resistor. You can read a selector switch on a spare GPIO to tell the code which resistor is active, adjusting the R_CHARGE variable dynamically.

How to Simplify (Headless Mode): If you don't want to buy an SSD1306 OLED, strip out the Adafruit_GFX and Adafruit_SSD1306 includes and all display.* function calls. Rely entirely on the Serial.printf() output and use the Arduino IDE's Serial Plotter to visualize the charge curve in real-time.

Frequently Asked Questions

What exactly does the 104 code mean on a 0.1 uF capacitor?

The "104" is a 3-digit EIA standard code. The first two digits (10) are the significant figures, and the third digit (4) is the multiplier (number of zeros). The base unit is picofarads. Therefore, 10 followed by four zeros is 100,000 pF. Since 1,000 pF = 1 nF, and 1,000 nF = 1 µF, 100,000 pF equals 100 nF, which is exactly 0.1 µF.

How do I calculate the value from a 3-digit ceramic capacitor code?

Take the first two digits as your base number. Multiply that number by 10 raised to the power of the third digit. The result is in picofarads (pF). For example, a code of 223 means 22 × 10³ = 22,000 pF, which is 22 nF or 0.022 µF.

Why does my multimeter read my 0.1 uF (104) capacitor as 100nF?

This is not an error; it is a unit conversion. 0.1 µF (microfarads) and 100 nF (nanofarads) are the exact same value. Multimeters often default to the most readable integer unit. Since 1 µF = 1000 nF, 0.1 µF is displayed as 100 nF to avoid decimal points. Both your meter and the capacitor's 104 code are correct.

What do the letters (like Z, M, K, J) after the 104 capacitor code mean?

The letter following the 3-digit code indicates the manufacturing tolerance. For a 104 capacitor, you will frequently see "104Z", "104M", or "104K".

  • Z: +80% / -20% (Very common for cheap decoupling ceramics)
  • M: ±20%
  • K: ±10%
  • J: ±5% (Usually C0G/NP0 dielectric, used in precision RF/timing circuits)
If your ESP32 meter reads a 104Z capacitor at 130 nF, it is still technically within factory specification.