AC Voltage & Frequency Measurement with Arduino

Building a DIY AC voltage & frequency measurement circuit using Arduino development board is a nice project for students and hobbyists, as the one shown in this post with AC line voltage & frequency values printed on LCD and sent to Arduino IDE serial monitor tool.
The good thing with this project is that it is very accurate and stable when compared with a pre-calibrated Fluke 289 industrial digital multimeter. Also, mains network is totally isolated from our Arduino hardware circuit using a voltage transformer. This circuit can measure domestic Phase-to-Phase and Phase-to-Natural voltages up to 500V AC with RMS calculation.

Arduino MEGA AC voltage & frequency measurement with LCD and transformer RMS circuit

No warranty is provided with this project, so do it at your own risk!
A part of project circuit may be subjected to a high voltage level which is very harmful to human body, so be-careful!

AC: Alternating Current.
DC: Direct Current.
TRMS (True RMS): True Root Mean Square.
ADC: Analog-to-Digital Converter
PCB: Printed Circuit Board
DIY: Do It Yourself
Op amp: operational amplifier
DMM: Digital Multi-Meter

AC Voltage & Frequency Measurement with Arduino Circuit:
Project circuit diagram is shown below (click on the image to view the image in higher resolution).

Arduino MEGA AC voltage and frequency measurement with LCD

Hardware required:
This is a summary of circuit required parts (circuit schematic diagram may contain some component parameters not mentioned below).

  • Arduino MEGA or equivalent board (U1)  —>   ATmega2560 microcontroller details
  • DL-PT202D 2mA/2mA voltage sensor transformer (T1)
  • 2 x OPA2191 op amp (U4, U5)   —>  details
  • ADR4520 2.048 voltage reference (U3)   —> details
  • TPS60403 charge pump voltage inverter (U2)   —>   details
  • TLV3502 dual comparator IC  —> details
  • 1602 LCD screen
  • BAT54S dual serial small signal Schottky diode (D1)
  • SMBJ3.3CA TVS diode (D2)
  • 3 x 2.2uF capacitor (C6, C7, C17)
  • 3 x 1uF capacitor (C1, C2, C3)
  • 8x 100nF capacitor (C4, C5, C9, C10, C12, C14, C18, C19)
  • 3 x 10nF capacitor (C11, C13, C16)
  • 2 x 1nF capacitor (C8, C15)
  • 1M Ohm resistor (R20)
  • 2 x 100k Ohm resistor (R17, R18)
  • 4 x 75k Ohm resistor (R6, R7, R11, R12)
  • 4 x 20k Ohm resistor (R3, R4, R13, R16)
  • 8 x 10k Ohm resistor (R2, R5, R8, R14, R15, R19, R21, R22)
  • 300 Ohm resistor (R10)
  • 100 Ohm resistor (R9)
  • 10k ohm variable resistor (R1)
  • Breadboard & jumper wires

Circuit description:
The voltage to measure terminals is indicated in the circuit diagram as ‘AC Source’, we can apply an AC voltage up to 500V, this means we can measure home phase-to-natural (230V) and phase-to-phase (400V) voltages.

The two AC voltage source terminals are connected to DL-PT202D transformer (T1) through 4 current limiting resistors each of 75k ohm (R6, R7 & R11, R12), the tolerance of these resistors should be 1% or lower in order to get better results, voltage rating of each resistor should be greater than or equal to 200V with rated power of 0.25W or higher.

The voltage sensor transformer used in this project is just a current-type voltage transformer with ratio of 1000:1000, it converts an AC current on the primary to another equal one on the secondary. The maximum working current that may be applied to the primary is 2 mA RMS.

There are many alternatives to the voltage transformer that I’m using such as ZMPT112 and ZMPT101B, and any other replacement should have the same voltage rating (or higher) and ratio (2mA/2mA).
This type of transformers gives a significant safety factor to the circuit as it provide a galvanic isolation between the high voltage mains circuit and the low voltage control circuit which is in a direct contact with human body and other equipments. They also have a small size, low cost and require few components.

Since the voltage transformer used in this project is a current type then its secondary shouldn’t be kept floating, a resistor (R10) with resistance of 100 Ohm is connected in parallel with the secondary of the voltage transformer and hence the current is converted into voltage.

The ratio of the voltage transformer circuit including the resistors R6, R7 & R11, R12 & R10 is:
100/300k = 1/3000.
That means a voltage of 400V RMS will be scaled down to 0.13333 V = 133.33 mV RMS.

The voltage across the resistor R10 is amplified using OPA2191 differential amplifier from Texas Instruments, with a gain of 3. Therefore, the gain till this point becomes: 100 x 3 / 3000 = 1/1000
So, an input voltage of 400V RMS will be 400mV RMS at the output of OPA2191 U4A op amp.

The OPA2191 IC contains 2 independent op amps in one package which indicated in the circuit diagram by U4A and U4B. A bipolar supply of ±5 V is used to power this IC because we’re dealing with an AC signal.
To get a negative voltage of -5 V I used TPS60403 60mA charge pump voltage inverter from Texas Instruments. The TPS60403 device automatically generates -5 V from the +5 V supply.
The 5V positive of the OPA2191 and the TPS60403 comes from the Arduino MEGA board.

The second op amp of the OPA2191 (U4B) adds an offset voltage of 1.024 V to the input signal so the AC signal swings at 1.024V instead of 0V.
Before going to Arduino microcontroller (ATmega2560) ADC module, voltage signal enters to a voltage follower op amp circuit that provides a low impedance to the ADC and also gives more protection to the microcontroller against negative voltages.
Another OPA2191 IC is used to build 2 voltage follower circuits, one for the voltage signal earlier mentioned (U5A) and the other for DC bias voltage (U5B).

