# Measure AC current accurately (100 mA to 10 A)

#### anandhuskumar

Joined May 14, 2014
29
Hi,
I am trying to build a device which can measure the AC current accurately and with a large measuring range. I tried using ACS712 sensor with arduino, but when I tried to measure the current with a heat gun as load, the ACS712 module's output voltage is initially increasing, but when I increased the load (stepped up the level of heat gun), the voltage is decreasing. I don't understand why the voltage is decreasing as the current is increasing, because I tried measuring using a multimeter as well. For the first level of heat gun, it shows around 2A, for which the ACS712 sensor gave an output of 2.8V and when I tried the second level, the multimeter measured around 7A and the output of ACS712 goes back to 2.5V. And when I plugged in a 7W LED lamp as load, there is no change in the output voltage of ACS712.
Please help. And is there any other modules or sensors which can be used for this application. I can't use large sensors or modules. It needs to be as small as possible. Thank you in advance.

#### Ian0

Joined Aug 7, 2020
8,406
How are you deriving the current from the output of the ACS712?
The ACS712 will give an instantaneous output centred on 2.5V. You have to subtract the offset, square the output, sum the squares and extract the square root to get the AC current.

#### anandhuskumar

Joined May 14, 2014
29
How are you deriving the current from the output of the ACS712?
The ACS712 will give an instantaneous output centred on 2.5V. You have to subtract the offset, square the output, sum the squares and extract the square root to get the AC current.
Yes, that is how I derive the current from the sensor. But, isn't the senosor's output voltage supposed to increase when the load current increases? As I mentioned, It is giving an output voltage of 2.8V for approximately 2A current and gets decreased to 2.5V when the load current is increased to around 7A.

#### Ian0

Joined Aug 7, 2020
8,406
Yes, that is how I derive the current from the sensor. But, isn't the senosor's output voltage supposed to increase when the load current increases? As I mentioned, It is giving an output voltage of 2.8V for approximately 2A current and gets decreased to 2.5V when the load current is increased to around 7A.

#### anandhuskumar

Joined May 14, 2014
29
I am measuring the output voltage of ACS712 module using a multimeter now. And for measuring using Arduino I am using an ADS1115 module for better resolution, and the sampling rate is 0.86.

#### Ian0

Joined Aug 7, 2020
8,406
I am measuring the output voltage of ACS712 module using a multimeter now. And for measuring using Arduino I am using an ADS1115 module for better resolution, and the sampling rate is 0.86.
A multimeter will give you the average DC voltage, which will be 2.5V.
Some multimeters on AC ranges will ignore the DC offset and give you the rms value, which is what you need; but most won’t.

0.86 what?

#### anandhuskumar

Joined May 14, 2014
29
A multimeter will give you the average DC voltage, which will be 2.5V.
Some multimeters on AC ranges will ignore the DC offset and give you the rms value, which is what you need; but most won’t.

0.86 what?
t_start = micros();
while((micros() - t_start) < period) { //frequency(f) is 50Hz. Period = 1/f = 0.016 seg = 16,666 microsec
m++; // counter to be used for avg.
}

Current = (0.183908 * Vrms * Vrms) + (8.96874 * Vrms);

This is the code I am using to find get the adc value

#### Ian0

Joined Aug 7, 2020
8,406
You need to subtract the offset first.

#### anandhuskumar

Joined May 14, 2014
29
You need to subtract the offset first.
You mean, subtract the ac offset before taking the square root?

#### Ian0

Joined Aug 7, 2020
8,406
You mean, subtract the ac offset before taking the square root?
No, before that, before you square it.

#### ronsimpson

Joined Oct 7, 2019
2,752
Zero current is half of the supply voltage. Subtract 2.5V from the reading to get 0A to equal a 0 reading. Do this first.

#### Ian0

Joined Aug 7, 2020
8,406
There's another way to do it - if you examine the maths, you'll see that the DC offset is the mean, and the rms of the superimposed AC voltage is the standard deviation.
The standard deviation is the square root of the variance, and you can calculate the variance without having to know the offset (mean)

σ^2 = Σx^2/n-(Σx)^2/n^2

where x is the reading from your a/d and n is the number of samples.

#### anandhuskumar

