The 5 color band resistor code uses three significant digit bands, one multiplier band, and one tolerance band to denote high-precision resistors (typically 1%, 0.5%, or 0.25% tolerance). Unlike the standard 4-band code, the extra significant digit allows for exact values like 10.0kΩ or 4.75kΩ, which are critical in analog filtering and precision ADC voltage dividers. However, reading faded bands under poor bench lighting leads to costly prototype errors. The direct solution is to verify the component mathematically and electrically. In this guide, we will decode the 5-band theory and build an automated ESP32 verification jig that calculates the theoretical value from the color code and measures the actual resistance to confirm it falls within the stated tolerance.
The 5 Color Band Resistor Code: Theory and Bench Reality
Before we solder the jig, you must understand the anatomy of the 5-band system. The physical layout is always read from the band closest to the lead inward. The fifth band (tolerance) is usually separated by a slightly wider gap or is a distinct metallic color (gold, silver, brown, red).
| Color | Bands 1-3 (Significant Digits) | Band 4 (Multiplier) | Band 5 (Tolerance) |
|---|---|---|---|
| Black | 0 | ×1Ω | — |
| Brown | 1 | ×10Ω | ±1% (F) |
| Red | 2 | ×100Ω | ±2% (G) |
| Orange | 3 | ×1kΩ | — |
| Yellow | 4 | ×10kΩ | — |
| Green | 5 | ×100kΩ | ±0.5% (D) |
| Blue | 6 | ×1MΩ | ±0.25% (C) |
| Violet | 7 | ×10MΩ | ±0.1% (B) |
| Grey | 8 | — | ±0.05% (A) |
| White | 9 | — | — |
| Gold | — | ×0.1Ω | ±5% (J) |
| Silver | — | ×0.01Ω | ±10% (K) |
Digits: 1, 0, 0 (100). Multiplier: Red (×100). Tolerance: Brown (±1%).
Calculation: 100 × 100 = 10,000Ω (10kΩ). Acceptable measured range: 9,900Ω to 10,100Ω.
For deeper reference on standard component markings, the All About Circuits Resistor Color Code Calculator provides an excellent interactive breakdown of the IEC 60062 standard.
Build the ESP32 Resistor Verification Jig
To verify the 5 color band resistor code on the bench, we will build a jig that uses a precision voltage divider. The ESP32's internal ADC measures the voltage drop across the unknown resistor, calculates the actual resistance, and compares it against the theoretical value you input via the Serial Monitor.
Parts List
- Microcontroller: ESP32-WROOM-32 DevKit V1 (30-pin or 38-pin variant)
- Display: 0.96-inch I2C OLED (SSD1306 driver, 128x64 resolution)
- Reference Resistor: 10kΩ 0.1% tolerance precision metal film resistor (e.g., Vishay PR02 or Yageo MFR-25)
- Miscellaneous: Half-size breadboard, 22 AWG solid jumper wires, alligator clips for test leads
Pin Mapping Table
| ESP32 GPIO | Function | Connected To | Notes |
|---|---|---|---|
| GPIO 21 | I2C SDA | OLED SDA | Internal pull-ups enabled in code |
| GPIO 22 | I2C SCL | OLED SCL | Internal pull-ups enabled in code |
| GPIO 34 | ADC1_CH6 | Voltage Divider Midpoint | Input only; no internal pull-up |
| 3V3 | Power | OLED VCC, Divider Top | Must be clean 3.3V rail |
| GND | Ground | OLED GND, Divider Bottom | Common ground required |
Complete Firmware: Calculation and ADC Measurement
This firmware targets the ESP32-WROOM-32 DevKit V1 compiled via the Arduino IDE (ESP32 Core v2.x or v3.x). It requires the Adafruit_SSD1306 and Adafruit_GFX libraries. The code includes multisampling to mitigate the ESP32's inherent ADC noise and explicit error handling for I2C and memory allocation failures.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// --- PIN DEFINITIONS ---
#define PIN_ADC 34
#define PIN_SDA 21
#define PIN_SCL 22
// --- HARDWARE SPECS ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
#define REF_RESISTOR 10000.0 // 10k ohm 0.1% precision reference
#define ADC_SAMPLES 64 // Multisampling to reduce ESP32 ADC noise
#define VCC 3.3 // Nominal 3V3 rail
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(PIN_SDA, PIN_SCL);
// Error Handling: I2C Display Initialization
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("ERROR: SSD1306 allocation failed"));
Serial.println(F("Check I2C wiring and 0x3C address."));
for(;;); // Halt execution
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Resistor Jig Ready");
display.println("Input 5-band code");
display.println("via Serial Monitor.");
display.display();
Serial.println("Enter theoretical resistance in ohms (e.g., 10000):");
}
void loop() {
if (Serial.available() > 0) {
float theoreticalOhms = Serial.parseFloat();
if (theoreticalOhms > 0) {
measureAndVerify(theoreticalOhms);
}
}
}
void measureAndVerify(float theoretical) {
// 1. Read ADC with multisampling
uint32_t adc_sum = 0;
for (int i = 0; i < ADC_SAMPLES; i++) {
adc_sum += analogRead(PIN_ADC);
delayMicroseconds(100);
}
float adc_avg = (float)adc_sum / ADC_SAMPLES;
// 2. Calculate Voltage and Resistance
// Note: ESP32 ADC is non-linear. This linear approximation is accurate
// within ~5% between 0.2V and 2.8V. For production, use esp_adc_cal.
float v_out = (adc_avg / 4095.0) * VCC;
// Prevent division by zero if test leads are shorted
if (v_out >= VCC - 0.05) {
Serial.println("ERROR: ADC reading stuck at 4095. Open circuit or overvoltage.");
return;
}
if (v_out <= 0.05) {
Serial.println("ERROR: ADC reading near 0. Short circuit detected.");
return;
}
float actualOhms = REF_RESISTOR * (v_out / (VCC - v_out));
// 3. Calculate Tolerance Deviation
float deviationPercent = ((actualOhms - theoretical) / theoretical) * 100.0;
// 4. Output to Serial and OLED
Serial.printf("Theoretical: %.2f ohms\n", theoretical);
Serial.printf("Actual: %.2f ohms\n", actualOhms);
Serial.printf("Deviation: %.2f%%\n\n", deviationPercent);
display.clearDisplay();
display.setCursor(0,0);
display.printf("Theo: %.0f R\n", theoretical);
display.printf("Act: %.0f R\n", actualOhms);
display.printf("Dev: %.2f%%\n", deviationPercent);
if (abs(deviationPercent) <= 1.0) {
display.println("PASS: Within 1%");
} else if (abs(deviationPercent) <= 5.0) {
display.println("WARN: >1% but <5%");
} else {
display.println("FAIL: Check bands!");
}
display.display();
}
Debugging Common I2C and ADC Errors
When bridging embedded firmware with analog bench measurements, hardware quirks quickly surface. Below are the exact error strings you will encounter and how to resolve them.
Error 1: "ERROR: SSD1306 allocation failed"
This is the most common I2C initialization failure in the Adafruit library. It triggers when the MCU cannot allocate the display buffer in heap memory, or when the I2C bus fails to acknowledge the display's address.
Ranked Causes:
- Incorrect I2C Address: Many cheap 0.96" OLEDs use
0x3C, but some variants (especially 1.3" SH1106 displays masquerading as SSD1306) use0x3D. Run an I2C scanner sketch to verify. - Missing Pull-up Resistors: The ESP32's internal pull-ups (approx. 45kΩ) are often too weak for long breadboard traces. Add external 4.7kΩ pull-up resistors to SDA and SCL.
- Heap Fragmentation: If you have other large libraries initialized before the display, the contiguous 1024-byte block required for the 128x64 buffer may be unavailable. Move
display.begin()to the very top ofsetup().
Error 2: "ERROR: ADC reading stuck at 4095"
This occurs when the voltage at GPIO 34 exceeds the ADC's measurable threshold, causing the register to saturate at its maximum 12-bit value (4095).
Ranked Causes:
- Open Circuit (Floating Input): The test resistor is not connected. Without the test resistor to ground, GPIO 34 floats up to 3.3V through the reference resistor. Always connect the DUT (Device Under Test) before powering on.
- Voltage Overload: You accidentally wired the divider to the 5V VIN pin instead of 3V3. GPIO 34 is strictly limited to 3.3V. Voltages above 3.6V will permanently damage the ESP32's ADC multiplexer.
- GPIO 34 Strapping Conflict: GPIO 34 is an input-only pin and generally safe, but if your specific DevKit variant has a hardware pull-up on this pin for boot-strapping, it will skew the reading. Switch to GPIO 35 or 32 if this persists.
1. I2C Continuity: Use your multimeter in continuity mode to verify SDA/SCL are not shorted to ground or each other.
2. Reference Resistor Value: Measure your 10kΩ reference resistor with a trusted DMM. If it's actually 9.85kΩ, update the
REF_RESISTOR constant in the code to match, or your calculations will always be skewed by 1.5%.3. ADC Non-Linearity Extremes: The ESP32 ADC is highly non-linear below 0.15V and above 2.8V. If your test resistor is extremely low (<100Ω) or extremely high (>500kΩ), the voltage divider pushes the ADC into these dead zones. Change the reference resistor value to match the expected DUT range.
Extending and Simplifying the Build
Depending on your bench needs, you can scale this project up or down.
How to Simplify the Build
If you don't want to wire an I2C OLED, strip out all Adafruit_SSD1306 and Wire.h dependencies. Rely entirely on the Arduino IDE Serial Plotter. Output the measured resistance as a raw CSV string (Serial.printf("%f\n", actualOhms);) and use the Serial Plotter to watch the resistance stabilize in real-time as you clip the leads onto the resistor. This saves roughly 40KB of flash memory and eliminates I2C debugging entirely.
How to Extend the Build
To make this a true "color code" reader rather than just a resistance verifier, add a TCS34725 RGB Color Sensor mounted in a 3D-printed shroud to block ambient light. By sampling the RGB reflectance of each band and mapping it to the IEC 60062 color space, the ESP32 can automatically deduce the 5 color band resistor code without manual serial input. Be warned: distinguishing between Red/Brown and Green/Blue on cheap carbon-film resistors requires heavy software calibration and a dedicated white LED illumination ring.
For advanced ADC calibration to eliminate the ESP32's native non-linearity, consult the official Espressif ADC API Reference regarding the esp_adc_cal library, which uses the chip's internal eFuse calibration data to map raw ADC ticks to exact millivolts.
Frequently Asked Questions
How do I read a 5 color band resistor code if the bands are faded or burnt?
If the paint is scorched or faded, visual decoding is unreliable. Do not guess. Use a digital multimeter (DMM) to measure the resistance directly. If the resistor is damaged (open circuit or wildly out of spec), it must be replaced. If it measures correctly but you need the exact tolerance for a precision circuit, assume the worst-case scenario (e.g., ±5% or ±10%) unless you can verify the original bill of materials (BOM) from the manufacturer.
What is the difference between a 4-band and 5 color band resistor code?
A 4-band code uses two significant digits, one multiplier, and one tolerance band (e.g., Yellow, Violet, Red, Gold = 47 × 100 = 4.7kΩ ±5%). A 5 color band resistor code adds a third significant digit, allowing for tighter value specification (e.g., Yellow, Violet, Black, Brown, Brown = 470 × 10 = 4.7kΩ ±1%). The 5-band system is almost exclusively used for 1%, 0.5%, and 0.25% precision metal film resistors, while 4-band is standard for 5% carbon film or thick film resistors.
Why does my multimeter read a different value than the 5 color band resistor code?
The color code indicates the nominal value, not the exact value. A 10kΩ resistor with a brown (±1%) tolerance band is guaranteed to be between 9,900Ω and 10,100Ω. If your multimeter reads 10,045Ω, the resistor is perfectly within spec. Additionally, cheap multimeters often have a ±1% to ±2% base accuracy on the resistance range. Always zero out your test lead resistance (relative mode) before measuring low-value precision resistors, as 0.2Ω of lead resistance will skew a 100Ω measurement by 0.2%.
Which way do I read the bands if there is no visible gap?
If the spacing is uniform, look at the colors. The tolerance band (Band 5) is almost always Gold, Silver, Brown, or Red. The significant digit bands will never be Gold or Silver. Therefore, if one end has a Gold or Silver band, start reading from the opposite end. If both ends have valid digit colors (e.g., Brown and Red), use your multimeter to measure the resistance, then work backward to see which reading direction yields a standard E96 series value.






