Voltage in Indian homes often swings from 180 V to over 250 V, and fridges, ACs and pumps suffer at both ends. The ZMPT101B module has a small precision transformer and an op-amp. It turns the mains voltage into a small, isolated AC signal that an Uno can read safely — provided the mains side is wired and boxed properly.
On the Uno the low-voltage side is simple: 5V, GND and OUT to A0. At 5 V the output wave is centred at 2.5 V, right in the middle of the Uno’s ADC range. The L/N terminals go to the mains through a 250 mA fuse, inside a closed enclosure. That part is an electrician’s job.
The sketch samples A0 for 10 mains cycles and calculates the true RMS voltage. It flags LOW below 190 V and HIGH above 250 V, and shows NO SUPPLY during a power cut instead of a misleading low reading.
Wiring
| Arduino Uno R3 | ZMPT101B AC voltage sensor | Wire | Notes |
|---|---|---|---|
| 5V | VCC | red | At 5 V the output swings around 2.5 V, centred in the Uno’s 0–5 V ADC range. |
| GND | GND | black | |
| A0 | OUT | green | |
| 230 V AC via 250 mA fuse (electrician only) · L | L | brown | Live through an inline 250 mA fuse — electrician only. |
| 230 V AC via 250 mA fuse (electrician only) · N | N | blue | Neutral. The module’s transformer isolates this side from the Uno. |
5 V (some boards 3.3 V) part, 5 V board. OUT is an AC waveform centred on VCC/2. On ESP32/Pico power the module from 3.3 V if your board supports it, or divide OUT so it never exceeds 3.3 V.
Board quirks
- Electrician only. The L/N screw terminals and the solder joints under them carry 230 V. Mount the module in a closed enclosure, feed it through a 250 mA fuse from a circuit protected by an MCB and RCCB, and never touch the board while it is plugged in. Test the Uno side on USB from a laptop on battery first.
- The transformer isolates the Uno from the mains, but only when the module is wired as shown. Don’t connect the Uno’s GND to the mains neutral.
- AC must be measured as RMS. The sketch samples for 200 ms (ten 50 Hz cycles), removes the DC centre and takes the square root of the variance — what a true-RMS meter shows.
- Calibrate once against a true-RMS multimeter on the same socket: adjust
VOLTS_PER_COUNTuntil both agree. The module’s blue trimmer also changes the gain — set it so the waveform is not clipped (check with the Serial Plotter), then leave it alone. - The Uno’s ADC is more linear than the ESP32’s, so a single calibration point usually stays within a few volts across 180–260 V. If you care most about low-voltage alarms, calibrate near 200 V.
Code
// ZMPT101B AC voltage sensor on an Arduino Uno R3 - true-RMS mains voltage.
// Low-voltage side only: VCC → 5V, GND → GND, OUT → A0.
// L/N terminals: 230 V through a 250 mA fuse, in a closed enclosure - ELECTRICIAN ONLY.
// Calibrate VOLTS_PER_COUNT against a true-RMS multimeter on the same socket.
const uint8_t ZMPT_PIN = A0;
float VOLTS_PER_COUNT = 0.89; // change until the reading matches your meter
const unsigned long WINDOW_MS = 200; // 10 cycles of 50 Hz
void setup() {
Serial.begin(9600);
Serial.println(F("ZMPT101B on A0 - mains RMS every second"));
}
float readRmsCounts() {
// One pass: running mean and variance (Welford), so the DC midpoint drops out by itself.
unsigned long start = millis();
unsigned int n = 0;
float mean = 0, m2 = 0;
while (millis() - start < WINDOW_MS) { // ~1700 samples at the Uno's ~112 µs per analogRead
float x = analogRead(ZMPT_PIN);
n++;
float d = x - mean;
mean += d / n;
m2 += d * (x - mean);
}
return n > 1 ? sqrt(m2 / n) : 0;
}
void loop() {
float rmsCounts = readRmsCounts();
float volts = rmsCounts * VOLTS_PER_COUNT;
Serial.print(F("RMS counts "));
Serial.print(rmsCounts, 1);
Serial.print(F(" Mains "));
if (volts < 20) {
Serial.println(F("NO SUPPLY"));
} else {
Serial.print(volts, 0);
Serial.print(F(" V"));
if (volts < 190) Serial.println(F(" LOW"));
else if (volts > 250) Serial.println(F(" HIGH"));
else Serial.println();
}
delay(800);
}// ZMPT101B AC voltage sensor on an Arduino Uno R3 - true-RMS mains voltage.
// Low-voltage side only: VCC → 5V, GND → GND, OUT → A0.
// L/N terminals: 230 V through a 250 mA fuse, in a closed enclosure - ELECTRICIAN ONLY.
// Calibrate VOLTS_PER_COUNT against a true-RMS multimeter on the same socket.
const uint8_t ZMPT_PIN = A0;
float VOLTS_PER_COUNT = 0.89; // change until the reading matches your meter
const unsigned long WINDOW_MS = 200; // 10 cycles of 50 Hz
void setup() {
Serial.begin(9600);
Serial.println(F("ZMPT101B on A0 - mains RMS every second"));
}
float readRmsCounts() {
// One pass: running mean and variance (Welford), so the DC midpoint drops out by itself.
unsigned long start = millis();
unsigned int n = 0;
float mean = 0, m2 = 0;
while (millis() - start < WINDOW_MS) { // ~1700 samples at the Uno's ~112 µs per analogRead
float x = analogRead(ZMPT_PIN);
n++;
float d = x - mean;
mean += d / n;
m2 += d * (x - mean);
}
return n > 1 ? sqrt(m2 / n) : 0;
}
void loop() {
float rmsCounts = readRmsCounts();
float volts = rmsCounts * VOLTS_PER_COUNT;
Serial.print(F("RMS counts "));
Serial.print(rmsCounts, 1);
Serial.print(F(" Mains "));
if (volts < 20) {
Serial.println(F("NO SUPPLY"));
} else {
Serial.print(volts, 0);
Serial.print(F(" V"));
if (volts < 190) Serial.println(F(" LOW"));
else if (volts > 250) Serial.println(F(" HIGH"));
else Serial.println();
}
delay(800);
}Expected serial output
ZMPT101B on A0 - mains RMS every second
RMS counts 262.4 Mains 234 V
RMS counts 261.9 Mains 233 V
RMS counts 207.8 Mains 185 V LOWZMPT101B on A0 - mains RMS every second RMS counts 262.4 Mains 234 V RMS counts 261.9 Mains 233 V RMS counts 207.8 Mains 185 V LOW
Common errors
Reads NO SUPPLY with mains connected
The fuse has blown, or the trimmer is turned to minimum gain. With power OFF, check the fuse; then, with the enclosure closed, adjust the trimmer through its access hole only.
Reading jumps by 10–20 V
The waveform is clipped (trimmer too high) or the Uno’s 5V is noisy. Lower the trimmer gain, recalibrate, and average more windows.
Correct at 230 V but wrong at low voltage
Recalibrate at the voltage you care about most, or do a two-point calibration (one low, one normal).