In electronics, the term capacitance code carries a dual meaning. On the workbench, it refers to the standardized 3-digit EIA (Electronic Industries Alliance) marking printed on ceramic capacitors (e.g., '104' for 100nF). On the breadboard, it refers to the embedded firmware used to measure, verify, and decode those physical components. This guide bridges both domains: we will decode the physical markings and then build an automated capacitance meter using the ESP32's internal touch sensor peripheral to verify them.

Direct Answer: A physical 3-digit capacitance code uses the first two digits as significant figures and the third as a multiplier in picofarads (pF). For example, 104 = 10 × 10^4 pF = 100,000 pF (100 nF). To measure this electronically, the ESP32-WROOM-32 utilizes its internal touch sensor RC oscillator, where added external capacitance lowers the raw touchRead() count value.

The Physical Capacitance Code: EIA Standards Explained

Before writing firmware to measure capacitance, you must understand what you are measuring. Most through-hole and SMD ceramic capacitors are too small to print their actual values. Instead, they use a 3-digit code defined by EIA standards, alongside a letter indicating tolerance.

Printed CodeSignificant DigitsMultiplier (10^x)Value in pFValue in nF / µF
1011010^1100 pF0.1 nF
1021010^21,000 pF1 nF
1031010^310,000 pF10 nF
1041010^4100,000 pF100 nF (0.1 µF)
2222210^22,200 pF2.2 nF
4734710^347,000 pF47 nF

Tolerance Letters: You will often see a letter following the 3-digit code. J = ±5%, K = ±10%, and M = ±20%. A capacitor marked '104K' is a 100nF capacitor with a 10% tolerance, meaning its actual measured capacitance can legally range from 90nF to 110nF. For a deep dive into component tolerances and derating, refer to the Murata Ceramic Capacitor Catalog.

Hardware Parts List & Pin Mapping

To build a verifier that reads these components, we will use the ESP32's dedicated touch sensor hardware. Unlike standard GPIO RC-charge methods, the ESP32 touch peripheral uses an internal oscillator that measures the charge/discharge time of the pin's parasitic capacitance plus any external capacitance attached to it.

Required Components

  • Microcontroller: ESP32-WROOM-32 DevKit v1 (30-pin or 38-pin variant)
  • Display: SSD1306 128x64 I2C OLED (0.96 inch)
  • Test Subjects: Assorted ceramic capacitors (10pF to 1µF)
  • Probe: Single female-to-male jumper wire (keep under 3 inches to minimize parasitic baseline)
  • Breadboard & Jumper Wires

Pin Mapping Table

ComponentPin / LabelESP32 GPIONotes
SSD1306 OLEDVCC3V3Do not use 5V on 3.3V OLED variants
SSD1306 OLEDGNDGNDCommon ground
SSD1306 OLEDSCLGPIO 22Default I2C Clock
SSD1306 OLEDSDAGPIO 21Default I2C Data
Capacitor ProbeTouch T0GPIO 4Must be a touch-capable pin
Parasitic Capacitance Warning: The ESP32 touch pins are highly sensitive. A standard 6-inch jumper wire adds roughly 15-30 pF of parasitic capacitance. For accurate low-value measurements (under 50pF), solder a small header pin directly to the ESP32 GPIO4 pad and insert the capacitor lead directly into the header.

The ESP32 Capacitance Measurement Code

The following C++ code targets the ESP32-WROOM-32 DevKit v1 using the Arduino framework. It initializes the I2C OLED, reads the raw touch sensor data, applies a baseline subtraction to account for parasitic PCB/wire capacitance, and converts the delta into an estimated picofarad (pF) reading.

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

// --- Pin Definitions ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET   -1
#define SCREEN_ADDRESS 0x3C
#define TOUCH_PIN 4  // GPIO4 corresponds to Touch0 (T0)

// --- Calibration Constants ---
// These require empirical tuning for your specific board and probe wire.
// The ESP32 touchRead() value DECREASES as capacitance INCREASES.
const int BASELINE_READING = 85;  // Raw reading with NO capacitor attached
const float PF_PER_UNIT = 2.5;    // Approximate pF change per raw unit drop

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(115200);
  delay(500);
  
  // Initialize I2C OLED with Error Handling
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    // Halt execution to prevent I2C bus lockups in the main loop
    while(true) { 
      delay(1000); 
    }
  }
  
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println("Capacitance Meter");
  display.println("Calibrating...");
  display.display();
  
  // Auto-calibrate baseline on startup (ensure no capacitor is connected!)
  long sum = 0;
  for(int i=0; i<50; i++) {
    sum += touchRead(TOUCH_PIN);
    delay(10);
  }
  // Note: In a production build, you would store this in EEPROM/NVS.
}

void loop() {
  // Read touch sensor multiple times and average to reduce noise
  long rawSum = 0;
  for(int i=0; i<20; i++) {
    rawSum += touchRead(TOUCH_PIN);
  }
  int rawAvg = rawSum / 20;
  
  // Calculate capacitance
  // Because higher capacitance = lower raw value, we subtract raw from baseline
  int delta = BASELINE_READING - rawAvg;
  float capacitance_pF = 0;
  
  if(delta > 2) { // Threshold to ignore minor noise fluctuations
    capacitance_pF = delta * PF_PER_UNIT;
  }
  
  // Format output for OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("ESP32 Cap Meter");
  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);
  
  display.setTextSize(2);
  display.setCursor(0, 20);
  if(capacitance_pF < 1000) {
    display.print(capacitance_pF, 0);
    display.print(" pF");
  } else {
    display.print(capacitance_pF / 1000.0, 2);
    display.print(" nF");
  }
  
  display.setTextSize(1);
  display.setCursor(0, 50);
  display.print("Raw ADC: ");
  display.print(rawAvg);
  
  display.display();
  delay(250);
}

