Ventricular fibrillation in the human heart can be triggered by as little as 30mA of alternating current passing through the chest. A standard 15A or 20A thermal-magnetic branch breaker will not trip at 30mA; it requires thousands of milliamps and seconds of thermal buildup to react. This lethal gap in protection is exactly why ground-fault circuit interrupters (GFCIs) exist. By continuously comparing the current flowing out on the ungrounded (hot) conductor with the current returning on the grounded (neutral) conductor, a GFCI detects imbalances as small as 4mA to 6mA and opens the circuit in under 25 milliseconds.

However, GFCIs are electromechanical devices. Their internal solenoids and sense coils degrade over time, and nuisance trips can mask underlying insulation failures in branch wiring. In this guide, we will build an ESP32-based IoT leakage current logger. This device clamps around a branch circuit, monitors baseline leakage in real-time, and pushes MQTT alerts before a fault escalates into a hard trip or a shock hazard.

The Physics of the Fault: Neutral, Ground, and Bonding

To understand what a GFCI measures, you must strictly separate three concepts that are frequently confused on the jobsite: the neutral, the equipment grounding conductor (EGC), and the bonding jumper.

  • Neutral (Grounded Conductor): This is a normal, current-carrying wire. It completes the 120V AC circuit back to the transformer. In a healthy circuit, neutral current exactly equals hot current.
  • Ground (Equipment Grounding Conductor): This is a non-current-carrying safety path. It connects exposed metal chassis and enclosures back to the panel. It only carries current during a fault (e.g., a frayed hot wire touches a metal toaster casing).
  • Bonding: This is the physical connection between the neutral busbar and the ground busbar. In North American residential systems, this bond occurs at exactly one point: the main service disconnect.
Safety Warning: Never create a secondary neutral-to-ground bond downstream of the main panel (such as at a subpanel or receptacle). Doing so creates parallel return paths for normal neutral current. The GFCI will read this diverted neutral current as a ground fault and trip continuously, tempting inexperienced DIYers to remove the ground pin or bypass the device. Never defeat a protective device.

When a ground fault occurs, some of the hot current bypasses the neutral and returns via the EGC, a plumbing pipe, or a human body. The GFCI’s internal differential current transformer (CT) sees this Kirchhoff's Current Law violation and drops power.

UL 943 Trip Thresholds and Response Times

Not all ground-fault protection is identical. Standard receptacle GFCIs are built to UL 943 Class A specifications, while industrial equipment might use Class C or specialized Arc-Fault/Ground-Fault combination devices. When programming your ESP32 logger's alert thresholds, use the following baseline data to distinguish between normal capacitive leakage and an imminent fault.

Parameter Class A GFCI (Standard Receptacle) Class C GFCI (Equipment/Industrial) GFPE (Ground-Fault Protection of Equipment)
Nominal Trip Threshold 5 mA (± 1 mA) 20 mA 30 mA to 100 mA+
Primary Hazard Prevented Human electrocution / microshock Equipment damage / higher leakage environments Fire prevention / arcing faults
Max Trip Time (at Threshold) ~20 ms to 25 ms ~20 ms 1 second or less (depends on current magnitude)
Typical Application Kitchens, bathrooms, outdoors, garages Industrial machinery, HVAC compressors Main feeders, large solar arrays, 400A+ panels

Source data derived from UL Solutions Electrical Safety standards and standard NEC-style guidance. Note: Your local Authority Having Jurisdiction (AHJ) has final authority on specific device requirements for your region.

Building the ESP32 Leakage Monitor

Measuring 5mA of leakage on a 15A circuit requires high resolution. A standard SCT-013 current transformer (designed for 0-100A) will output virtually nothing at 5mA. Instead, we use a high-permeability differential CT like the CR Magnetics CR8459-1000-G, which is specifically wound for mA-level leakage detection.

Hardware and the INA128 Biasing Circuit

The CR8459 has a 1000:1 turns ratio. If 5mA flows through the primary (the hot and neutral wires passed through the center), the secondary outputs 5µA. Across a 100Ω burden resistor, that yields just 0.5mV RMS. The ESP32-WROOM-32’s 12-bit ADC has a noise floor that will completely swallow a 0.5mV signal.

To solve this, we use an INA128 instrumentation amplifier to boost the signal before it hits the ESP32:

  1. Burden Resistor: Place a 100Ω 1% metal film resistor across the CR8459 secondary leads.
  2. Amplification: Feed the burden voltage into the INA128 inputs. Set the gain to 500 using a 100Ω gain resistor ($R_g = 49.4k\Omega / (Gain - 1)$). This amplifies our 0.5mV signal to 250mV.
  3. DC Bias: The ESP32 ADC cannot read negative AC voltages. Use a voltage divider (two 10kΩ resistors) from the 3.3V rail to create a 1.65V DC offset, and inject it into the INA128 reference pin. The AC signal now oscillates cleanly between 1.4V and 1.9V.
  4. ADC Connection: Connect the amplifier output to GPIO 34 (ADC1_CH6). Set the ESP32 ADC attenuation to 11dB to allow readings up to ~3.1V.

