0% found this document useful (0 votes)
93 views10 pages

AC Meter With LCD

This document provides code to monitor AC power values including voltage, current, power, and frequency using an Arduino. It measures RMS voltage and current values with analog input pins and calculates apparent and real power. The code displays readings on an LCD screen refreshed every second and in the serial monitor. It includes offset calibration functions to improve accuracy. Safety notes are provided to handle electricity safely.

Uploaded by

khalid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
93 views10 pages

AC Meter With LCD

This document provides code to monitor AC power values including voltage, current, power, and frequency using an Arduino. It measures RMS voltage and current values with analog input pins and calculates apparent and real power. The code displays readings on an LCD screen refreshed every second and in the serial monitor. It includes offset calibration functions to improve accuracy. Safety notes are provided to handle electricity safely.

Uploaded by

khalid
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

// AC Power Monitoring with LCD By Solarduino

// Note Summary
// Note : Safety is very important when dealing with electricity. We take no
responsibilities while you do it at your own risk.
// Note : This AC Power Monitoring Code needs AC current module and AC Voltage
Module to determine AC Power value.
// Note : This Code monitors RMS Voltage, RMS current, RMS AC Power (Apparent
Power) and Instantaneous AC Power (Active Power)
// Note : The value shown in Serial Monitor is refreshed every second, can be used
for 50Hz and 60Hz.
// Note : The frequency is measured by counting time and average it for every 25
samples taken (1 sample is 1 cycle).
// Note : The auto calibration (voltageOffset1 & currentOffset1) is using averaged
analogRead value of 1000 samples.
// Note : The auto calibration (voltageOffset2 & currentOffset2) is using
calculated RMS value including Offset1 value for calibration.
// Note : The unit provides reasonable accuracy and may not be comparable with
other expensive branded and commercial product.
// Note : All credit shall be given to Solarduino.

/
*//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
////////////////*/////////////*/

/* 0- General */

int decimalPrecision = 2; // decimal places for all


values shown in LED Display & Serial Monitor

/* 1- AC Voltage Measurement */

int VoltageAnalogInputPin = A2; // Which pin to measure


voltage Value
float voltageSampleRead = 0; /* to read the value of a
sample*/
float voltageLastSample = 0; /* to count time for each
sample. Technically 1 milli second 1 sample is taken */
float voltageSampleSum = 0; /* accumulation of sample
readings */
float voltageSampleCount = 0; /* to count number of
sample. */
float voltageMean ; /* to calculate the
average value from all samples*/
float RMSVoltageMean ; /* square roof of
voltageMean*/

/*1.1 Offset AC Voltage */

int voltageOffsetRead = 0; /* to change the mode for


offset */
float voltageOffset1 = 0; // to Offset deviation
and accuracy. Offset any fake current when no current operates.
// Offset will
automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
// If you do not have LCD
Display Shield, look into serial monitor to add or minus the value manually and key
in here.
float voltageOffset2 = 0; // to offset value due to
calculation error from squared and square root.
float voltageSampleSumOffset =0; /* accumulation of sample
readings for offset */
float offsetVoltageMean = 0; /* to calculate the
average value from all samples for offset, in analog values*/
float voltageOffsetLastSample = 0; /* to count time for each
sample for offset purpose. */
float voltageOffsetSampleCount = 0; /* to count number of
sample for offset. */

/* 2- AC Current Measurement */

int CurrentAnalogInputPin = A3; // Which pin to measure


Current Value
float mVperAmpValue = 31.25; // If using ACS712
current module : for 5A module key in 185, for 20A module key in 100, for 30A
module key in 66
// If using "Hall-Effect"
Current Transformer, key in value using this formula: mVperAmp = maximum voltage
range (in milli volt) / current rating of CT
/* For example, a 20A
Hall-Effect Current Transformer rated at 20A, 2.5V +/- 0.625V, mVperAmp will be 625
mV / 20A = 31.25mV/A */
float currentSampleRead = 0; /* to read the value of a
sample*/
float currentLastSample = 0; /* to count time for each
sample. Technically 1 milli second 1 sample is taken */
float currentSampleSum = 0; /* accumulation of sample
readings */
float currentSampleCount = 0; /* to count number of
sample. */
float currentMean ; /* to calculate the
average value from all samples*/
float RMSCurrentMean =0 ; /* square roof of
currentMean*/
float FinalRMSCurrent ; /* the final RMS current
reading*/

/*2.1 Offset AC Current */