Joined May 14, 2014
29
There's another way to do it - if you examine the maths, you'll see that the DC offset is the mean, and the rms of the superimposed AC voltage is the standard deviation.
The standard deviation is the square root of the variance, and you can calculate the variance without having to know the offset (mean)

σ^2 = Σx^2/n-(Σx)^2/n^2

where x is the reading from your a/d and n is the number of samples.
Thank you. I wll try to calculate it using this equation. You are right, the output is an AC signa. I tested using another multimeter and is showing the ac voltage without the dc offset and is increasing as the load current increases. Based on most articles online I thought the output is a constant dc voltage for the respective current drawn by the load. But the problem is that I can't make a consistent reading using the above code. So I am thinking about finding the peak value to calculate the voltage. Do I need to clamp down the signal to zero level before doing this or is it possible to subtract the dc offset in the code?

#### Ian0

Joined Aug 7, 2020
8,406
Based on most articles online I thought the output is a constant dc voltage for the respective current drawn by the load.
If you assume that someone who wants to measure AC current will buy a current transformer because it is cheaper, then the odds are that someone buying the ACS712 is measuring DC current.
If the ACS712 is being used to measure DC current then you assertion will be true!

If your micro has a 5V supply, and its a/d is referenced to the supply, then you won't go far wrong assuming that 0x8000 represents 0A, and if you subtract 0x8000 from the reading you will get a two's complement representation of the instantaneous current.
Now if your micro has a 3.3V supply then things get a bit trickier. If you have differential a/d inputs, then connect the - input to a resistive divider of two equal values across your 5V supply to give half supply. Don't use a 2.5V reference, because the ACS712's "zero" output is half the supply voltage not necessarily 2.5V, depending on how accurate your 5V supply is.
You could put a 5V/3.3V divider on the ACS712 output (4.7k/9.1k gets it within 0.1%) so that your a/D will read mid-scale at zero current.

I use the LEM current sensors, and they have two outputs, one being the mid-scale reference, so they can be connected to a differential amplifier when the sensor supply voltage and the micro supply voltage don't match.

I'll try the "variance equation" method myself in the next couple of days - it only crossed my mind when writing the post, but it does mean that you don't need to know exactly where the mid-scale value is.

Another possibility is to pass the data through a IIR high-pass filter, but make sure that the filter -3dB frequency is low enough that it' phase response doesn't upset your measurements - you need it to be below 5Hz.

#### anandhuskumar

Joined May 14, 2014
29
If you assume that someone who wants to measure AC current will buy a current transformer because it is cheaper, then the odds are that someone buying the ACS712 is measuring DC current.
If the ACS712 is being used to measure DC current then you assertion will be true!

If your micro has a 5V supply, and its a/d is referenced to the supply, then you won't go far wrong assuming that 0x8000 represents 0A, and if you subtract 0x8000 from the reading you will get a two's complement representation of the instantaneous current.
Now if your micro has a 3.3V supply then things get a bit trickier. If you have differential a/d inputs, then connect the - input to a resistive divider of two equal values across your 5V supply to give half supply. Don't use a 2.5V reference, because the ACS712's "zero" output is half the supply voltage not necessarily 2.5V, depending on how accurate your 5V supply is.
You could put a 5V/3.3V divider on the ACS712 output (4.7k/9.1k gets it within 0.1%) so that your a/D will read mid-scale at zero current.

I use the LEM current sensors, and they have two outputs, one being the mid-scale reference, so they can be connected to a differential amplifier when the sensor supply voltage and the micro supply voltage don't match.

I'll try the "variance equation" method myself in the next couple of days - it only crossed my mind when writing the post, but it does mean that you don't need to know exactly where the mid-scale value is.

Another possibility is to pass the data through a IIR high-pass filter, but make sure that the filter -3dB frequency is low enough that it' phase response doesn't upset your measurements - you need it to be below 5Hz.
Here I am using a wemos D1 mini board and an ADS1115 module for reliability and better resolution. Yes the adc input is fed through a potential divider. I am using the ACS712 module because I need to reduce the size of the whole setup as low as possible. Is there any other reliable accurate sensors which can be used for this project. Or shall I continue using this ACS712 module. I can't get a consistent relaible reading out of it. I am yet to try the variance equation you mentioned and I will post the development here as soon as I do that. Thank you.

#### Ian0

Joined Aug 7, 2020
8,406
Run the ADS1115 off the same supply as the ACS712, use the differential inputs of the ADS1115, and bias the - input to half supply with two resistors. That will get rid of the offset.
Your next problem is the sample rate, unless you crank the ADS1115 up to its maximum speed it won't be fast enough. Unless you can implement some really steep anti-aliasing filters, I wouldn't sample any less than 800 samples per second.
It's probably not necessary to use a 16-bit a/d. You can get as good resolution with a 10-bit or 12-bit device and a higher sampling rate. The oversampling and subsequent filtering increases the resolution.

#### anandhuskumar

Joined May 14, 2014
29
Run the ADS1115 off the same supply as the ACS712, use the differential inputs of the ADS1115, and bias the - input to half supply with two resistors. That will get rid of the offset.
Your next problem is the sample rate, unless you crank the ADS1115 up to its maximum speed it won't be fast enough. Unless you can implement some really steep anti-aliasing filters, I wouldn't sample any less than 800 samples per second.
It's probably not necessary to use a 16-bit a/d. You can get as good resolution with a 10-bit or 12-bit device and a higher sampling rate. The oversampling and subsequent filtering increases the resolution.
Thank you so much. I will try that and will post the development. Guess I can use a potential divider to connect the ADS1115 to Wemos D1. I used ADS1115 because I read online that the adc on wemos d1 mini is not a reliable one.

Last edited:

#### Ian0

Joined Aug 7, 2020
8,406
Thank you so much. I will try that and will post the development. And is it okay to connect 5V powered ADS1115 to the 3.3V powered Wemos D1 mini? I used ADS1115 because I read online that the adc on wemos d1 mini is not a reliable one.
I2C is an open-drain structure, so one device can't harm another device on the same bus, even if they don't run at the same supply voltage.
Most I2C pins are 5V compatible, even on 3.3V devices, but you'd have to check.
If the pullup resistors go to 3.3V it doesn't quite get to the minimum spec for HIGH logic on the ADS1115 @ 5V, but the odds are it would work (but not something you'd do for production).
If you connect the pullup resistors to 5V, and the device isn't 5V compatible, the protection diodes would limit it to 4V, which would be enough to guarantee the ADS1115 to work - not a great piece of design but effective.

I don't know anything about Wemos D1, nor the ESP-8266, but I recall reading somewhere (perhaps on this forum) that it's A/D wasn't great.

#### anandhuskumar

Joined May 14, 2014
29
I2C is an open-drain structure, so one device can't harm another device on the same bus, even if they don't run at the same supply voltage.
Most I2C pins are 5V compatible, even on 3.3V devices, but you'd have to check.
If the pullup resistors go to 3.3V it doesn't quite get to the minimum spec for HIGH logic on the ADS1115 @ 5V, but the odds are it would work (but not something you'd do for production).
If you connect the pullup resistors to 5V, and the device isn't 5V compatible, the protection diodes would limit it to 4V, which would be enough to guarantee the ADS1115 to work - not a great piece of design but effective.

I don't know anything about Wemos D1, nor the ESP-8266, but I recall reading somewhere (perhaps on this forum) that it's A/D wasn't great.
I have managed to get a better reading using this equation with ADS1115 differential input method. Now I need to find a way to calculate the current from the reading. Also I believe the reading will be better if I can take a more samples. For now, I have managed take maximum of 105 samples in the code, and more than that, it is producing an error. I think the ADS1115 needs to be set up to it's maximum speed.

Last edited:

#### Ian0

Joined Aug 7, 2020
8,406
I have managed to get a better reading using this equation with ADS1115 differential input method. Now I need to find a way to calculate the current from the reading. Also I believe the reading will be better if I can take a more samples. For now, I have managed take maximum of 105 samples in the code, and more than that, it is producing an error. I think the ADS1115 needs to be set up to it's maximum speed.
I use 1600 samples per second. That gives me 16 samples in each half-cycle of 50Hz mains, and it can read the mains voltage accurate to 0.1V using a 12-bit A/D.
Are you using continuous conversion mode, and the alert/ready pin to determine when to read the new data?