Interface ZMPT101B AC Voltage Sensor with Arduino

This tutorial explains how to interface the ZMPT101B AC voltage sensor with an Arduino development board. Learn how we can use the ADC of Arduino to measure the RMS voltage of single-phase AC (Alternating Current) and display the readings on the Serial Monitor of Arduino IDE. Household mains voltage such as 110 Volts or 230 Volts can be easily measured by the steps explained in this guide.

In the end, learn how we can make a simple RMS AC voltmeter by adding an OLED display. RMS (Root Mean Square) voltage is a measure of the effective or equivalent DC voltage of an AC signal. It represents the amount of power an AC voltage delivers to a load. The code explained in this article will help to accurately measure the RMS value of AC Voltage.

Can Arduino Measure AC Voltage?

An Arduino development board is not designed to handle high voltages and generally works with voltages up to 5 Volts only. To measure higher voltage such as household mains supply, we have to step down the voltage to a safe level for the Arduino board. In this guide, the ZMPT101B module we use has a dedicated step-down transformer for this purpose.

Components Required

  • An Arduino Development Board such as Arduino UNO
  • ZMPT101B AC Voltage Sensor Module
  • OLED Display (Optional)
  • Jumpers and connecting wires.

⚠ WARNING: Handle mains AC with caution. Things to keep in mind:

  • Turn off the power of the AC switch before working.
  • Double-check wiring connections before applying power.
  • If you’re unsure or inexperienced, consult a qualified electrician.

The ZMPT101B AC Voltage Sensor Module

The ZMPPT101B module provides an easy and safe way to measure AC voltages such as household 110 V or 230 V mains AC. The module is named after the ZMPPT101B high precision voltage transformer which steps down AC voltage to a lower voltage, allowing us to measure it safely. As the transformer only works with AC, measuring DC voltage is not possible with the ZMPT101B module.

The ZMPPT101B transformer has the following specifications:

Turns Ratio1000:1000
Rated Input Current 2mA
Rated Output Current 2mA

Apart from the transformer, the ZMPPT101B module consists of an IC and a few passive components that help extract meaningful sensor data easily.

Schematic

The ZMPT101B module commonly uses an LM358 Dual Operational Amplifier IC to precisely amplify the secondary voltage of the ZMPT101B transformer. Its datasheet can be found here: https://www.onsemi.com/download/data-sheet/pdf/lm358-d.pdf

The LM358 IC features dual opamps in a single IC. In the ZMPT101B module, both the opamps work in inverting amplifier configuration with a gain of 10(set by the 100K and 10K resistors R4, R5, R6, R7). The first opamp inverts the signal by 180 degrees and passes it to the second one, which again adds a phase shift of 180 degrees, thereby restoring the phase of the original signal. Moreover, using two opamps instead of one improves stability and bandwidth.

Both the opamps are biased at VCC/2 so that the waveform stays centered around the mid-point of Arduino’s operating voltage. A trimpot (R10) onboard the ZMPT101B module lets us adjust the gain or amplitude of the waveform obtained via the OUT pin.

ZMPT101B Pinout

The ZMPT101B module consists of 4 pins for interfacing with a microcontroller and a screw terminal block for connecting AC wires. Two of the pins are Ground pins (GND) and any one of them can be used. The module works with a 5 Volts supply between the VCC and GND pins. The maximum AC voltage to the input terminals should be limited to ±250 V.

The sensor module outputs a voltage equal to VCC/2 when no input AC is applied. In the presence of AC at the terminal block, voltage at its OUT pin varies proportional to the AC voltage supplied.

Wiring Arduino with ZMPT101B AC Voltage Sensor

Safety First! ⚠️ Before wiring components with your Arduino, turn OFF the mains AC supply for the device or socket where you plan to measure AC voltage. Stay safe!

