ACS712 DC amplifier

I am trying to measure DC current using a ACS712-05, but the problem is that the currents I am trying to measure are small (50-100 mA), and whatever change that causes in the output of the ACS712 is too small for the Arduino’s 10-bit ADC to pick up.

As you know, the ACS712’s zero-amp reading is Vcc/2 (around 2.5V), and it goes down to 0.5V for negative currents and up to 4.5V for positive currents. In my application, I#ll always be reading positive DC currents, so I don’t need to read anything below 2.5V, so if I can bring the output of the ACS712 for positive currents from 0 to 5V, I’ll have a much better resolution, of up to 400mV/A.

That is how I came up with the circuit below, which I need your help validating.

Basically, what I want it to do is:

  • pass the output of the ACS712 through a RC filter to improve signal-to-noise ration (page 13 of the datasheet)

  • then go through a Unity Gain Differential Amplifier [U1.1] (Vout = V2 - V1), where V2 is the output of the ACS712 after the RC filter and V1 is Vcc/2 (taken from a voltage divider)

  • this way, I can take the positive output of the ACS712 and make its zero-amp reference a zero-volt output.

  • now take the output of [U1.1] and amplify it using a non-inverting amplifier [U1.2] with a gain of 2.42 (using only commercial value resistors).

  • The output of [U1.2] now will be in the range of 0 ~ 4.84V, which is almost 400mV/A resolution.

I chose the MAX412 because it is dual, rail-to-rail, low-noise, , and I have one in my drawer.

Is the circuit below correct for what I want to achieve?


(Note: same version as the previous one, but with a few cosmetic improvements. Click to enlarge.)

Thanks in advance.

I'm sorry, but I don't like it. The ACS712 are very noisy and very sensitive for magnetic influences. As they are, they are already inaccurate. You want to amplify that inaccuracy ?
You can keep it near a computer or a computer screen, or near mains wires, or you move the wire with the current that you want to measure, and you will see that the value will change.

In my opinion the ACS712 can be used when averaging the value a lot in the sketch. And even then the result could be 10% inaccurate.

The number of bits can be increased with a trick. Apply 2.5V to AREF and only 0...2.5V is measured. A resistor is all that is needed to apply 2.5V to AREF since AREF has a resistor inside to GND (about 32k).
Are you using a normal Arduino board ? like the Arduino Uno / Nano / Mini / Pro Mini / Leonardo / Micro.

There are very good chips for shunt resistors.

Use a 10k resistor between the 3.3volt pin and the Aref pin, and set Aref to external.

Aref is now 32/(32+10)*3.3= ~2.51volt.
Uni-directional current with almost twice the resolution.
Leo

Thank you Koepel and Wawa.

Thee ACS712 was chosen because it is pretty easy to find them here in Brazil for cheap. I didn't know its output was so dirty until I looked at it on the oscilloscope. It is really a mess, but for now, it will have to make do. I'll be orderinga INA219 from DealEXtreme today, but that won't be here until late January, so...

The Arduino I am using is a homemade clone, and this is it:

3.3V is attained through a MAX604, which gives a pretty clean output, even without the bypass caps. A newer version of this board has all the bypass caps, but I gifted it to a friend.

I'll try your ideas, but do you think it would be wise to leave the RC filter on after the output of the ACS712?

I'll reverse the current going into the ACS712 so it will appear as negative current, so it reads from 2.5-0V. If I set the analog pin it's connected to to INPUT_PULLUP, I'll get readings from 0-2.5, instead of 2.5-0, which will easen my math. Is that logic correct?

I'll set the analogReference to external just when reading that specific pin, wait a few milliseconds for it to stabilize, do a few dummy readings, then take about 100 readings and average them. After that I'll set the analogReference back to default.

Regarding the ACS712 board being sensitive to external influences, what if I protect it with PVC wrapper, some tin foil and then more PVC wrapper?

It will protect the little breakout board from ETs, NSA and the CIA, but will it make less sensitive to EMI ?

Use an air gapped ferrite toroid to increase the signal to noise.

I haven't found a supplier for split toroids, so you'll probably need to make one using a Dremel and diamond wheel.

For magnetic shielding put everything inside a steel biscuit tin or petty cash box. PVC isn't going to help.

not sure if this is any better or not, but sparkfun sells the ACS712 with op amp so it can measure low current. this is the schematic

The MAX604 really needs those capacitors. Can you add them ?

AlxDroidDev:
I’ll set the analogReference to external just when reading that specific pin, wait a few milliseconds for it to stabilize, do a few dummy readings, then take about 100 readings and average them. After that I’ll set the analogReference back to default.

Read the warnings about minimum load resistance on the Aref page.
Why not set it to external in setup, and leave it.
If you use a voltage divider for something else, adjust the resistors.
Stability of the 3.3volt supply is probably a lot better than the 5volt supply.

Leo…

Koepel:
The MAX604 really needs those capacitors. Can you add them ?

I can just use a UNO or one of the other Arduinos I have. I am prototyping this idea to see if the ACS712 is suitable for a larger project I have in mind. I am starting to believe it isn't.

News update: I gave up on using the ACS712. I actually was so pi*d off with my ACS-05 board that I fed it with 24V (on the supply side, not on the measurement side!!!) just to see it burn.

It is all you guys said it was: horrible, very susceptible to noise and interference, has a very dirty output and is not sensitive at all to small currents.

Actually, the ACS712-05 sucks so much I kinda feel sorry for people using it.

I moved to the INA219 and I gotta tell you: this little device is amazing. Fully programmable through I2C, and I can measure currents as low as 1mA, just like I wanted.

I got hold of a INA219B (the more sensitive version) IC on SOT-23, and I etched my own breakout board. I hand-soldered the INA218B to the board. For shunt resistor, I used a 3W 0R15 resistor.

I based my library off the Adafruit INA219 library. I re-did all the math to calibrate my board (considering I was using a different shunt resistor) and I was able to have the exact same measurement from my INA219 board than from my Fluke 17B+.

The best thing that ever happened was the ACS712 being so crappy: it forced me to look for an alternative and I found the INA219, which is excellent.

Later I'll post pictures of my INA219 breakout board and my sloppy SOT-23 hand-soldering job.

Hi AlxDroidDev!

Is it also possible to detect the current direction with the INA219?
I want to use it for monitoring charge/discharge of a battery.
If yes, is the Adafruit Library prepared for +/- sensing?

Thanks!
Spiff

rfSpiff:
Is it also possible to detect the current direction with the INA219?
I want to use it for monitoring charge/discharge of a battery.
If yes, is the Adafruit Library prepared for +/- sensing?

Yes, it can detect current in the opposite direction, and when that happens, the voltage and current registers will show negative values. According to the datasheet, pages 20-23, negative values are stored in 2's complement format.

The Adafruit library is NOT prepared for that. It will not try to decode a 2's complement number. You can adapt the library to do so, implementing the steps outlined in pages 20-21, item 8.6.3.1. The same goes for negative current.

Thanks AlxDroidDev, I understand and will try doing that.
Just placed the order of a INA219 board. I also had the expierences you had with the ACS712. :slight_smile:

Spiff.

Hi.

Just wanted to let you know that the Adafruit library actually IS prepared for current direction.
The INA219 is great, I am so happy that I replaced the ACS712 with it.

Thanks
Spiff