int currentOffsetRead = 0; /* to change the mode for


offset */
float currentOffset1 = 0; // to Offset deviation
and accuracy. Offset any fake current when no current operates.
// Offset will
automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
// If you do not have LCD
Display Shield, look into serial monitor to add or minus the value manually and key
in here.
// 26 means add 26 to all
analog value measured
float currentOffset2 = 0; // to offset value due to
calculation error from squared and square root.
float currentSampleSumOffset = 0; /* accumulation of sample
readings for offset */
float offsetCurrentMean = 0; /* to calculate the
average value from all samples for offset, in analog values*/
float currentOffsetLastSample = 0; /* to count time for each
sample for offset purpose. */
float currentOffsetSampleCount = 0; /* to count number of
sample for offset. */

/* 3- AC Power Measurement */

float sampleCurrent1 ; /* use to calculate


current*/
float sampleCurrent2 ; /* use to calculate
current*/
float sampleCurrent3 ; /* use to calculate
current*/
float apparentPower; /* the apparent power
reading (VA) */
float realPower = 0; /* the real power reading
(W) */
float powerSampleRead = 0; /* to read the current X
voltage value of a sample*/
float powerLastSample = 0; /* to count time for each
sample. Technically 1 milli second 1 sample is taken */
float powerSampleCount = 0; /* to count number of
sample. */
float powerSampleSum = 0; /* accumulation of sample
readings */
float powerFactor = 0; /* to display power
factor value*/

/*3.1 Offset AC Power */

int powerOffsetRead = 0; /* to change the mode for


offset */
float powerOffset = 0; // to Offset deviation
and accuracy. Offset any fake current when no current operates.
// Offset will
automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
// If you do not have LCD
Display Shield, look into serial monitor to add or minus the value manually and key
in here.
float powerOffsetLastSample = 0; /* to count time for each
sample for offset purpose. */
float powerOffsetSampleCount = 0; /* to count number of
sample for offset. */

/* 4 - LCD Display */

#include<LiquidCrystal.h> /* Load the liquid Crystal


Library (by default already built-it with arduino solftware)*/
LiquidCrystal LCD(8,9,4,5,6,7); /* Creating the LiquidCrystal
object named LCD. The pin may be varies based on LCD module that you use*/
unsigned long startMillisLCD; /* start counting time for LCD
Display */
unsigned long currentMillisLCD; /* current counting time for
LCD Display */
const unsigned long periodLCD = 1000; // refresh every X seconds (in
seconds) in LED Display. Default 1000 = 1 second
int page = 1; /* flip page to display
values*/

void setup() /*codes to run once */

/* 0- General */

Serial.begin(9600); /* to display readings in


Serial Monitor at 9600 baud rates */

/* 4 - LCD Display */

LCD.begin(16,2); /* Tell Arduino that our


LCD has 16 columns and 2 rows*/
LCD.setCursor(0,0); /* Set LCD to start with
upper left corner of display*/
startMillisLCD = millis(); /* Start counting time
for LCD display*/

void loop()
/*codes to run again and again */
{

/* 0- General */

/* 0.1- Button Function */

int buttonRead;
buttonRead = analogRead (0);
// Read analog pin A0. Pin A0 automatically assigned for LCD Display Button
function (cannot be changed)

/*Right button is pressed */


if (buttonRead < 60)
{ LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); }

/* Up button is pressed */
else if (buttonRead < 200)
{
page = 1;
}

/* Down button is pressed */


else if (buttonRead < 400)
{
page = 2;
}

/* Left button is pressed */


else if (buttonRead < 600)
{ LCD.setCursor(0,0); LCD.print ("PRESS <SELECT> "); }
/* Select button is pressed */
else if (buttonRead < 800)
{
currentOffsetRead = 1;
// to activate offset for current
voltageOffsetRead = 1;
// to activate offset for voltage
powerOffsetRead = 1;
// to activate offset for power
LCD.setCursor(0,0);
/* set display words starting at upper left corner*/
LCD.print ("INITIALIZING..... ");
LCD.setCursor(0,1);
/* set display words starting at lower left corner*/
LCD.print ("WAIT 5 SEC ..... ");
}

/* 1- AC Voltage Measurement */

if(millis() >= voltageLastSample + 1 )


/* every 1 milli second taking 1 reading */
{
voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512) +
voltageOffset1; /* read the sample value */
voltageSampleSumOffset = voltageSampleSumOffset + voltageSampleRead;
/* values accumulate for offset purpose every milli second */

voltageSampleSum = voltageSampleSum + sq(voltageSampleRead) ;


/* accumulate value with older sample readings*/
voltageSampleCount = voltageSampleCount + 1;
/* to move on to the next following count */
voltageLastSample = millis() ;
/* to reset the time again so that next cycle can start again*/
}

