Since writing up the article on how to build a simple Arduino home energy meter which measured the energy consumption for a single phase, I’ve had a number of people ask about doing a 3 phase energy meter. While there is a range of commercially available single phase energy meters available, the 3 phase meters aren’t nearly as common and tend to be quite expensive. So I decided to take the opportunity to build a 3 phase energy meter and fix up a couple of areas in the original energy meter’s code which could have been done better.
Again, with this meter I was going for simplicity. Sure, for perfectly accurate measurements you need to measure both the supply current and voltage but for this application and in the interests of keeping the energy meter simple and safe – only requiring a non-contact connection to your mains – I’ve decide to stick with a simple current measurement which gives you an estimate to within a couple of decimal points of a kilowatt hour.
This meter measures the supply current through each phase using a CT (current transformer) and then does a few calculations to give you the current, power, maximum power and kilowatt hours consumed for each phase. With a few changes to the code, you can also add your local tariffs and display the cost of electricity used to date.
This project assumes you know the basics of Arduino programming, otherwise read our article on getting started with Arduino, and that you know how to connect an LCD screen to an Arduino.
What You Will Need For A 3 Phase Energy Meter
- An Arduino (Uno used in this guide) – Buy Here
- LCD Shield (Or LCD Screen – how to connect an LCD screen) – Buy Here
- 3 x CTs – Talema AC1030 (See below for options and purchase links)
- 3 x 56Ω Burden Resistors – Buy Here
- 3 x 10µF Capacitors – Buy Here
- 6 x 100K Divider Resistors – Buy Here
How To Make The Energy Meter
First you need to start by assembling your components onto the CTs to create the current sensors which produce a signal which your Arduino can understand. An Arduino only has analogue voltage inputs which measure 0-5VDC, so you need to convert the current output from the CT into a voltage reference and then scale it into the 0-5V input range.
Assemble the Components
If you are going to be installing your power meter somewhere permanently then you may want to solder the resistors and capacitor directly onto each CT so that they cannot come loose. If you are simply trying this project for fun then a breadboard is perfect.
The basic circuit for the connection of the CTs to the Arduino is shown below:
The LCD screen shield already picks up on the analogue inputs but only A0 is used by the shield for the button inputs. Simply solder the five leads from your current sensors onto the pin headers on the shield and use A1 to A3 as your sensor inputs as shown below.
Once you have connected all of your components, you need to connect your sensors onto the supply you want to monitor. For connection to a typical 3 phase mains supply, connect one CT around each of the phases as shown below.
Each CT should only have one wire/phase running through its core.
NB – Be careful when connecting the CTs to your mains and make sure that the power to your board is switched off before doing anything in the mains box. Do not remove any wires or remove any screws before checking your local regulations with your local authority, you may require a certified electrician to install the CT for you.
Choosing Different Components
There are essentially four components which need to be chosen or correctly sized for you energy meter.
Choosing A Current Transformer
The first is the CT or current transformer. The one used here is the Talema AC1030 which can sense 30A nominal and 75A maximum current. At 220VAC, it can theoretically sense up to 16.5kW for short periods of time but it is sized to continuously sense 6.6kW which is suitable for a small household. To calculate how many amps yours needs to sense, take the maximum continuous power your are expecting to sense and divide that by your voltage (usually 110V or 220V depending on your country).
Sizing The Burden Resistor
Next you need to size your burden resistor R3, this converts your CT current into a voltage reference. Start by dividing your primary current (the maximum as used above) by your CT’s turns ratio (available on the data sheet). This should be around 500-5000 to 1. This article worked on 42A with a turns ratio 0f 1000:1 giving a secondary current of 0.042A or 42mA. Your analogue reference voltage to the Arduino is 2.5V so to determine the resistance you use R=V/I – R=2.5/0.042=59.5Ω. The closest standard resistor value is 56Ω, so this was used.
Here are some options on different CTs and their ideal burden resistors (in standard sizes):
- Murata 56050C – 10A – 50:1 – 13Ω
- Talema AS-103 – 15A – 300:1 – 51Ω
- Talema AC-1020 – 20A – 1000:1 – 130Ω
- Alttec L01-6215 – 30A – 1000:1 – 82Ω
- Alttec L01-6216 – 40A – 1000:1 – 62Ω
- Talema ACX-1050 – 50A – 2500:1 – 130Ω
- Alttec L01-6218 – 60A – 1000:1 – 43Ω
- Talema AC-1060 – 60A – 1000:1 – 43Ω
- Alttec L01-6219 – 75A – 1000:1 – 33Ω
- Alttec L01-6221 – 150A – 1000:1 – 18Ω
- CTYRZCH SCT-013-000 – 100A – Built In Burden Resistor – Buy Here
- TOOGOO SCT-013-000 – 100A – Buy Here
The capacitor used is 10µF which should be sufficient for most CT ranges for household applications.
Finally you need two dividing resistors to get the 2.5V reference voltage from the Arduino. They must be the same value, so R1=R2 and we don’t need much current so this articles uses two 100K resistors.
Upload the Sketch
Now you can upload your sketch onto your Arduino, if you haven’t uploaded a sketch before then follow this guide on getting started.
//Michael Klements
//The DIY Life
//26 February 2017
#include <LiquidCrystal.h>
int currentPins[3] = {1,2,3}; //Assign phase CT inputs to analog pins
double calib[3] = {11.8337,11.8234,12.0325};
double kilos[3];
unsigned long startMillis[3];
unsigned long endMillis[3];
double RMSCurrent[3];
int RMSPower[3];
int peakPower[3];
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Assign LCD screen pins, as per LCD shield requirements
void setup()
{
lcd.begin(16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
lcd.clear();
lcd.setCursor(0,0); // set cursor to column 0, row 0 (the first row)
lcd.print("3 Phase");
lcd.setCursor(0,1);
lcd.print("Energy Meter");
delay(2000);
}
void readPhase () //Method to read information from CTs
{
for(int i=0;i<=2;i++)
{
int current = 0;
int maxCurrent = 0;
int minCurrent = 1000;
for (int j=0 ; j<=200 ; j++) //Monitors and logs the current input for 200 cycles to determine max and min current
{
current = analogRead(currentPins[i]); //Reads current input and records maximum and minimum current
if(current >= maxCurrent)
maxCurrent = current;
else if(current <= minCurrent)
minCurrent = current;
}
if (maxCurrent <= 517)
{
maxCurrent = 516;
}
RMSCurrent[i] = ((maxCurrent - 516)*0.707)/calib[i]; //Calculates RMS current based on maximum value and scales according to calibration
RMSPower[i] = 220*RMSCurrent[i]; //Calculates RMS Power Assuming Voltage 220VAC, change to 110VAC accordingly
if (RMSPower[i] > peakPower[i])
{
peakPower[i] = RMSPower[i];
}
endMillis[i]= millis();
unsigned long time = (endMillis[i] - startMillis[i]);
kilos[i] = kilos[i] + ((double)RMSPower[i] * ((double)time/60/60/1000000)); //Calculate kilowatt hours used
startMillis[i]= millis();
}
}
void loop() //Calls the methods to read values from CTs and changes display
{
readPhase();
displayKilowattHours ();
delay(3000);
readPhase();
displayCurrent ();
delay(3000);
readPhase();
displayRMSPower ();
delay(3000);
readPhase();
displayPeakPower ();
delay(3000);
}
void displayKilowattHours () //Displays all kilowatt hours data
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(kilos[0]);
lcd.print("kWh");
lcd.setCursor(9,0);
lcd.print(kilos[1]);
lcd.print("kWh");
lcd.setCursor(0,1);
lcd.print(kilos[2]);
lcd.print("kWh");
lcd.setCursor(9,1);
lcd.print("Energy");
}
void displayCurrent () //Displays all current data
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(RMSCurrent[0]);
lcd.print("A");
lcd.setCursor(9,0);
lcd.print(RMSCurrent[1]);
lcd.print("A");
lcd.setCursor(0,1);
lcd.print(RMSCurrent[2]);
lcd.print("A");
lcd.setCursor(9,1);
lcd.print("Current");
}
void displayRMSPower () //Displays all RMS power data
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(RMSPower[0]);
lcd.print("W");
lcd.setCursor(9,0);
lcd.print(RMSPower[1]);
lcd.print("W");
lcd.setCursor(0,1);
lcd.print(RMSPower[2]);
lcd.print("W");
lcd.setCursor(9,1);
lcd.print("Power");
}
void displayPeakPower () //Displays all peak power data
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(peakPower[0]);
lcd.print("W");
lcd.setCursor(9,0);
lcd.print(peakPower[1]);
lcd.print("W");
lcd.setCursor(0,1);
lcd.print(peakPower[2]);
lcd.print("W");
lcd.setCursor(9,1);
lcd.print("Max Pwr");
}
Here is the link to download the 3 phase meter code.
Because your setup, CTs , resistors and input voltages may be different, there is a scaling factor in the sketch which you will need to change before you will get accurate results, see below for calibration. If your LCD is connected to the same pins as used here and your CT is connected to the same input pin, you should at least get the screens populated with some figures although these will most likely be incorrect and some may be negative.
This code, unlike our original simple Arduino energy meter’s code makes use of the millis() function to calculate the duration between cycles instead of relying on an estimate, this results in a slightly more accurate (about 0.5%) calculation. For those of you who have read that the millis() function goes into overflow after about 49 days, the code deals with the rollover automatically by making use of the unsigned long variable. For example, if the overflow happens at 10000, the start millis was 9987 and the end millis was 2031, the difference would be 2031-9987=-7956 but the value can’t be negative as it is unsigned so it becomes -7956+10000=2044 which is the correct duration.
Calibrate the Current Reading
As mentioned above, because your setup, CTs , resistors and input voltages may be different, there is a scaling factor in the sketch for each CT which you will need to change before you will get accurate results.
To calibrate your energy meter, your need to be sure that the current that your meter says is being drawn on each phase is what you expect is actually being drawn. In order to do this accurately, you need to find a calibrated load. These are not easy to come by in a normal household so you will need to find something which uses an established and consistent amount of power. I used a couple of incandescent light bulbs and spot lights, these come in a range of sizes and their consumption is fairly close to what is stated on the label, ie a 100W light bulb uses very close to 100W of real power as it is almost entirely a purely resistive load.
Plug in a small light bulb (100W or so) on each phase and see what load is displayed. You will now need to adjust the scaling factors defined in line 8 accordingly:
double calib[3] = {11.8337,11.8234,12.0325}
In this case they were 11.8337 for phase 1, 11.8234 for phase 2 and 12.0325 for phase 3. They may be higher or lower depending on your application. Either use linear scaling to calculate this figure or, if you’re not good with math, play around with different values until the load you have plugged in is shown on the energy meter’s screen.
The Energy Meter In Operation
Once you have you energy meter calibrated and the scaling factors have been uploaded onto the Ardunio, your meter should be ready to connect and leave to monitor your energy consumption.
Upon startup, you’ll see a 3 Phase Energy Meter screen followed by cycling through the current, power, maximum power and kilowatt hours consumed screens. In each case, the top line displays phase 1 and phase 2’s measurements and the bottom line displays phase 3’s measurements.
Current Screen
Power Screen
Maximum Power Screen
Energy Consumption Screen
Video Of The Energy Meter In Operation
How did this project go for you? What have you used it to monitor? If you have any questions or would like to share your build of this three-phase energy meter, please post a comment below or send a mail using the contact form.



































