Wiring Details:

  • Connect the 5V pin of Arduino UNO to the VCC pin of the ZMPT101B module.
  • Connect the A0 pin of Arduino UNO to the OUT pin of the ZMPT101B module.
  • Connect the GND pin of Arduino UNO to the GND pin of the ZMPT101B module.
  • Connect Phase and Neutral wires from a single-phase AC source to the screw terminal blocks of the ZMPT101B module. If you want to measure the voltage across an electrical load/device, extend two wires from the load to the terminal blocks of ZMPT101B i.e. connect the load and ZMPT101B module in parallel.

Here we use the A0 pin in Arduino for ADC(Analog-to-Digital Converter) input. You can use any other pin in Arduino that supports ADC.

Interfacing ZMPT101B using Arduino Code

Adjusting the AC Waveform

To obtain valid results, we first need to ensure that the signal from the ZMPT101B is free from distortion. Here are the steps:

  • Keep the AC turned OFF initially for safety. Connect all the components as shown in the schematic above.
  • Upload the following code to obtain the ADC values from the sensor.
void setup() {
  Serial.begin(115200);
}

void loop() {
  Serial.println(analogRead(A0));
  delayMicroseconds(1000);
}Code language: JavaScript (javascript)
  • Turn ON the AC. Go to Tools>Serial Plotter in Arduino IDE to view the waveform read by the ADC. Set the correct baud rate (115200) in the Serial Plotter window. The data read by the ADC should look like a sine wave when plotted.
  • If the image is distorted or clipped, adjust the amplitude of the wave by rotating the trimpot (potentiometer) onboard the ZMPT101B module until the wave resembles a sine wave.

ZMPT101B Arduino Library

To make the interfacing process easy, we shall use a library that allows us to calibrate the sensor and get readings. To install the library, go to Library Manager in Arduino IDE and search for “ZMPT101B”. Install the library by Abdurraiq Bachmid.

Sensor Calibration

We have to calibrate the sensor to get reliable readings.

Steps for calibration:

  • Measure the AC voltage using a voltmeter or multimeter.
#include <ZMPT101B.h>

#define ACTUAL_VOLTAGE 237.0f // Adjust based on real voltage

#define START_VALUE 0.0f  // Initial sensitivity
#define STOP_VALUE 1000.0f  // Max sensitivity limit
#define STEP_VALUE 0.25f  // Increment step for calibration
#define TOLLERANCE 1.0f  // Acceptable voltage deviation

#define MAX_TOLLERANCE_VOLTAGE (ACTUAL_VOLTAGE + TOLLERANCE)  // Upper tolerance limit
#define MIN_TOLLERANCE_VOLTAGE (ACTUAL_VOLTAGE - TOLLERANCE)  // Lower tolerance limit

ZMPT101B voltageSensor(A0, 50.0);  // Voltage sensor instance

void setup() {
  Serial.begin(115200);
  Serial.print("The Actual Voltage: ");
  Serial.println(ACTUAL_VOLTAGE);

  float senstivityValue = START_VALUE;
  voltageSensor.setSensitivity(senstivityValue);
  float voltageNow = voltageSensor.getRmsVoltage();

  Serial.println("Start calculate");

  // Adjust sensitivity until voltage is within tolerance
  while (voltageNow > MAX_TOLLERANCE_VOLTAGE || voltageNow < MIN_TOLLERANCE_VOLTAGE) {
    if (senstivityValue < STOP_VALUE) {
      senstivityValue += STEP_VALUE;
      voltageSensor.setSensitivity(senstivityValue);
      voltageNow = voltageSensor.getRmsVoltage();
      
      Serial.print(senstivityValue);
      Serial.print(" => ");
      Serial.println(voltageNow);
    } else {
      Serial.println("Unfortunately, the sensitivity value cannot be determined");
      return; // Stop if sensitivity reaches limit
    }
  }

  Serial.print("Closest voltage within tolerance: ");
  Serial.println(voltageNow);
  Serial.print("Sensitivity Value: ");
  Serial.println(senstivityValue, 10);
}