if(voltageSampleCount == 1000)
/* after 1000 count or 1000 milli seconds (1 second), do the calculation and
display value*/
{
offsetVoltageMean = voltageSampleSumOffset/voltageSampleCount;
/* average the offset reading*/

voltageMean = voltageSampleSum/voltageSampleCount;
/* calculate average value of all sample readings taken*/
RMSVoltageMean = sqrt(voltageMean)+ voltageOffset2;
/* square root of the average value*/
Serial.print(" The Voltage RMS value is: ");
Serial.print(RMSVoltageMean,decimalPrecision);
Serial.println(" V ");
voltageSampleSum =0;
/* to reset accumulate sample values for the next cycle */
voltageSampleCount=0;
/* to reset number of sample for the next cycle */
voltageSampleSumOffset=0;
}
/* 1.1 - Offset AC Voltage */

if(voltageOffsetRead == 1)
/* Run this code when button SELECT is pressed */
{
voltageOffset1 = 0;
if(millis()>= voltageOffsetLastSample + 1)
/* keep countng time for offset1*/
{

voltageOffsetSampleCount = voltageOffsetSampleCount + 1;
/* 1 milli second add 1 count*/

voltageOffsetLastSample = millis();
/* to reset the time again so that next cycle can start again*/

if(voltageOffsetSampleCount == 2000)
/* after 2 seconds, run this codes. */
{

voltageOffset1 = -1*(offsetVoltageMean);
/* set the offset values */
voltageOffsetRead = 2;
/* go for second offset Settings */
voltageOffsetSampleCount = 0;
/* to reset the time again so that next cycle can start again */

}
}

if(voltageOffsetRead == 2)
/* Run this code after first offset done */
{
voltageOffset2 = 0;
/* set back currentOffset2 as default*/
if(millis()>= voltageOffsetLastSample + 1)
/* keep countng time for offset2*/
{

voltageOffsetSampleCount = voltageOffsetSampleCount + 1;

voltageOffsetLastSample = millis();

if(voltageOffsetSampleCount == 2000)
/* after 2 seconds, run this codes. */
{

voltageOffset2 = - RMSVoltageMean;
/* set the offset values */
voltageOffsetRead = 0;
/* change the offset mode to original, wait until the button is pressed again */

voltageOffsetSampleCount = 0;
/* to reset the time again so that next cycle can start again */
}
}

/* 2- AC Current Measurement */

if(millis() >= currentLastSample + 1)


/* every 1 milli second taking 1 reading */
{
currentSampleRead = analogRead(CurrentAnalogInputPin)-512 +
currentOffset1; /* read the sample value */

currentSampleSumOffset = currentSampleSumOffset + currentSampleRead;


/* accumulate offset value */

currentSampleSum = currentSampleSum + sq(currentSampleRead) ;


/* accumulate value with older sample readings*/
currentSampleCount = currentSampleCount + 1;
/* to move on to the next following count */
currentLastSample = millis();
/* to reset the time again so that next cycle can start again*/
}

if(currentSampleCount == 1000)
/* after 1000 count or 1000 milli seconds (1 second), do the calculation and
display value*/
{
offsetCurrentMean = currentSampleSumOffset/currentSampleCount;
/* average offset value*/

currentMean = currentSampleSum/currentSampleCount;
/* calculate average value of all sample readings taken*/
RMSCurrentMean = sqrt(currentMean)+currentOffset2 ;
/* square root of the average value*/
FinalRMSCurrent = (((RMSCurrentMean /1024) *5000) /mVperAmpValue);
/* calculate the final RMS current*/
Serial.print(" The Current RMS value is: ");
Serial.print(FinalRMSCurrent,decimalPrecision);
Serial.println(" A ");
currentSampleSum =0;
/* to reset accumulate sample values for the next cycle */
currentSampleCount=0;
/* to reset number of sample for the next cycle */
currentSampleSumOffset=0;
/* to reset accumulate offset value for the next cycle*/
}

/* 2.1 - Offset AC Current */

if(currentOffsetRead == 1)
/* Run this code when button SELECT is pressed */
{
currentOffset1 = 0;
/* set currentOffset back to default value*/
if(millis()>= currentOffsetLastSample + 1)
/* keep countng time for offset1*/
{

currentOffsetSampleCount = currentOffsetSampleCount + 1;
currentOffsetLastSample = millis();

if(currentOffsetSampleCount == 2000)
/* after 2 seconds, run this codes. */
{

currentOffset1 = - offsetCurrentMean;
/* set the offset values */
currentOffsetRead = 2;
/* go for second offset Settings */
currentOffsetSampleCount = 0;
/* to reset the time again so that next cycle can start again */

}
}

if(currentOffsetRead == 2)
/* Run this code after first offset done */
{
currentOffset2 = 0;
/* set back currentOffset2 as default*/
if(millis()>= currentOffsetLastSample + 1)
/* keep countng time for offset2*/
{

currentOffsetSampleCount = currentOffsetSampleCount + 1;

currentOffsetLastSample = millis();

if(currentOffsetSampleCount == 2000)
/* after 2 seconds, run this codes. */
{

currentOffset2 = - RMSCurrentMean;
/* set the offset values */
currentOffsetRead = 0;
/* change the offset mode to original, wait until the button is pressed again */

currentOffsetSampleCount = 0;
/* to reset the time again so that next cycle can start again */
}

/* 3- AC Power with Direction */

if(millis() >= powerLastSample + 1)


/* every 1 milli second taking 1 reading */
{
sampleCurrent1 = analogRead(CurrentAnalogInputPin)-512+ currentOffset1;
sampleCurrent2 = (sampleCurrent1/1024)*5000;
sampleCurrent3 = sampleCurrent2/mVperAmpValue;
voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512)+
voltageOffset1 ;
powerSampleRead = voltageSampleRead * sampleCurrent3 ;
/* real power sample value */
powerSampleSum = powerSampleSum + powerSampleRead ;
/* accumulate value with older sample readings*/
powerSampleCount = powerSampleCount + 1;
/* to move on to the next following count */
powerLastSample = millis();
/* to reset the time again so that next cycle can start again*/
}

if(powerSampleCount == 1000)
/* after 1000 count or 1000 milli seconds (1 second), do the calculation and
display value*/
{
realPower = ((powerSampleSum/powerSampleCount)+ powerOffset) ;
/* calculate average value of all sample readings */
Serial.print(" The Real Power (W) is: ");
Serial.print(realPower);
Serial.println(" W ");
apparentPower= FinalRMSCurrent*RMSVoltageMean;
/*Apparent power do not need to recount as RMS current and RMS voltage values
available*/
Serial.print(" The Apparent Power (VA) is: ");
Serial.print(apparentPower,decimalPrecision);
Serial.println(" VA ");
powerFactor = realPower/apparentPower;
if(powerFactor >1 || powerFactor<0)
{
powerFactor = 0;
}
Serial.print(" The Power Factor is: ");
Serial.println(powerFactor,decimalPrecision);

powerSampleSum =0;
/* to reset accumulate sample values for the next cycle */
powerSampleCount=0;
/* to reset number of sample for the next cycle */
}

/* 3.1 - Offset AC Power */

if(powerOffsetRead == 1)
/* Run this code after first offset done */
{
powerOffset = 0;
/* set back currentOffset2 as default*/
if(millis()>= powerOffsetLastSample + 1)
/* keep countng time for offset2*/
{

powerOffsetSampleCount = powerOffsetSampleCount + 1;

powerOffsetLastSample = millis();

if(powerOffsetSampleCount == 5000)
/* after 5 seconds, run this codes. */
{

powerOffset = -realPower;

powerOffsetRead = 0;
/* change the offset mode to original, wait until the button is pressed again */

powerOffsetSampleCount = 0;
/* to reset the time again so that next cycle can start again */
}

/* 4 - LCD Display */

currentMillisLCD = millis();
/* Set current counting time */
if (currentMillisLCD - startMillisLCD >= periodLCD && page ==1)
/* for every x seconds, run the codes below*/
{
LCD.setCursor(0,0);
/* Set cursor to first colum 0 and second row 1 */
LCD.print("I=");
LCD.print(FinalRMSCurrent,decimalPrecision);
/* display current value in LCD in first row */
LCD.print("A ");
LCD.print("V=");
LCD.print(RMSVoltageMean,decimalPrecision);
/* display current value in LCD in first row */
LCD.print("V ");
LCD.setCursor(0,1);
LCD.print(realPower,decimalPrecision);
LCD.print("W ");
LCD.print(apparentPower,decimalPrecision);
/* display current value in LCD in first row */
LCD.print("VA ");
startMillisLCD = currentMillisLCD ;
/* Set the starting point again for next counting time */
}

if( currentMillisLCD - startMillisLCD >= periodLCD && page ==2)


{
LCD.setCursor(0,0);
/* Set cursor to first colum 0 and second row 1 */
LCD.print("PF=");
LCD.print(powerFactor,decimalPrecision);
LCD.print(" ");
LCD.setCursor(0,1);
LCD.print(" ");
startMillisLCD = currentMillisLCD ;
/* Set the starting point again for next counting time */
}

You might also like