AC Current Measurement

Hello everyone,

I’m currently doing a project on how to measure AC current using ACS712 and Arduino Mega 2560. The problem here is the result i got from my coding is not tally with the result I got from measuring the current using multimeter

I’m sorry I don’t know how to use the code tags.

Capture1.PNG

In the Quick Reply use the first symbol “</>”.Copy Your code and place it between the two code markers.

Hi here is my code

const int CurrentIn1 = A0;
int mVperAmp = 66; // use 100 for 20A Module and 66 for 30A Module

float CurrentL1 = 0;
double VRMS1 = 0;
double Voltage1 = 0;


void loop()
{
Voltage1 = getVPP1();
 VRMS1 = (Voltage1/2.0) *0.707; 
 CurrentL1 = ((VRMS1 * 1000)/mVperAmp)-0.07;
 Serial.println(" Zone 1:");
 Serial.print(CurrentL1);
 Serial.println("A");
}

float getVPP1()
{
  float result1;
  
  int readCurrent1;             //value read from the sensor
  int maxValue1 = 0;          // store max value here
  int minValue1 = 1024;          // store min value here
  
   uint32_t start_time = millis();
   while((millis()-start_time) < 1000) //sample for 1 Sec
   {
       readCurrent1 = analogRead(CurrentIn1);
       // see if you have a new maxValue
       if (readCurrent1 > maxValue1) 
       {
           /*record the maximum sensor value*/
           maxValue1 = readCurrent1;
       }
       if (readCurrent1 < minValue1) 
       {
           /*record the maximum sensor value*/
           minValue1 = readCurrent1;
       }
   }

the result i got from my coding is not tally with the result I got from measuring the current using multimeter

What results did you get from your coding, and what results from the multimeter?

A much safer way to measure AC current is to use a current transformer, as described here: Learn | OpenEnergyMonitor

You do understand what AC is, right? It goes positive & negative and it crosses-through zero twice per cycle. So... The minimum is zero and there's no need to "find" the minimum. The ACS712 puts-out a positive voltage but it's still zero twice per cycle.

If you simply read the values (like the Analog Read Serial Example) the values will look "random" because you are sampling a continuously-varying voltage.

You can take several readings in a "fast loop" over s short period of time and then find the maximum (ignoring everything else). Then, multiply by 0.707 to get the RMS. That 0.707 factor is only valid for sine waves (like the power line).

There is more than one version of the ACS712 and you'll have to look at the sensitivity spec (mV/A) to find the amps-to-volts conversion factor. And of course, you'll need to include the 5/1024 factor.

The result I get on my multimeter is around 0.29A but on the serial monitor it print 0.97. So, do i need to remove the line "minimum sensor value" from my coding? but the formula that I do look almost the same like what you just told me.

ACS712 puts-out a positive voltage but it's still zero twice per cycle.

Ignore this nonsense.

For zero current, the ACS712 outputs Vcc/2, as described in the data sheet.

Please post ALL your code. What you posted will not compile and won't work.

Thanks for the replies. Here is my full coding.

#include <SoftwareSerial.h>
#include <Wire.h>

SoftwareSerial mySerial (19,18);

/*
Measuring AC Current Using ACS712
*/
const int CurrentIn1 = A0;
const int CurrentIn2 = A1;
const int CurrentIn3 = A2;
int mVperAmp = 66; // use 100 for 20A Module and 66 for 30A Module


double Voltage1 = 0;
double Voltage2 = 0;
double Voltage3 = 0;

double VRMS1 = 0;
double VRMS2 = 0;
double VRMS3 = 0;

float CurrentL1 = 0;
float CurrentL2 = 0;
float CurrentL3 = 0;



void setup(){ 
 Serial.begin(9600);
 Wire.begin();
 mySerial.begin (9600);

 delay(1000);
}

void loop(){
 
 /*Reading current sensor 1*/
 Voltage1 = getVPP1();
 VRMS1 = (Voltage1/2.0) *0.707; 
 CurrentL1 = ((VRMS1 * 1000)/mVperAmp)-0.07;
 Serial.println(" Zone 1:");
 Serial.print(CurrentL1);
 Serial.println("A");

/*Reading current sensor 2*/
 Voltage2 = getVPP2();
 VRMS2 = (Voltage2/2.0) *0.707; 
 CurrentL2 = ((VRMS2 * 1000)/mVperAmp)-0.07;
 Serial.println(" Zone 2:");
 Serial.print(CurrentL2);
 Serial.println("A");

/*Reading current sensor 3*/
 Voltage3 = getVPP3();
 VRMS3 = (Voltage3/2.0) *0.707; 
 CurrentL3 = ((VRMS3 * 1000)/mVperAmp)-0.07;
 Serial.println(" Zone 3:");
 Serial.print(CurrentL3);
 Serial.println("A");

 mySerial.print("Current:");
 mySerial.print(CurrentL1);
 mySerial.print("A");
 mySerial.print("|");
 mySerial.print("Current:");
 mySerial.print(CurrentL2);
 mySerial.print("A");
 mySerial.print("|");
 mySerial.print("Current:");
 mySerial.print(CurrentL3);
 mySerial.println("A");
 delay (1000);
 
 /*Display for under current Zone 1*/
 if ((0.67 < CurrentL1) && (CurrentL1 < 0.74))
 {
  Serial.println("Lamp 1 Zone 1 need attention. Under current");
  }
 else if ((0.74 < CurrentL1) && (CurrentL1 < 0.79))
 {
  Serial.println("Lamp 2 Zone 1 need attention. Under current");
  }
 else if ((0.79 < CurrentL1) && (CurrentL1 < 0.84))
 {
  Serial.println("Lamp 3 Zone 1 need attention. Under current");
  }
 else if ((0.49 < CurrentL1) && (CurrentL1 < 0.54))
 {
   Serial.println ("Lamp 1 and 2 Zone 1 need attention. Under current.");
 }
 else if ((0.54 < CurrentL1) && (CurrentL1 < 0.59))
 {
   Serial.println ("Lamp 1 and 3 Zone 1 need attention. Under current.");
 }
 else if ((0.59 < CurrentL1) && (CurrentL1 < 0.64))
 {
   Serial.println ("Lamp 2 and 3 Zone 1 need attention. Under current");
 }
 else if (CurrentL1 < 0.44)
 {
  Serial.println ("All lamp in Zone 1 need attention. Under current");
  }

 /*Display for under current Zone 2*/
 if ((0.67 < CurrentL2) && (CurrentL2 < 0.74))
 {
  Serial.println("Lamp 1 Zone 2 need attention. Under current");
  }
 else if ((0.74 < CurrentL2) && (CurrentL2 < 0.79))
 {
  Serial.println("Lamp 2 Zone 2 need attention. Under current");
  }
 else if ((0.79 < CurrentL2) && (CurrentL2 < 0.84))
 {
  Serial.println("Lamp 3 Zone 2 need attention. Under current");
  }
 else if ((0.49 < CurrentL2) && (CurrentL2 < 0.54))
 {
   Serial.println ("Lamp 1 and 2 Zone 2 need attention. Under current.");
 }
 else if ((0.54 < CurrentL2) && (CurrentL2 < 0.59))
 {
   Serial.println ("Lamp 1 and 3 Zone 2 need attention. Under current.");
 }
 else if ((0.59 < CurrentL2) && (CurrentL2 < 0.64))
 {
   Serial.println ("Lamp 2 and 3 Zone 2 need attention. Under current");
 }
 else if (CurrentL2 < 0.44)
 {
  Serial.println ("All lamp in Zone 2 need attention. Under current");
  }
 
 /*Display for under current Zone 3*/
 if ((0.67 < CurrentL3) && (CurrentL3 < 0.74))
 {
  Serial.println("Lamp 1 Zone 3 need attention. Under current");
  }
 else if ((0.74 < CurrentL3) && (CurrentL3 < 0.79))
 {
  Serial.println("Lamp 2 Zone 3 need attention. Under current");
  }
 else if ((0.79 < CurrentL3) && (CurrentL3 < 0.84))
 {
  Serial.println("Lamp 3 Zone 3 need attention. Under current");
  }
 else if ((0.49 < CurrentL3) && (CurrentL3 < 0.54))
 {
   Serial.println ("Lamp 1 and 2 Zone 3 need attention. Under current.");
 }
 else if ((0.54 < CurrentL3) && (CurrentL3 < 0.59))
 {
   Serial.println ("Lamp 1 and 3 Zone 3 need attention. Under current.");
 }
 else if ((0.59 < CurrentL3) && (CurrentL3 < 0.64))
 {
   Serial.println ("Lamp 2 and 3 Zone 3 need attention. Under current");
}
 else if (CurrentL3 < 0.44)
 {
  Serial.println ("All lamp in Zone 3 need attention. Under current");
  }
}

float getVPP1()
{
  float result1;
  
  int readCurrent1;             //value read from the sensor
  int maxValue1 = 0;          // store max value here
  int minValue1 = 1024;          // store min value here
  
   uint32_t start_time = millis();
   while((millis()-start_time) < 1000) //sample for 1 Sec
   {
       readCurrent1 = analogRead(CurrentIn1);
       // see if you have a new maxValue
       if (readCurrent1 > maxValue1) 
       {
           /*record the maximum sensor value*/
           maxValue1 = readCurrent1;
       }
       if (readCurrent1 < minValue1) 
       {
           /*record the maximum sensor value*/
           minValue1 = readCurrent1;
       }
   }
   
   // Subtract min from max
   result1 = ((maxValue1 - minValue1) * 5.0)/1024.0;
      
   return result1;
 }

 float getVPP2()
{
  float result2;
  
  int readCurrent2;             //value read from the sensor
  int maxValue2 = 0;          // store max value here
  int minValue2 = 1024;          // store min value here
  
   uint32_t start_time = millis();
   while((millis()-start_time) < 1000) //sample for 1 Sec
   {
       readCurrent2 = analogRead(CurrentIn2);
       // see if you have a new maxValue
       if (readCurrent2 > maxValue2) 
       {
           /*record the maximum sensor value*/
           maxValue2 = readCurrent2;
       }
       if (readCurrent2 < minValue2) 
       {
           /*record the maximum sensor value*/
           minValue2 = readCurrent2;
       }
   }
   
   // Subtract min from max
   result2 = ((maxValue2 - minValue2) * 5.0)/1024.0;
      
   return result2;
 }

 float getVPP3()
{
  float result3;
  
  int readCurrent3;             //value read from the sensor
  int maxValue3 = 0;          // store max value here
  int minValue3 = 1024;          // store min value here
  
   uint32_t start_time = millis();
   while((millis()-start_time) < 1000) //sample for 1 Sec
   {
       readCurrent3 = analogRead(CurrentIn3);
       // see if you have a new maxValue
       if (readCurrent3 > maxValue3) 
       {
           /*record the maximum sensor value*/
           maxValue3 = readCurrent3;
       }
       if (readCurrent3 < minValue3) 
       {
           /*record the maximum sensor value*/
           minValue3 = readCurrent3;
       }
   }
   
   // Subtract min from max
   result3 = ((maxValue3 - minValue3) * 5.0)/1024.0;
      
   return result3;
 }

Your approach is basically correct, but if the power line has noise spikes, the peak to peak measurement will be too high.

Why did you include the constant (-0.07) ?

Post a link to the exact module you have. Does it include a filter capacitor?

Are you sure you are using the correct mV/Amp scale factor?

Have you measured your Arduino power supply voltage?

Consider calibrating the sensor using several current standards, following this tutorial: Why Calibrate? | Calibrating Sensors | Adafruit Learning System

Hi, I'm using ACS712 current sensor 30A module. The data sheet of the module is as in the link below. I'm using 66mV/A for the conversion. I'm sorry for the (-0.07), I'm just trying to change the value on the monitor
http://henrysbench.capnfatz.com/wp-content/uploads/2014/11/acs712-datasheet.pdf

Method is indeed correct, but the code could be more compact if you had used arrays.
Don't know why the original program is using such a long sampling time (1sec).
Long delays if you're measuring more than one ACS. I think 250ms (like a DMM) should be long enough.

What are you measuring.
Complex loads, like low energy lightbulbs (LED, spiral), could throw off the readings.
You must try these things with a resistive load (heater, incandescent lightbulb).

Remember that you only have a resolution of 1024/2*0.7= 358 steps across that 30Amp range.
The last digit of 0.97Amp is largely made up.
Leo..

Hi leo,

Thank you for the replies. I'm measuring incandescent lightbulb with power rating of 25W. Still can't figure out why I can't get the correct reading :cry:

My Arduino supply is 8 VDC.
The measured reading is around 0.08 A to 0.11 A. but i don't know why did it get to 0.97

I assume you’re on 120volt AC (from the DMM result).

Did you first test ONE sensor, with the original code, before you tried to use three sensors.

Are you sure you got the 30A version of the ACS712 (should be printed on the chip).
Leo…

Hi leo,

I'm measuring the current on 240V AC supply line and there is 30A printed on the chip just as you say.

Hi everyone,

Is there any way for me to calibrate the current sensor ACS712 to get the value that I need?

Consider calibrating the sensor using several current standards, following this tutorial: Why Calibrate? | Calibrating Sensors | Adafruit Learning System

You obviously didn’t read the forum rules about how to post.
That leaves us with a lot of questions.

SoftwareSerial mySerial (19,18); // which Arduino…
Is it a 5volt Arduino, and how are you powering the sensors.

A 0.29A DMM readout for a 240volt/25watt incadescent lightbulb doesn’t make sense.
It should be 25/240= ~0.1Amp.
Are you sure it isn’t a 75watt bulb.

Wrote this short test sketch that gets rid of the multi-stage way of calculating current.
And only a few lines are needed to calculate current for all three sensors when arrays are used.
If you need to calibrate, use the biggest resistive load you have (> 2000watt).
Post back the results.
Leo…

unsigned long startTime;
int rawValue, maxValue, minValue;
float current[3]; // for three sensors
float calFactor = 0.0259; // change last digit(s) to calibrate

void setup() {
  Serial.begin(9600);
}

void loop() {
  rawValues();
  // rest of the code here
  // current[0] holds the value for the first sensor
}

void rawValues() {
  for (int i = 0; i < 3; i++) {
    maxValue = 0;
    minValue = 1023;
    startTime = millis();
    while ((millis() - startTime) < 500) {
      rawValue = analogRead(i);
      if (rawValue > maxValue) maxValue = rawValue;
      if (rawValue < minValue) minValue = rawValue;
    }
    current[i] = (maxValue - minValue) * calFactor;
    Serial.print("Sensor");
    Serial.print(i + 1);
    Serial.print(": ");
    Serial.print(current[i], 1);
    Serial.print(" Amp");
    if (i < 2) Serial.print("\t");
    else Serial.println("");
  }
}

Did you read post#3.
The ACS712 (and the boards they come on) are not meant to be used with 240volt AC.
Leo..