Debugging: Measurement Drift & Initialization Errors

When working with the ESP32 touch peripheral, you will inevitably encounter hardware-level quirks. Here is how to troubleshoot the most common failure modes.

Error: SSD1306 allocation failed

This exact string prints to the Serial Monitor when the display.begin() function cannot allocate the 1024-byte display buffer in the ESP32's heap, or when the I2C address is wrong.

  1. Check I2C Address: Use an I2C scanner sketch. While 0x3C is standard, many 128x64 OLEDs ship with the address 0x3D. Change SCREEN_ADDRESS accordingly.
  2. Verify Wiring: Ensure SDA is on GPIO21 and SCL is on GPIO22. Swapping these will cause the I2C bus to hang, sometimes resulting in a Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout) instead of the allocation error.
  3. Pull-up Resistors: If using a bare OLED module without onboard pull-ups, add 4.7kΩ resistors from SDA and SCL to 3.3V.

Error: Touch Sensor Returns 0 or Max Saturation (1023+)

If your serial output shows the raw ADC value stuck at 0 or pegged at the maximum limit regardless of what capacitor you attach, check these three things first:

  1. Wrong Pin Type: You are calling touchRead() on a standard GPIO (like GPIO2 or GPIO16). The ESP32-WROOM-32 only supports touch on GPIOs 0, 2, 4, 12, 13, 14, 15, 27, 32, and 33. Stick to GPIO4 (T0).
  2. Pin is Floating or Shorted: If the pin is shorted to GND or 3.3V, the internal charge pump cannot function. Verify continuity with a multimeter before powering the board.
  3. Deep Sleep Residual State: If the ESP32 recently woke from deep sleep using a touch wake-up source, the touch sensor FSM (Finite State Machine) might be locked. Add touch_pad_init() and touch_pad_fsm_start() in your setup block if using ESP-IDF functions alongside Arduino wrappers.

For deeper architectural details on the ESP32 touch sensor charge/discharge cycles, consult the Espressif Touch Pad API Documentation.

Extending and Simplifying the Build

The provided code is a baseline verifier. Depending on your workbench needs, you can modify the build in two distinct directions:

Extension: Auto-Ranging for Electrolytic Capacitors

The ESP32 touch pins are optimized for low capacitance (10pF to 1nF). To measure large electrolytic capacitors (1µF to 1000µF), the touch peripheral will saturate. The Fix: Switch to a standard GPIO RC time-constant measurement. Connect the capacitor in series with a known 10kΩ resistor to a standard GPIO. Set the GPIO HIGH, and use micros() to measure the time it takes for an analog comparator (or a second GPIO configured as an input) to cross the 63.2% voltage threshold (one time constant, τ = R × C). Calculate C = τ / R.

Simplification: The Go/No-Go Factory Tester

If you are sorting bins of 104 (100nF) capacitors and only need to reject dead parts (shorts or opens), strip out the OLED and math. Read the raw touch value. If rawAvg is within 10% of the known baseline, flag it as an 'Open' (LED Red). If rawAvg drops to near zero, flag it as a 'Short' (LED Red). If it falls in the expected delta window, flag it as 'Pass' (LED Green). This reduces loop execution time to under 2 milliseconds per part.

Frequently Asked Questions

How do I read a 3-digit capacitance code on a ceramic capacitor?

Read the first two digits as the base number, and the third digit as the number of zeros to append, in picofarads (pF). For example, a code of '473' means 47 followed by three zeros: 47,000 pF. To convert to nanofarads (nF), divide by 1,000 (47 nF). To convert to microfarads (µF), divide by 1,000,000 (0.047 µF).

Why does my ESP32 capacitance code return fluctuating values?

The ESP32 touch sensor measures capacitance by timing an internal RC oscillator. This makes it highly susceptible to environmental noise, 50/60Hz mains hum, and temperature drift. Fluctuations of ±2 raw units are normal. To stabilize the reading, increase the averaging window in the code (e.g., average 50 reads instead of 20) and ensure your test leads are kept away from AC power supplies and switching regulators.

Can I measure electrolytic capacitors with the ESP32 touch pins?

No, not reliably. The ESP32 touch peripheral is designed for human-interface capacitance (typically 10pF to 50pF changes). While it can physically register the massive capacitance of a 10µF electrolytic, the raw ADC value will bottom out at 0, giving you no resolution to distinguish between 10µF and 100µF. Use a GPIO RC-charge timing method with a series resistor for electrolytics instead.

What is the difference between the physical capacitance code and firmware capacitance code?

The 'physical capacitance code' is the EIA standard 3-digit alphanumeric string printed on the component casing to denote its nominal value and tolerance (e.g., 104K). The 'firmware capacitance code' refers to the C/C++ instructions running on a microcontroller (like the ESP32) that utilize ADCs, touch sensors, or RC timing circuits to electrically measure the actual capacitance of that physical component to verify it falls within its stated tolerance band.