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.
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 Code | Significant Digits | Multiplier (10^x) | Value in pF | Value in nF / µF |
|---|---|---|---|---|
| 101 | 10 | 10^1 | 100 pF | 0.1 nF |
| 102 | 10 | 10^2 | 1,000 pF | 1 nF |
| 103 | 10 | 10^3 | 10,000 pF | 10 nF |
| 104 | 10 | 10^4 | 100,000 pF | 100 nF (0.1 µF) |
| 222 | 22 | 10^2 | 2,200 pF | 2.2 nF |
| 473 | 47 | 10^3 | 47,000 pF | 47 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
| Component | Pin / Label | ESP32 GPIO | Notes |
|---|---|---|---|
| SSD1306 OLED | VCC | 3V3 | Do not use 5V on 3.3V OLED variants |
| SSD1306 OLED | GND | GND | Common ground |
| SSD1306 OLED | SCL | GPIO 22 | Default I2C Clock |
| SSD1306 OLED | SDA | GPIO 21 | Default I2C Data |
| Capacitor Probe | Touch T0 | GPIO 4 | Must be a touch-capable pin |
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.
- Check I2C Address: Use an I2C scanner sketch. While 0x3C is standard, many 128x64 OLEDs ship with the address 0x3D. Change
SCREEN_ADDRESSaccordingly. - 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. - 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:
- 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). - 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.
- 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()andtouch_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.