ADC Voltage reference:
I used the ADR4520 ultra low noise, high accuracy 2.048V voltage reference IC manufactured by Analog Devices to get a stable and accurate voltage of 2.048V, which is then used as a positive voltage reference for the Arduino microcontroller ADC module and a bias voltage for AC voltage signal.
The output of the ADR4520 is directly connected to Arduino mega AREF pin and to “U5B” op amp non-inverting terminal through a low pass filter. This “U5B” op-amp connection forms a voltage follower circuit with output voltage equals to input voltage 2.048V, and it is used as a DC bias voltage for the AC voltage signal and also for its zero-crossing events.

Zero-crossing detection:
For zero-crossing events detection I used TLV3502 dual, high-speed voltage comparator IC manufactured by Texas Instruments where AC signal (with DC bias) is connected to the inverting input and DC bias voltage to the non-inverting input of the comparator. Here, the DC bias is divided by 2 using a simple voltage divider circuit consists of resistors R17 & R18. Tolerance of R17 & R18 should be no more than 1%.

With this configuration the comparator compares the AC input voltage with 1.024V, if the input voltage is higher than 1.024V then the comparator output is low (0V) and if the input voltage is lower than 1.024V then the comparator output is high (5V). The output of the comparator is directly connected to Arduino digital pin 2.
Note that no pull-up resistor is needed for the comparator output as it is a push-pull type.

When a sufficient AC voltage is applied to the circuit the comparator outputs a series of pulses as described above. The Arduino can calculate time between pulse events and therefore signal period (P). With a known period we can calculate signal frequency using the formula: F = 1/P.

The 1602 LCD screen (2 rows and 16 columns) is used to display AC voltage & frequency values, it is connected to the Arduino board as follows:
RS —> Arduino digital pin 3
RW —> Arduino digital pin 4
E   —> Arduino digital pin 5
D4 —> Arduino digital pin 6
D5 —> Arduino digital pin 7
D6 —> Arduino digital pin 8
D7 —> Arduino digital pin 9
VSS, D0, D1, D2, D3 and K are connected to GND,
VEE to the 10k Ohms variable resistor (or potentiometer) output,
Pins VDD & A to Arduino 5V.
VEE pin is used to control the contrast of the LCD. A (anode) and K (cathode) are back light LED pins.

AC Voltage & Frequency Measurement with Arduino Code:
Project Arduino code is the one below, it was tested with Arduino MEGA board.
This Arduino code calculates average and RMS values of AC signals, the average value is just used in the RMS calculations. The MCU only shows the RMS value of the applied voltage on the LCD and serial monitor.

Simply the average (mean or DC offset) value in discrete-time is the sum of all sample values divided by number of samples:

mean value equation

and the RMS value in discrete-time can be calculated using the following equation:

RMS value equation

The Arduino uno and similar boards microcontroller (ATmega328P) contains a 10-bit ADC module, with a positive voltage reference of 2.048 V, a 0 V is digitally represented by 0 and a 2.048 V is represented by 1023.

Programming hints:
As we have a 10-bit ADC module working in the range [0, 2.048V], the MCU takes 64 samples every 1 cycle and saves the sampled data in an array named Samples.
The ADC module with auto-trigger option enabled, is configured to be triggered from Timer1 compare match B source, this allows automatic timed starting of analog-to-digital conversions.

For a 50 Hz signal the period is 20 ms, the MCU takes one sample every 20000/64 = 312.5 us. I used Timer1 compare match B to start an ADC conversion every 312.5 us and once the conversion is complete ADC interrupt saves the digital value on the the array variable Samples. The array element is incremented every new reading until the filling of all elements and the completion of the cycle.
If the line frequency is slightly changed the Arduino can measure the new frequency and adjust sample taking time according to the new frequency. Here, Timer 3 is used to measure pulse widths using external interrupt attached to Arduino digital pin 2.

The Arduino MEGA microcontroller ATmega2560 runs @16MHz (can achieve 16 MIPS), to start an analog-to-digital conversion every 312.5 us Timer1 is configured to run also @ 16MHz clock (prescaler = 1), this means Timer1 will make 5000 ticks in a duration of 312.5 us (16 x 312.5 = 5000) which is the pre-programmed value of OCR1A & OCR1B registers for a default line frequency of 50Hz. This value is not fixed and it continuously changing depending on input AC voltage frequency.

Rest of code is described through comments.

Full Arduino code:

The following video shows my simple DIY circuit for this project:

Related Projects:
AC & DC Current Measurement with Arduino and LTSR 25-NP Sensor
AC Current Measurement using Arduino and Current Transformer
Measure AC & DC Currents with Arduino and ACS758 Sensor
Interfacing Arduino with Current Transformer – AC Current Measurement
AC Current Measurement using Arduino and Current Transformer
AC Voltage Measurement using PIC18F46K22 Microcontroller
Isolated AC Voltage Measurement with Arduino and AMC1301 Amplifier

2 thoughts on “AC Voltage & Frequency Measurement with Arduino”

  1. I want to make this project but I have a question about the maximum voltages you used for the capacitors and the power ratings for the resistors. Does it affect the circuit if I use an different voltage or power ratings?

  2. I read your blog post on “Arduino AC Voltage Frequency Measurement Project with LCD Circuit” with great interest, and I must say, you’ve provided a comprehensive guide for those looking to delve into AC voltage and frequency measurements using Arduino. Your clear and step-by-step explanation, along with the accompanying circuit diagrams and code snippets, make it an excellent resource for beginners and enthusiasts alike.

Leave a Comment

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top