Firmware: RMS Calculation and MQTT Alerting

The firmware samples the AC waveform at 4kHz, calculates the true RMS leakage over a 250ms window, and publishes the data via MQTT. If the leakage creeps above 2.5mA (a warning sign of degrading insulation or moisture ingress), it flags an alert before the GFCI physically trips.

#include <Arduino.h>
#include <PubSubClient.h>
#include <WiFi.h>

const int ADC_PIN = 34;
const int SAMPLES = 1000; // 250ms window at 4kHz
const float V_REF = 3.1;  // Max voltage at 11dB attenuation
const float ADC_RESOLUTION = 4095.0;
const float BIAS_VOLTAGE = 1.65;
const float GAIN = 500.0;
const float BURDEN_OHMS = 100.0;
const float CT_RATIO = 1000.0;

WiFiClient espClient;
PubSubClient mqttClient(espClient);

void setup() {
  Serial.begin(115200);
  analogSetPinAttenuation(ADC_PIN, ADC_11db);
  // WiFi and MQTT connection routines omitted for brevity
}

void loop() {
  float sumSquares = 0;
  unsigned long startTime = micros();
  
  for (int i = 0; i < SAMPLES; i++) {
    int rawAdc = analogRead(ADC_PIN);
    // Convert ADC to voltage, remove 1.65V DC bias
    float voltage = (rawAdc / ADC_RESOLUTION) * V_REF - BIAS_VOLTAGE;
    sumSquares += voltage * voltage;
    while(micros() - startTime < (i * 250)); // Enforce 4kHz sampling (250us)
  }
  
  float rmsVoltage = sqrt(sumSquares / SAMPLES);
  // Calculate primary current in mA
  float secondaryCurrent = rmsVoltage / BURDEN_OHMS;
  float primaryLeakage_mA = (secondaryCurrent * CT_RATIO) * 1000.0;
  
  Serial.printf("Leakage: %.2f mA\n", primaryLeakage_mA);
  
  if (primaryLeakage_mA > 2.5 && primaryLeakage_mA < 4.5) {
    mqttClient.publish("home/panel/gfci/status", "WARNING: High leakage detected");
  } else if (primaryLeakage_mA >= 4.5) {
    mqttClient.publish("home/panel/gfci/status", "CRITICAL: Imminent GFCI Trip");
  }
  
  delay(1000);
}

Verification, Testing, and Code Boundaries

Once your logger is built and clamped around the branch circuit, you must verify that both the commercial GFCI and your ESP32 monitor are functioning correctly.

How to Verify with a Tester

Do not rely solely on the "TEST" button built into the GFCI receptacle. That button only verifies that the internal solenoid can physically trip the contacts; it does not verify the integrity of the ground path back to the panel.

  1. Plug in a commercial solenoid tester, such as the Gardner Bender GFI-501A.
  2. Press the black test button. This injects a calibrated ~6mA fault between the hot and ground pins.
  3. The GFCI should trip within 25ms.
  4. Simultaneously, check your ESP32 serial monitor or MQTT dashboard. You should see a brief spike to >5.0mA logged right before the circuit de-energizes.

When a Licensed Electrician is Required

Clamping a split-core CT around the exterior of a non-metallic (NM-B) Romex cable is safe and requires no panel modifications. However, if you intend to install the CR8459 permanently inside a subpanel, or if you need to separate the hot and neutral conductors to pass only the hot and neutral through the CT (leaving the bare ground outside the toroid), you are entering a restricted zone.

Code and Safety Boundary: Removing the dead-front cover of an electrical panel exposes you to the unmetered, unfused main service lugs, which carry lethal fault currents with no upstream overcurrent protection. NEC-style guidance (Article 210.8 and 406.4) dictates strict placement rules for ground-fault circuit interrupters, but local codes vary. If your installation requires pulling the panel dead-front, rerouting branch conductors, or modifying busbars, de-energize the main breaker, verify dead with a CAT III rated multimeter, and hire a licensed electrician. Your local AHJ has final authority on all panel modifications.

By logging micro-faults and tracking insulation degradation over time, this ESP32 setup transitions ground-fault protection from a passive, binary safety net into an active, predictive maintenance tool for your home's electrical infrastructure.