Contents — 26 sections
Project Overview
Captures the voltage sags, swells, surges and disturbances that damage equipment and trip processes — timestamped and characterised — so a supply problem can finally be diagnosed and proven.
When equipment mysteriously resets, a process trips for no obvious reason, or electronics fail early, the cause is often the power quality — brief voltage sags when a big motor starts nearby, swells and surges, spikes from switching, distortion from non-linear loads — events too fast and transient for anyone to see on a normal meter, but more than enough to disrupt or damage equipment. And because they are invisible and intermittent, they are almost impossible to diagnose: the utility says the supply is fine, the equipment vendor blames the site, and the problem persists. This project builds a logger that catches these disturbances — measuring the voltage waveform fast enough to see them, characterising each event, and timestamping it — so a supply problem can be diagnosed and, crucially, proven.
It samples the mains voltage at a high rate (many samples per cycle) so it can compute the true RMS voltage cycle-by-cycle and detect deviations that a slow meter averages away. From the waveform it captures the classic power-quality events: sags (dips, the most common and disruptive — a brief drop when a large load starts), swells (temporary rises), surges/transients (fast spikes), interruptions, and frequency deviations, and it can measure harmonic distortion (THD) from non-linear loads. Each event is recorded with its timestamp, type, magnitude and duration — the characterisation that turns "the power is bad" into "a 30% sag lasting 80 ms occurred at 14:32", which is evidence.
That evidence is the point. A timestamped log of characterised events lets you correlate disturbances with equipment failures ("the machine trips whenever that sag occurs"), pin down the source (on-site vs the utility), and make a documented case to the utility or the equipment vendor. The logger trends event frequency, alarms on severe disturbances, and exports the record. It is honest that measuring mains is hazardous and that a DIY logger is not a calibrated, standards-compliant power-quality analyser (which classifies events per IEC 61000-4-30) — but as a high-rate voltage logger that captures and characterises the sags, swells and surges a normal meter cannot see, it turns an invisible, intermittent, un-diagnosable supply problem into a measured, timestamped, provable one.
What this project does
- Samples the mains voltage at high rate to see fast disturbances
- Computes true RMS voltage cycle-by-cycle
- Captures sags, swells, surges/transients, interruptions and frequency deviations
- Measures harmonic distortion (THD) from non-linear loads
- Characterises each event (type, magnitude, duration) with a timestamp
- Correlates disturbances with equipment problems and trends them
- Exports an evidence-grade log for utility/vendor disputes
Real-World Applications
| Setting | How it is used |
|---|---|
| Diagnosing equipment resets/trips | Correlating mysterious failures with voltage sags/surges to find the cause. |
| Supply-quality disputes | Documented, timestamped evidence for the utility or an equipment vendor. |
| Sensitive-load protection | Monitoring power quality where equipment is disturbance-sensitive. |
| Site power assessment | Characterising a site's supply before installing sensitive equipment. |
Deployment contexts where a build of this kind earns its keep.
Features & Capabilities
- High-rate waveform capture (fast enough for transients)
- Cycle-by-cycle true RMS
- Sag/swell/surge/interruption/frequency detection
- THD / harmonic measurement
- Timestamped, characterised event log
- Correlation and trending
- Honest: not a calibrated IEC power-quality analyser
Difficulty, Time & Required Skills
| Attribute | Value |
|---|---|
| Difficulty level | Advanced |
| Estimated completion time | 14–20 hours |
| Indicative build cost | ₹2,800 – ₹4,500 |
| Primary discipline | Energy |
| Reference platform | ESP32 DevKit V1 (ESP-WROOM-32) |
Skills you should have (or will pick up)
- High-rate mains-voltage sampling (safe, isolated)
- Cycle-by-cycle RMS and event detection
- Sag/swell/surge/THD characterisation
- Timestamped event logging and correlation
- Evidence export and interpretation
Bill of Materials
Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.
| Component | Key specification | Qty | Approx. cost |
|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly. | Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC | 1 | ₹450 |
| ZMPT101B AC voltage sensor Trim the on-board pot so the idle output sits exactly at Vcc/2. | 0–250 VAC input, 2 mA:2 mA precision transformer, ±1 % linearity | 1 | ₹220 |
| 0.96″ SSD1306 OLED display Static images burn in — invert or scroll the screen periodically. | 128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C | 1 | ₹250 |
| microSD card 32 GB A1 class For 24/7 loggers buy a high-endurance card — normal cards die in months. | A1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended | 1 | ₹450 |
| DS3231 precision RTC + CR2032 backup Vastly better than DS1307; some boards trickle-charge a non-rechargeable cell — cut that resistor. | ±2 ppm (±1 min/year), temperature-compensated crystal, alarms, 32 kHz out | 1 | ₹180 |
| 5 V 3 A regulated SMPS adapter Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A. | 100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection | 1 | ₹350 |
| Isolated voltage sensing Isolation is safety-critical | ZMPT101b or isolated voltage transformer for safe mains-voltage measurement | 1 | ₹400 |
| High-rate ADC / front-end | Fast ADC front-end for many samples/cycle (transient capture) | 1 | ₹500 |
| Accurate time source | RTC/GPS for precise event timestamps (correlation) | 1 | ₹300 |
| DIN enclosure + isolation | Safe mains-side enclosure | 1 | ₹500 |
Estimated total: ₹3,600, excluding tools, shipping and consumables.
Tools and consumables
- Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
- Digital multimeter — continuity, DC volts and current ranges
- Wire strippers, flush cutters and a small set of precision screwdrivers
- Heat-shrink tubing and a heat gun (or a lighter, carefully)
- A laptop with a USB port and the toolchain listed above
Hardware Specifications
| Part | Specification | Supply | Interface | Reference |
|---|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) | Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC | 3.3 V logic / 5 V USB | UART, SPI, I²C, I²S, CAN, PWM | Datasheet |
| ZMPT101B AC voltage sensor | 0–250 VAC input, 2 mA:2 mA precision transformer, ±1 % linearity | 5 V | Analogue | Datasheet |
| 0.96″ SSD1306 OLED display | 128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C | 3.3–5 V | I²C (0x3C) | Datasheet |
| microSD card 32 GB A1 class | A1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended | 3.3 V | SDIO / SPI | Datasheet |
| DS3231 precision RTC + CR2032 backup | ±2 ppm (±1 min/year), temperature-compensated crystal, alarms, 32 kHz out | 2.3–5.5 V | I²C (0x68) | Datasheet |
| 5 V 3 A regulated SMPS adapter | 100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection | 5 V | DC barrel / USB | Datasheet |
Consolidated electrical and interface specifications for every active part in the build.
Power Budget & Supply Sizing
Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.
| Load | Supply rail | Typical current (mA) | Notes |
|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) | 3.3 V logic / 5 V USB | 160 | Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly. |
| ZMPT101B AC voltage sensor | 5 V | 20 | Trim the on-board pot so the idle output sits exactly at Vcc/2. |
| 0.96″ SSD1306 OLED display | 3.3–5 V | 20 | Static images burn in — invert or scroll the screen periodically. |
| microSD card 32 GB A1 class | 3.3 V | 100 | For 24/7 loggers buy a high-endurance card — normal cards die in months. |
| DS3231 precision RTC + CR2032 backup | 2.3–5.5 V | 0.2 | Vastly better than DS1307; some boards trickle-charge a non-rechargeable cell — cut that resistor. |
| 5 V 3 A regulated SMPS adapter | 5 V | 3000 | Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A. |
Summed typical draw is 3300.2 mA. With a 1.5× design margin the supply should deliver at least 5000 mA continuously at the stated rail voltage.
Software Requirements & Development Environment
Reference toolchain: Arduino IDE 2.3.x with the ESP32 board package 3.x (or PlatformIO on VS Code). Anything newer normally works; anything older may lack the board definitions used here.
- Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
- Add
https://espressif.github.io/arduino-esp32/package_esp32_index.jsonunder File → Preferences → Additional Board Manager URLs, then install esp32 from the Boards Manager. - Set the correct port under Tools → Port. On Linux add yourself to the
dialoutgroup:sudo usermod -aG dialout $USERand log out and back in. - Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
- Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.
Required libraries
| Library | Why it is needed | Install |
|---|---|---|
| WiFi (ESP32 core) bundled | Station/AP connection management for the ESP32. | Bundled with the ESP32 Arduino core |
| PubSubClient 2.8 | Lightweight MQTT 3.1.1 client for constrained devices. | Library Manager → "PubSubClient" by Nick O'Leary |
| Adafruit SSD1306 + GFX 2.5.x | Framebuffer and text/graphics primitives for the OLED. | Library Manager → "Adafruit SSD1306" |
| NTPClient / configTime bundled | Wall-clock time from an NTP server for timestamping. | Bundled (`configTime()` on ESP32) |
| SQLite 3.45+ | Zero-configuration embedded database for local logs. | Bundled with Python (`import sqlite3`) |
| ArduinoJson 7.x | Zero-allocation JSON serialisation and parsing. | Library Manager → "ArduinoJson" by Benoit Blanchon |
Block Diagram
The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.
Circuit Diagram & Wiring
Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.
| Peripheral | Peripheral pin | Controller pin | Signal |
|---|---|---|---|
| Isolated V sense | AOUT | GPIO 34 (ADC) | Mains voltage waveform |
| DS3231 RTC/GPS | SDA/SCL | GPIO 21/22 | Event timestamps |
| OLED | SDA/SCL | GPIO 21/22 | RMS/event display |
| microSD | SPI | GPIO 18/19/23/5 | Event log / waveform |
| Wi-Fi | on-chip | — | Dashboard/alerts |
| Isolated supply | +/– | 3V3 reg | Power |
Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.
Wiring explanation
- Use isolated voltage sensing (ZMPT101b/isolated transformer) — measuring mains directly is dangerous; have a qualified person make the mains-side connection.
- Sample many times per cycle (e.g. 32–128 samples/cycle at 50/60 Hz) so transients and sub-cycle events are captured, not averaged away.
- Give the logger an accurate time source (RTC/GPS) for precise, correlatable event timestamps.
- Log events (and optionally waveform snippets) to local storage; keep an off-device copy for evidence.
- Keep the low-voltage electronics isolated from the mains sensing.
System Architecture
Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.
Working Principle
Power-quality problems are hard precisely because they are fast, transient and intermittent — a voltage sag when a nearby motor starts might last only a few cycles (tens of milliseconds), a surge a fraction of a cycle — and a normal meter, which reports a slow average, simply cannot see them: it smooths the disturbance into a number that looks fine. Yet these brief events are more than enough to reset a controller, trip a drive, corrupt data, or, over time, degrade equipment. So the whole approach hinges on measuring fast enough to see what a meter misses, and then turning each fleeting event into a permanent, characterised record.
Seeing the events requires high-rate waveform sampling — many samples per mains cycle — from which the logger computes the true RMS voltage cycle by cycle. This cycle-resolved RMS is the key measurement: it reveals a sag as a run of cycles where the RMS drops below normal, a swell as a run above, an interruption as RMS collapsing, all with the timing a slow average destroys. On top of RMS, the raw samples let the logger catch faster transients/surges (a spike within a cycle) and compute harmonic distortion (THD) — the waveform distortion caused by non-linear loads (drives, power supplies) that stresses equipment and indicates supply or load problems. The single design decision that makes everything possible is sampling density; everything else is analysis on top of a fast, faithful capture of the waveform.
The value comes from characterisation and timestamping, because a raw waveform is not actionable but a characterised event is. Each disturbance is classified by type (sag, swell, surge, interruption, frequency deviation, high THD), and recorded with its magnitude (how far the voltage deviated), duration (how long), and an accurate timestamp. This transforms a vague complaint into a precise fact: not "the power is bad" but "a sag to 70% of nominal lasting 80 ms occurred at 14:32:07". A log of such facts is evidence — the currency of any power-quality investigation.
That evidence enables the two things that actually solve power-quality problems: correlation and attribution. Correlation matches disturbances against symptoms — if the machine trips at 14:32 and the logger recorded a deep sag at 14:32, you have found your culprit and can stop guessing. Attribution helps locate the source: a sag that coincides with an on-site load starting points inward (fix your own installation or supply capacity), while disturbances arriving from the incoming supply point to the utility — and a timestamped record is what lets you make a documented, defensible case to the utility or an equipment vendor rather than a losing argument of assertions. The design is honest about its limits: mains measurement is genuinely hazardous and must be done safely and isolated, and a homebrew logger is not a calibrated, standards-compliant power-quality analyser (the ones that classify events strictly per IEC 61000-4-30 for formal disputes). But as an instrument that captures, characterises and timestamps the sags, swells and surges a normal meter cannot see, it does the essential thing: it makes an invisible, intermittent, previously un-diagnosable supply problem visible, measured and provable.
The maths behind it
Cycle-by-cycle true RMS
From N samples v[n] over one mains cycle:
V_rms = sqrt( (1/N) Σ v[n]^2 )
Compute per cycle (needs many samples/cycle). A slow meter
averages over seconds and hides sub-second events.
Sag / swell / interruption
Relative to nominal V_nom:
sag : 0.1·V_nom ≤ V_rms < 0.9·V_nom
swell : V_rms > 1.1·V_nom
interruption: V_rms < 0.1·V_nom
Record each event's magnitude (% of nominal) and duration
(number of affected cycles → time).
Harmonic distortion (THD)
From the FFT of the voltage waveform:
THD = sqrt(Σ_{h≥2} V_h^2) / V_1
V_1 = fundamental (50/60 Hz), V_h = harmonic amplitudes.
High THD = waveform distortion from non-linear loads.
Program Flowchart
The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.
Assembly Instructions
Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.
Set up isolated high-rate voltage sensing
Use isolated voltage sensing and a fast ADC front-end to sample the mains waveform many times per cycle, with the mains-side connection made by a qualified person and the electronics isolated.
Add an accurate time source (RTC/GPS) for event timestamps.
Set up detection and logging
Compute cycle RMS, frequency and THD, detect and characterise events, and log them (with optional waveform snippets) locally and off-device.
Set up correlation and export
Provide correlation/trending and an evidence export, and alarms on severe disturbances.
Step-by-Step Implementation Guide
Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.
Compute cycle RMS and detect events
Compute true RMS per cycle, compare to nominal for sags/swells/interruptions, detect transients and high THD, and characterise each with type/magnitude/duration/timestamp.
cpppq-detect.ino#define V_NOM 230.0f #define SAMPLES_PER_CYCLE 64 float cycleRMS(const float *v, int n){ double ss=0; for(int i=0;i<n;i++) ss += (double)v[i]*v[i]; return sqrtf(ss/n); } struct Event { const char* type; float magPct; }; Event classify(float vrms){ float pct = vrms / V_NOM; if (pct < 0.10f) return {"interruption", pct*100}; if (pct < 0.90f) return {"sag", pct*100}; // most common/disruptive if (pct > 1.10f) return {"swell", pct*100}; return {nullptr, 100}; // normal } // Track an ongoing event to record its duration. struct EvState { bool active=false; const char* type=nullptr; uint32_t startCycle=0; float peakPct=100; } ev; void onCycle(float vrms, uint32_t cycle, DateTime t){ Event e = classify(vrms); if (e.type){ if (!ev.active){ ev.active=true; ev.type=e.type; ev.startCycle=cycle; ev.peakPct=e.magPct; } if (fabsf(e.magPct-100) > fabsf(ev.peakPct-100)) ev.peakPct=e.magPct; } else if (ev.active){ // event ended uint32_t cycles = cycle - ev.startCycle; logEvent(ev.type, ev.peakPct, cycles, t); // type/mag/duration/time ev.active=false; } }float cycleRMS(const float *v, int n)Computes the true RMS of each mains cycle from many samples — the cycle-resolved measurement that reveals sub-second events a slow meter hides.if (pct < 0.90f) return {"sag", pct*100}A cycle RMS below 90% of nominal is a sag — the most common and disruptive disturbance — classified with its magnitude as a percentage of nominal.if (!ev.active){ ev.active=true; ev.type=e.type;An event is tracked from its first affected cycle so its duration and peak magnitude can be recorded, not just that it happened.logEvent(ev.type, ev.peakPct, cycles, t)When the event ends it is logged with type, peak magnitude, duration (in cycles → time) and timestamp — the characterisation that makes it evidence.Log, correlate and export
Log characterised events with timestamps, compute THD, trend event frequency, alarm on severe disturbances, and export an evidence record for correlation with failures and for the utility/vendor.
Complete Source Code
The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.
/* ═══════════════════════════════════════════════════════════════
Grid Power-Quality Logger — ESP32 (isolated, high-rate)
Samples the mains voltage many times per cycle, computes cycle RMS,
frequency and THD, and captures/characterises sags, swells, surges,
interruptions with timestamps — evidence for supply diagnosis.
Mains measurement is hazardous; a DIY logger is indicative, not a
calibrated IEC 61000-4-30 analyser.
══════════════════════════════════════════════════════════════════ */
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <RTClib.h>
#include <math.h>
#define PIN_V 34
#define V_NOM 230.0f
#define SPC 64 // samples per cycle
#define MAINS_HZ 50
RTC_DS3231 rtc; WiFiClient net; PubSubClient mqtt(net);
float VCAL; // ADC->volts calibration
struct EvState { bool active=false; const char* type=nullptr;
uint32_t startMs=0; float peakPct=100; } ev;
float sampleCycleRMS(){
const uint32_t period_us = 1000000UL/(MAINS_HZ*SPC);
double ss=0; uint32_t next=micros();
for(int i=0;i<SPC;i++){
while((int32_t)(micros()-next)<0){} next+=period_us;
float v = (analogRead(PIN_V) - 2048)/2048.0f * VCAL; // centred, scaled
ss += (double)v*v;
}
return sqrtf(ss/SPC);
}
const char* classify(float vrms, float &pct){
pct = vrms/V_NOM*100;
if (pct < 10) return "interruption";
if (pct < 90) return "sag";
if (pct > 110) return "swell";
return nullptr;
}
void setup(){
Serial.begin(115200);
analogSetPinAttenuation(PIN_V, ADC_11db);
Wire.begin(21,22); rtc.begin();
WiFi.begin(WIFI_SSID,WIFI_PASS); mqtt.setServer(MQTT_HOST,1883);
}
void loop(){
if(!mqtt.connected()&&WiFi.status()==WL_CONNECTED) mqtt.connect("pq-1");
mqtt.loop();
float vrms = sampleCycleRMS(); // one mains cycle
uint32_t now = millis();
float pct; const char* type = classify(vrms, pct);
if (type){
if (!ev.active){ ev.active=true; ev.type=type; ev.startMs=now; ev.peakPct=pct; }
if (fabsf(pct-100) > fabsf(ev.peakPct-100)) ev.peakPct=pct;
} else if (ev.active){ // event ended -> record it
uint32_t dur = now - ev.startMs;
DateTime t = rtc.now();
char m[200];
snprintf(m,sizeof m,
"{\"type\":\"%s\",\"mag_pct\":%.0f,\"dur_ms\":%lu,"
"\"time\":\"%04d-%02d-%02d %02d:%02d:%02d\"}",
ev.type, ev.peakPct, (unsigned long)dur,
t.year(),t.month(),t.day(),t.hour(),t.minute(),t.second());
logLocal(m); // evidence log (local + mirror)
mqtt.publish("pq/1/event", m);
if (ev.peakPct < 80 || ev.peakPct > 115) mqtt.publish("pq/1/alarm", m);
ev.active=false;
}
// periodic RMS/THD status
static uint32_t last=0;
if (now-last > 1000){ last=now;
char s[120]; snprintf(s,sizeof s,"{\"vrms\":%.1f}", vrms);
mqtt.publish("pq/1/status", s);
}
}
Configuration & Calibration
Configuration steps
- Set the nominal voltage, samples-per-cycle and event thresholds (sag/swell/interruption/THD).
- Calibrate the voltage scaling and configure the time source for accurate timestamps.
- Configure local + off-device logging and waveform-snippet capture.
- Set severe-disturbance alarm thresholds.
Calibration procedure
An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.
Voltage scaling
Calibrate the ADC-to-volts scaling against a reference so RMS and event magnitudes are accurate.
Sampling
Confirm the samples-per-cycle rate is steady and sufficient to capture transients; verify RMS matches a reference under steady voltage.
Time
Verify the RTC/GPS timestamps are accurate for correlation.
Network Architecture & Connectivity
Communication protocol
RMS/THD status publishes periodically; characterised events and severe-disturbance alarms publish immediately. The local log is the evidence record, mirrored off-device.
| Topic / endpoint | Direction | Payload |
|---|---|---|
pq/1/event | node → dashboard | type, magnitude, duration, timestamp |
pq/1/alarm | node → engineer | severe disturbance |
pq/1/status | node → dashboard | RMS, frequency, THD |
Message contract between the device and the broker.
Cloud platform configuration
A dashboard shows RMS/THD and an event timeline, trends event frequency, and exports the record for correlation with failures and for utility/vendor disputes.
Dashboard setup
Live RMS/frequency/THD, an event timeline with magnitude/duration, trend of event frequency, and export.
Mobile app integration
Alerts on severe disturbances; daily disturbance summaries.
Security considerations
- Keep the local evidence log authoritative and mirrored; timestamp accurately.
- Authenticate nodes; secure the data.
- Note a calibrated, standards-compliant analyser may be required for formal disputes.
Testing Procedure & Expected Output
Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.
| Test | What you should see |
|---|---|
| Steady nominal voltage | Accurate RMS; no events |
| Induce a sag (start a big load) | Sag captured with magnitude, duration, timestamp |
| Induce a swell/surge | Swell/transient captured and characterised |
| Add a non-linear load | THD rises; measured |
| Correlate an event with a trip | Timestamps match — cause identified |
| Export the log | Timestamped, characterised evidence record |
Bench-test checklist. If a row fails, stop and fix it before moving on.
Expected output
The dashboard shows live RMS/frequency/THD and a timeline of characterised events (type/magnitude/duration/time) with alarms and export.
{
"type": "sag",
"mag_pct": 71,
"dur_ms": 82,
"time": "2026-07-27 14:32:07"
}
A sag to 71% of nominal lasting 82 ms at 14:32:07 — a characterised, timestamped event that a normal meter would never have shown, and exactly the evidence needed to correlate with an equipment trip and take to the utility.
Troubleshooting: Common Errors & Fixes
Performance Optimisation
- Sample many times per cycle at a steady rate — this determines what you can see.
- Compute cycle RMS and event detection efficiently to keep up with the sampling.
- Log events (and snippets) locally and mirror; alarm on severe events.
- Trend event frequency for correlation and reporting.
- Replace every
delay()with amillis()comparison — blocking delays are the single most common cause of dropped readings. - Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
- Move networking into its own FreeRTOS task so a slow DNS lookup cannot stall the control loop.
- Use
uint8_t/uint16_twhere the range allows; on an 8-bit AVR a 32-bit add costs four times as much. - Batch several samples into one MQTT publish. Radio time, not CPU time, dominates the energy budget.
- Set the MQTT keep-alive to a value that matches your reporting interval so the broker does not churn reconnections.
- For battery builds use deep sleep between samples: an ESP32 drops from ~160 mA awake to about 10 µA asleep, which is the difference between days and months of runtime.
Safety Precautions
- Measuring mains is dangerous — use isolated sensing and a qualified person for the mains-side connection.
- Keep the low-voltage electronics isolated from the mains sensing.
- A DIY logger is indicative, not a calibrated, standards-compliant (IEC 61000-4-30) power-quality analyser; formal disputes may need certified equipment.
- Investigate/act on power-quality findings with appropriate electrical expertise.
- Mains voltage kills. Anything on the load side of the relay is at 230 V. Do not work on a powered circuit, and never leave exposed mains wiring on a bench where someone could touch it.
- Keep at least 6 mm of creepage between the mains and low-voltage sides of any board you make, and never route mains tracks under the microcontroller.
- Have a qualified electrician do the final installation into a consumer unit or wall fitting. In most jurisdictions this is a legal requirement, not a suggestion.
- Fit an RCD/RCBO upstream and fuse the load appropriately for its rating.
- Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
- Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
- Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.
Maintenance
- Verify voltage calibration and timestamp accuracy periodically.
- Check the log and off-device mirror; export/archive evidence.
- Confirm sampling rate/integrity after any change.
- Correlate events with equipment issues and act.
- Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
- Rotate the microSD card annually and keep an image of the working system. Cards used as loggers wear out silently.
- Keep the broker and dashboard containers patched, and rotate device credentials at least once a year.
- Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
- Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.
Future Improvements & Upgrades
A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.
- Add current channels for full power-quality (flicker, unbalance, power).
- Add standards-aligned event classification and reporting.
- Add waveform capture/streaming for detailed analysis.
- Correlate multiple loggers to locate disturbance sources.
- Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
- Add over-the-air firmware updates so you never have to physically reach a deployed node again.
- Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
- Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
- Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
- Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.
Frequently Asked Questions
References & Learning Resources
These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.
- Power quality — overviewReference
- Voltage sag (dip) and swellReference
- Total harmonic distortion (THD)Reference
- IEC 61000-4-30 power-quality measurementReference
- RMS and waveform measurementReference