The "102" Mystery: Decoding the 1nF Capacitor Code

If you are digging through your component bins for a 1nF capacitor, the standard 3-digit EIA (Electronic Industries Alliance) code you need to look for is 102.

Here is the exact math: the first two digits represent the significant figures (10), and the third digit is the multiplier in picofarads (pF). A multiplier of 2 means you add two zeros. Therefore, 10 × 10² pF = 1000 pF. Since 1000 pF equals 1 nanofarad (nF) or 0.001 microfarads (µF), a "102" marking is your definitive 1nF capacitor code. You will often see a trailing letter like "102J" or "102K"—this indicates the tolerance (J = ±5%, K = ±10%, M = ±20%). For a deep dive into standard markings, the SparkFun capacitor tutorial provides an excellent baseline on physical packaging and codes.

In embedded systems, 1nF capacitors are the workhorses of signal integrity. They act as I2C line filters to tame high-frequency ringing, serve as snubbers for PWM-driven inductive loads, and provide anti-aliasing for ADC sample-and-hold circuits. But reading the code is only step one. Assuming a "102" capacitor will behave exactly as 1nF in your circuit is a classic bench mistake, primarily due to dielectric physics and parasitic effects. To solve this, we are going to build an automated verifier.

Decision Matrix: Picking the Right 1nF (102) Dielectric

Not all 102 capacitors are created equal. The dielectric material dictates how the capacitor reacts to voltage, temperature, and aging. Use this decision path to select the exact part you need for your embedded build.

Dielectric Code Temp Range Voltage Coefficient (DC Bias) Best Embedded Application
C0G / NP0 -55 to 125°C Near Zero (Stable) Timing circuits, I2C filtering, ADC anti-aliasing
X7R -55 to 125°C High (Loses up to 50% cap at rated voltage) General decoupling, power rail bypass
Y5V -30 to 85°C Extreme (Loses up to 80% cap with heat/voltage) Bulk bypass where exact value doesn't matter
The Decision Path:
  • If your 1nF capacitor is setting a time constant (RC oscillator, PWM dead-time) or filtering a precision analog signal You must use C0G/NP0.
  • If your 1nF capacitor is shunting high-frequency noise to ground on a 3.3V or 5V digital rail X7R is acceptable and cheaper.
  • If you are operating above 50°C ambient or dealing with sensitive I2C rise-times Never use Y5V.

Concrete Default Pick: For 95% of embedded sensor and I2C debugging, buy the KEMET C315C102J1G5TA (C0G, 1nF, 50V, 5% tolerance, through-hole). It costs roughly $0.15 in singles and guarantees your time constants won't drift when your enclosure heats up.

Project Build: ESP32 RC Decay Capacitor Verifier

To prove your "102" capacitor is actually 1nF (and not a degraded 800pF or a mislabeled 10nF), we will build an RC decay tester. The ESP32 will charge the capacitor, cut the power, and measure the time it takes to discharge through a known resistor. According to the Espressif Arduino Core ADC documentation, using the factory-calibrated millivolt reading function is critical here to bypass the ESP32's notorious raw ADC non-linearity.

Difficulty: 2/5 | Time: 30 Minutes

Parts List

  • MCU: ESP32-DevKitC V4 (featuring the ESP32-WROOM-32 module)
  • Resistor: 2.2MΩ 1% Metal Film Resistor (Provides a ~2.2ms time constant, perfect for MCU timing)
  • Test Subject: 1nF (Code 102) Capacitor
  • Hardware: Standard 830-point solderless breadboard, male-to-male jumper wires

Pin Mapping Table

ESP32 Pin Function Connection Target
GPIO 27 Charge / Discharge Trigger 2.2MΩ Resistor (Other end to Cap +)
GPIO 34 Analog Sense (ADC1_CH6) Direct to Cap + (Junction of Resistor and Cap)
GND Circuit Ground Direct to Cap -

Complete ESP32 Verification Code

This code targets the ESP32-WROOM-32 on a DevKitC V4 board. It requires ESP32 Arduino Core v2.0.0 or higher to utilize analogReadMilliVolts(). Upload this via the Arduino IDE (Board: "ESP32 Dev Module").

#include <Arduino.h>

// Pin Definitions for ESP32-WROOM-32
#define CHARGE_PIN   27
#define SENSE_PIN    34  // ADC1_CH6 (Input only, no pull-up conflicts)

// Circuit Constants
#define RESISTOR_OHMS 2200000UL  // 2.2 Megohms
#define TARGET_MV     1214       // 3300mV * 0.368 (1 Time Constant tau)
#define TIMEOUT_US    50000      // 50ms max wait to prevent infinite loops

void setup() {
  Serial.begin(115200);
  delay(1000); // Allow serial monitor to connect
  
  pinMode(CHARGE_PIN, OUTPUT);
  pinMode(SENSE_PIN, INPUT);
  
  // Ensure capacitor is fully discharged at startup
  digitalWrite(CHARGE_PIN, LOW);
  delay(100);
  
  Serial.println("ESP32 1nF (102) Capacitor Verifier Ready.");
  Serial.println("Place capacitor on breadboard and press reset to test.");
}