void loop() {}  // Nothing to do in loopCode language: PHP (php)
  • In the following line within the code, replace the ACTUAL_VOLTAGE value with the one you got by measuring. I obtained 237 Volts AC using a True RMS multimeter which I used in this code.
#define ACTUAL_VOLTAGE 237.0fCode language: CSS (css)
  • Open the Serial Monitor in Arduino IDE and wait for the “Sensitivity Value” to be displayed. The calculation may take a few seconds.
  • Take note of this sensitivity value as it will be used in the main code.

Code to Read RMS AC Voltage

Here is the main code:

#include <ZMPT101B.h>

#define SENSITIVITY 462.5f

// ZMPT101B sensor output connected to analog pin A0
// and the voltage source frequency is 50 Hz.
ZMPT101B voltageSensor(A0, 50.0);

void setup() {
  Serial.begin(115200);
  voltageSensor.setSensitivity(SENSITIVITY);
}

void loop() {
  float voltage = voltageSensor.getRmsVoltage();
  Serial.print("AC Voltage= ");
  Serial.println(voltage);
  delay(1000);
}Code language: PHP (php)
  • Replace the sensitivity value in the code with the one you obtained in the steps above.
  • Open the Serial Monitor to view the AC voltage.

Make an AC Voltmeter with OLED Display

Now that we have a solid grasp of the fundamentals, let’s make a simple AC voltmeter by adding an OLED display to our project.

The basics of interfacing an OLED display is explained in our guide: Interface Arduino with SSD1306 OLED Display Using I2C

Wiring

The wiring of ZMPT101B with Arduino stays the same as explained earlier. A 128×64 pixels monochrome OLED display is connected by using the A4 pin in Arduino for SDA and the A5 pin for SCL.

Arduino Code for AC Voltmeter

For the OLED display, we shall use the Adafruit GFX and Adafruit SSD1306 libraries which can be installed via the library manager. After installing the libraries, upload the following code which will display the AC RMS voltage obtained from the ZMPT101B sensor on the OLED display.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ZMPT101B.h>

#define SCREEN_WIDTH 128  // OLED width
#define SCREEN_HEIGHT 64  // OLED height
#define OLED_RESET    -1  // Reset pin (-1 for shared reset)
#define SCREEN_ADDRESS 0x3C  // I2C address for 128x64 OLEDs

#define SENSITIVITY 462.5f  // Voltage sensor sensitivity
#define ADC_PIN A0  // ADC input pin

ZMPT101B voltageSensor(ADC_PIN, 50.0);  // Sensor instance
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // OLED instance

void setup() {
    Serial.begin(115200);
    voltageSensor.setSensitivity(SENSITIVITY);

    // Init OLED display
    if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
        Serial.println("SSD1306 allocation failed");
        for (;;); // Halt if display fails
    }

    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);
    display.display();
}

void loop() {
    float voltage = voltageSensor.getRmsVoltage();
    
    // Display voltage on OLED
    display.clearDisplay();
    display.setTextSize(2);
    display.setCursor(15, 10);
    display.print("Voltage=");
    display.setCursor(25, 35);
    display.print(voltage, 2);
    display.print(" V");
    display.display();

    delay(1000);  // Update every second
}Code language: PHP (php)

Demonstration

Troubleshooting

Check the jumper wires for continuity if you find any errors while making the project.

I found that measuring the AC voltage with a multimeter on the screw terminal block may slightly change the values displayed on the Serial Monitor. It is better to measure the AC voltage in the socket or near the load while calibrating.

Final Thoughts

While the ZMPT101B offers a practical solution, keep in mind that proper calibration is essential for precise measurements. You can also use an external ADC like the ADS1115 to get higher-resolution ADC readings. The information in this tutorial will be helpful in making various projects such as undervoltage/overvoltage monitoring, energy monitoring, fault detection, or automation.

I hope you found this guide to measure AC voltage using Arduino useful. If you want to measure alternating current too, read: Measure AC using Arduino & ACS712 Current Sensor


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *