[SOLVED] ACS712 unstable and wild zero current reading (DC)

Hello everyone!

I'm trying to measure DC current with the ACS712 - 20A and it seems to work ok except for the zero current measurement. I need some help from someone who has experience with those sensors.
The code seems to be good as it does work and I do get the correct reading when the current is flowing. If the current is very small or actual zero I get wild fluctuations. I'm not talking regular noise which is to be expected, rather I'm talking about wild fluctuations.
With the current flowing I get 1A for 1A and 10A for 10A. That is good. When the load is disconnected the reading will jump all over the place by as much as 9A!! So, I might see readings like 0.1A, then -2.0A, then 0.0A, then 6.5A, then -9.1A. It's just wild and it really screws up the operation of my circuit triggering overcurrent or undercurrent alarms while the load and supply are actually disconnected! What's up it that? Any ideas?
When I disconnect the sensor from Arduino and just let the analog pin float I get similar wild fluctuations. I tried measuring the voltage on the output pin of the sensor and it is steady at 2.542V with 5.01V supply. Measured with good Fluke multimeter.
It seems to me as if there is not enough load on the analog input pin for the Arduino and I get random noise but then why does it work just fine when there is current flowing? I don't get it.
I guess I should mention that I have tried three different Arduino boards (2x Uno and 1x Mega) and two separate ACS712 sensors and I always get the same results.

The idea to measure the zero current was to establish the base sensor voltage to get accurate starting point. Then a small current is applied to the load (about 100mA) for 500ms to check if the load is still present and connected. At this point I absolutely cannot set the zero point and I cannot check the presence of the load. With no current and 100mA my readings are just crazy.

An example:
The code starts by checking the input voltage on analog in to establish sensor zero point. Supply and load are disconnected. The reading I get is... pretty much anything from -10A to 10A. Let's say that it gets 3.0A as an example here. Then about 100mA is applied for 500ms and the reading goes from -5A to 4A. As it is averaged as a result I might get the final result as -1A and that's it. It's a lot less than the expected 100mA and the circuit goes into error mode saying that the load is disconnected.
If the check current is set to about 1A it might work better but the initial zero point reading is all over the place so as a result the circuit will go into shutdown mode anyway.

I appreciate all your help.

Thanks!

2 capacitors installed ?

Where is your sketch ? I think the problem is in your sketch.

Yes, the capacitors are installed. I got those little boards with ACS712, two caps and terminals. Both are from the same eBay seller but like I said, it seems more like a problem with the Arduino analog pin than the ACS itself.

I don't have the code with me at the moment, it's on my other computer. I'll try posting it tomorrow.
My last version of the code doesn't even do the base reading and I'm using a fixed zero value. Still, small and zero currents result in wild readings.

Thanks

When I disconnect the sensor from Arduino and just let the analog pin float I get similar wild fluctuations.

Sounds like the sensor is not properly grounded to the Arduino. Post a wiring diagram (not Fritzing, please).

Is schematic really needed for this? It's a very simple circuit with Arduino UNO and the ACS712 - 20A on a separate board with it's own capacitors. Both are connected to a 9V power supply (tried a different supply and got the same result). +5V goes from the power line on the Arduino board as does the GND and the signal wire (this one goes to one of the analog pins). The 9V coming directly from the power supply goes through a MOSFET, then the sensor board and then goes to a light bulb. This is just a test setup. In the final version the circuit is suppose to drive a large 12V fan. That's it.
I can draw a schematic but with such a simple circuit I don't have one. It's all just done "one the fly".

BTW, I had to ask Google about what Fritzing is :wink: I use Eagle for my schematics and board layouts. I think I should add that I'm fairly experienced with electronics but not with coding.

This is the code that I'm using to get the current reading:

int analogCurrent(int pin)

{

float current;

for(int i = 0; i < 50; i++)

{

current = current + (((0.0048875855327468 * analogRead(pin) - 2.5) / 0.1)-0.12);

}

current = current / 50;
return current;

}

As you can see I'm trying to average out the current value by doing 50 measurements. That does help a little but it's still not enough because of the large spread that I'm getting. With just one measurement the results were totally unusable.
Keep in mind that my current readings are correct. I checked them with my Fluke meter and everything checks out all the way to over 12 amps. The problem is only when the current is very low - about 100mA or less and it's just crazy when there is no current flowing. The closer to 0 the worst the problem is.
It doesn't make sense to me because if it was caused by noise or improper grounding then I should see it all the time and not just at 0. It would make sense if 0 current was equal to 0V on the output but since 0A equals about 2.5V on the output it doesn't seem like noise or interference to me.
Is my code wrong?

Thank you for your help guys!

Your math return negative numbers. Is this correct?
try: read once -> return a float

A test sketch:

// Arduino Uno clone
// Arduino IDE 1.6.0
// Test for ACS712 5A

void setup() 
{
  Serial.begin(9600);
  Serial.println("Started");
}

void loop() 
{
  Serial.println( analogRead(A0));
  delay(200);
}

Without any current, it varies a lot. This is near my computer.

504
497
504
514
511
510
515
512
503
499
512
512
509
508
509
506
514

Some distance away from my computer it is not better:

503
506
506
508
509
509
508
506
506
517
506
510
515

Shortcutting the current pins makes no change.
Keeping the current pins open and connecting one to a transformer makes no change.

I think that is just how inaccurate they are.

Using average:

// Arduino Uno clone
// Arduino IDE 1.6.0
// Test for ACS712 5A

void setup() 
{
  Serial.begin(9600);
  Serial.println("Started");
}

void loop() 
{
  unsigned long total = 0;
  for( int i=0; i<100; i++)    
  {
    total += analogRead(A0);
//    delayMicroseconds( 200);  // stretching the sampling period did not help.
  }
  // print with decimal digits, for fun
  Serial.println( (float) total / 100.0);
  delay(200);
}

That results into something more stable, but it still is not very stable.

507.39
507.76
507.34
508.48
507.54
507.44
508.07
507.42
507.70
507.80
507.48
507.23
508.52
507.11
508.31

Then I tried your snippet (inclusive the bad float to int conversion for the return value).

// Arduino Uno clone
// Arduino IDE 1.6.0
// Test for ACS712 5A

void setup() 
{
  Serial.begin(9600);
  Serial.println("Started");
}

void loop() 
{
  Serial.println( analogCurrent(A0));
  delay(200);
}

int analogCurrent(int pin)
{
  float current;
  for(int i = 0; i < 50; i++)
  {
    current = current + (((0.0048875855327468 * analogRead(pin) - 2.5) / 0.1)-0.12);
  }
  current = current / 50;
  return current;
}

And I get only zeros

0
0
0
0
0
0
0
0
0
0
0
0
0
0

Perhaps you should get another ACS712 module and test that.
Can you make a photo of your wiring ? and a schematic would be very helpful because I don't know what you mean with: power line.
Can you do a few of these tests, and confirm that you have the same results as me ?

knut,
I don't understand why my calculation would return negative values. Actually it doesn't.
That long decimal value calculates amp value from analog read value (0 to 1023), then -2.5 is to get a zero point (ACS712 puts out 2.5V when no current is flowing), 0.1 is the value in volts for each Amp flowing though (20 amp version of ACS712). The final value is the offset for my particular chip that is always reading 120mA too high and without it I would get 2.12A for actual 2Amps, and 3.12A for actual 3Amps and so on.

I don't understand what you mean by "try: read once -> return a float". Like I said, I'm a novice when it comes to Arduino. Can you explain?

Peter,
Your averaged result would be perfectly fine for me. The problem is that I'm getting junk. I run it a bit more today and now I got some really interesting results. I didn't make any changes (software or hardware), yet it was different. For example, I got a reading of -129 amps that was steady for a few seconds! Then it went to positive 104A for another few seconds. It seemed to be "sticking" at those extreme values. Weird... BTW, I wasn't trying to measure the charge current on a Tesla Model S, there was nothing connected to the sensor board - no current flowing and no magnetic field present. After connecting a load (about 1.2A) the reading was pretty much steady and accurate.
Anyway, the bad float to int conversion for the return value is my mistake. What I did before was this: the reading was taken 50 times and then divided by 5. I just had this idea for using a decimal value without actually using any decimal values. It did work, but I was getting 10 instead of 1.0. I tried simplifying it for you guys and actually made a mistake. Sorry about that.

Like I said in my previous post, I have two ACS712 boards and they both behave in the same way. I could try getting another one and maybe from a different seller/batch but I thought I'll ask you guys if this is a known issue/error in my code/error in my thinking.

I can't take a picture of my board at this time but it looks pretty much exactly as your picture. The only difference is that I use single piece wires and my ACS712 board doesn't have that bright LED. Oh, and my Arduino board is blue ;).
As for the "power line" - When I look at my Arduino Uno board there is a row of connectors with "POWER" printed next to them. One of those pins is marked 5V. This is what I was referring to as +5V power line. I wasn't thinking about one of those 480kV power lines :wink:

Here's a schematic of my circuit. This is just to show what I have. I hope this is enough.

As far as I can tell, what you did is okay. The cause is still a mystery.

Can you get normal numbers if nothing is connected to the current pins ? As in my photo.
It could be a bad breadboard. I would like to see a photo of your circuit.
Try new wires, and other breadboard or without breadboard.
Perhaps you make the same assumption every time that something on the breadboard is connected or not connected.

If both ACS712 modules are from the same seller, they both can be from a bad factory batch. It happens.
The analog section of the Arduino can be damaged.

To solve this the fastest way: Use a new Arduino Uno, new wires, new ACS712 module from a different seller and connect only the ACS712. If that works, you can add the mosfet and the load.

Peter,

It is a complete mystery to me as well because I have used three separate Arduino boards - two Uno and one Mega.
I do not use a breadboard at this time. I can take a picture tomorrow but it's going to look just like the one in your post. No breadboard, just the Arduino board and the ACS712 board. Yes, I did suspect the wires as well and tried using different ones to no avail. BTW, during my troubleshooting I have removed everything from the circuit and ended up with just the Arduino and the ACS, nothing else at this time. The other components like the LED, the mosfet and others are just an example of what I'm trying to use it for.

Yes, I do get correct numbers. Once in a while the reading will stay somewhere around zero (sometimes within plus/minus 30mA) but not for long. No more than 10 - 20 seconds and then the crazy dance comes back. The readouts I've seen today were totally crazy... I mean, how could it get to some -120 odd Amps? That's not even possible, is it? I would suspect the ACS but the values I've seen are not possible with anything this chip is capable of. Heck, that is not possible for the analog IN on the ATmega chip! 100A would mean that there was -10V on the analog IN pin and the A/D converter somehow went into negative values. I've seen similar values a few days ago and that's why I've borrowed some Arduino boards from a friend just to see the same thing happen again today.
Either I'm doing something wrong or my PC is possessed :wink: Or both.

I think I want to start over with my code as I have pretty much tried everything hardware related except for replacing the ACS712. The two I have seem to act exactly the same.
Can you guys post a simple code for reading the current? Something that works. Something that you might recommend for my application. I would appreciate that.

Thank you for your help guys!

Use one the test sketches in my Reply #7.
Use the first test sketch. I think the raw ADC value is the most simple at the moment.

The USB power could also have some influence. You could try a power supply to the DC power jack of 7.5 to 12V.

Hey everyone,
I think I have found what the main problem was and it seems to be a bit better now. I don't get the wild swings as I used to get before. The culprit here was the number I was using in converting to actual amp value. This number: 0.0048875855327468. This number was just too long and a buddy of mine told me that if there is more than six digits after the decimal point it will start acting up. So, the correct number for the conversion is now 0.004887. It's less accurate but I don't get the large numbers anymore and it seems to be working much better. This is the best accuracy that Arduino can provide.
The problem is that it is still not perfect.
The zero point is still drifting. Sometimes it will drift down by 5A (after conversion) without any current flowing. I'll have to check that with my multimeter to see if this problem is caused by the ACS or Arduino itself. OR, there is a huge magnetic field around my desk that's messing up the sensor... Maybe there's a wormhole about to open up :wink:
I'll post an update soon.

Thanks!

This number was just too long and a buddy of mine told me that if there is more than six digits after the decimal point it will start acting up.

If so, that would suggest a compiler error. The compiler should just ignore extra digits, or round off the result appropriately. So, I conducted a test to see if that might be the case, and find no evidence for such a problem.

This is the program that I ran (on a Pro Mini):

void setup() {
  Serial.begin(115200);
  float x = 0.0048875855327468;
  float y = 0.0048876;  //rounded slightly
  Serial.println("x");
  Serial.println(x,3);
  Serial.println(x,6);
  Serial.println(x,8);
  Serial.println("y");
  Serial.println(y,3);
  Serial.println(y,6);
  Serial.println(y,8);
  Serial.print("y-x = ");
  Serial.println(y-x,8);
}

void loop(){}

And this was the result:

X
0.005
0.004888
0.00488759
y
0.005
0.004888
0.00488760
y-x = 0.00000001
int???? analogCurrent(int pin) // ..or float ??
{
  float current;
  for(int i = 0; i < 50; i++)
  {
    current = current + (((0.0048875855327468 * analogRead(pin) - 2.5) / 0.1)-0.12);
  }
  current = current / 50;
  return current;
}

jremington, I don't know if my compiler is acting up but that was the cause for the problem as this was the only thing that I've changed in my code and it fixed the wild readings. I'm using the latest version of Arduino IDE. Just to confirm I've used the long number again and again got the strange large numbers like -120 A. With the shorter number everything seems to be fine.
I'll try your code to see if I get the same result but either way, it works now and I'm happy.

knut_ny, yeah, I've changed the int to float. Forgot to post it in my last reply. Thanks.

As for the drifting current reading I still haven't figured out what is going on exactly but it seems to be a problem with my ACS712 boards. I connected a Fluke meter to the output pin on this little board and the readings are very unstable. Without anything connected to the sensor the zero voltage drifts slowly between about 2.00 V to about 2.541 V. It seems that the longer it is on the lower the output voltage is.
Input voltage comes from a lab power supply and is stable at 5.001 V
I've ordered some new sensor boards and I'll run some tests as soon as they arrive. I'll post the results.

Thanks guys!

After almost a month I have finally received my new ACS712 and run some tests. Here are the results: new chips seem a lot more stable! Apparently the two units I had were faulty and they could not hold a constant voltage even when there was no current flowing. There is no slow drift with the new chips. The readings are still not rock solid but from what I see they are well within the limits.

So, if anyone gets some strange readings you should connect a high quality meter to the output pin of the ACS712. If you see the voltage drifting or jumping all over the place with no current flowing through the measuring pins you should consider getting a new sensor chip from a different production batch / different supplier / different production date.

Thanks to everyone who offered their help. I can finally get some reliable readings!

Thanks for letting us know. You should add [solved] to the subject title.

I would like to give helpful expert tips for anyone that is sampling and averaging this sensor

Don't do complicated calculations in the averaging loop.
Use sensible constants that are greater than 1.0
Spread out your calculations so they are readable and understandable.
(The processor doesn't do things quicker if they are written on one line)

Example:

double sum = 0.0;
float current = 0.0;

// sample over approximately 50 milliseconds

sum = 0.0;

for (int i = 0; i < 50; i++)

{
sum += analogRead(CURRENT);
delay(1);

}

// now we can find the average and do calculations
//

sum = sum /= 50.0;

// subtract the zero
//
sum = sum - 512.0;

// convert to volts
//
sum = sum * (5.0 / 1024.0);

// convert voltage reading to current
//
current = sum * CONSTANT;

penguinman8:
I would like to give helpful expert tips...

Then you would know that this line

penguinman8:
sum = sum * (5.0 / 1024.0);

could be nonsense.

A ratiometric ACS712, used with a ratiometric A/D (most Arduinos on default Aref), outputs a ratio of the A/D range.
"Voltage" should be nowhere near ACS712 current calculations.
Leo..