void loop() {
  // Step 1: Charge the capacitor to 3.3V
  digitalWrite(CHARGE_PIN, HIGH);
  delay(15); // 15ms is >5x tau (2.2ms), ensuring 99.3% charge
  
  // Step 2: Begin discharge and start timer
  unsigned long startTime = micros();
  digitalWrite(CHARGE_PIN, LOW); // Pulling LOW discharges through the 2.2M resistor
  
  unsigned long elapsedTime = 0;
  bool thresholdReached = false;
  
  // Step 3: Poll ADC until voltage drops to 36.8% (1 tau)
  while ((micros() - startTime) < TIMEOUT_US) {
    int currentMV = analogReadMilliVolts(SENSE_PIN);
    
    // Error Handling: Check for short circuit (starts near 0V)
    if (currentMV < 100 && (micros() - startTime) < 50) {
      Serial.println("ERROR: SHORT_CIRCUIT - Sense pin reads < 100mV immediately.");
      delay(3000);
      return;
    }
    
    if (currentMV <= TARGET_MV) {
      elapsedTime = micros() - startTime;
      thresholdReached = true;
      break;
    }
  }
  
  // Step 4: Calculate and Output Results
  if (!thresholdReached) {
    Serial.println("ERROR: RC_TIMEOUT - Voltage did not drop below 1214mV within 50ms.");
  } else {
    // tau = R * C  =>  C = tau / R
    // elapsedTime is in microseconds. R is in Ohms. Result is in microfarads.
    // Multiply by 1000 to convert microfarads to nanofarads.
    double cap_nF = ((double)elapsedTime / (double)RESISTOR_OHMS) * 1000.0;
    
    Serial.printf("Time Constant (tau): %lu us\n", elapsedTime);
    Serial.printf("Measured Capacitance: %.2f nF\n", cap_nF);
    
    if (cap_nF >= 0.90 && cap_nF <= 1.10) {
      Serial.println("PASS: Within 10% of 1nF (102) target.");
    } else {
      Serial.println("FAIL: Outside 10% tolerance. Check dielectric drift or part code.");
    }
  }
  
  // Wait before next test cycle
  delay(2000);
}

Debugging: When the Verifier Throws a Timeout Error

When testing unknown bin pulls, the serial monitor will occasionally halt on this exact string:

ERROR: RC_TIMEOUT - Voltage did not drop below 1214mV within 50ms.

This means the capacitor held its charge far longer than the 2.2ms time constant we programmed. Here are the ranked causes, from most likely to least likely:

  1. Wrong Capacitor Code Grabbed: You accidentally picked a 103 (10nF) or 104 (100nF) instead of a 102 (1nF). A 100nF capacitor with a 2.2MΩ resistor yields a 220ms time constant, which will easily blow past our 50ms software timeout.
  2. Breadboard Parasitics / Moisture: High-impedance circuits (2.2MΩ) are highly susceptible to stray leakage. If your fingers are touching the breadboard traces, or if the flux residue is humid, the leakage current can skew the ADC decay curve.
  3. Resistor Value Error: You used a 22MΩ resistor instead of 2.2MΩ. Always verify high-value resistors with a DMM before inserting them; color bands on 1% metal film resistors can be tricky to read under bench lighting.
The First 3 Things to Check When It Fails:
  1. Verify the Resistor: Pull the resistor and measure it with your multimeter. It must read between 2.15MΩ and 2.25MΩ.
  2. Re-read the Capacitor Code: Use a magnifying glass. Ensure the third digit is a 2 (10 x 100 = 1000pF). If it's a 3 or 4, you have the wrong part.
  3. Check for Breadboard Shorts: Remove the capacitor. Measure the resistance between the SENSE_PIN row and GND on the breadboard. It should read infinite (OL). If it reads a few megaohms, your breadboard contacts are dirty or shorted.

Extending and Simplifying the Build

This baseline verifier is designed for quick bench checks, but you can adapt it based on your lab needs.

How to Simplify

If you don't have a 2.2MΩ resistor on hand, you can simplify the build by using the ESP32's internal pull-up resistors. By setting the charge pin to INPUT_PULLUP (which engages an internal ~45kΩ resistor) and timing the charge curve instead of the discharge curve, you can eliminate external resistors entirely. However, be warned: internal pull-ups have up to a 30% tolerance variance between chips, meaning your capacitance readings will only be accurate to within ±30%. This is fine for sorting 1nF from 100nF, but useless for verifying a 5% tolerance C0G part.

How to Extend

To turn this into a permanent bench tool, wire an SSD1306 128x64 I2C OLED to GPIO 21 (SDA) and GPIO 22 (SCL). Use the Adafruit_SSD1306 library to print the measured nanofarads directly to the screen. Furthermore, if you want to test larger electrolytic capacitors (e.g., 10µF to 1000µF), the 2.2MΩ resistor will cause the test to take minutes. Add a 2N2222 NPN transistor to switch a 100Ω power resistor to ground, allowing the ESP32 to safely dump large capacitors in milliseconds without exceeding the 40mA absolute maximum current limit of the ESP32's GPIO pins.