How to calibrate ACS712 properly

Hi,
I have been struggling with a 30A ACS712 hall current sensor these days.
I tried to calibrate it using the standard parameters (2,5V middle and 66mV/A sensivity), but on the starting range (between 0A and 1A) I get sometimes a value with 100% error.

My testing circuit is a 12V power supply in series with an ammeter in series with the ACS712 and on the end different resistors. The output voltage of ACS712 is read by a standalone Atmega328p (internal OSC 8Mhz), supplied from a LM7805 that is being fed from the 12V power supply.

I tried doing some statistics with excel to get the exact voltage offset and sensivity, but it fluctuates A LOT!
So I tried to put a "calibrating the offset" at the setup of the program, but after some minutes it goes crazy and starts to get more and more error with no load.

Does anybody know how to calibrate this sensor properly?
Thank you

Note that a bidirectional 30Amp ACS712 has a unidirectional resolution of about 400 A/D values.
That's a granularity of 30/400= 0.075A = 75mA.
So readout could fluctuate by that much, or even twice that much.

Might want to program multiple analogReads with averaging and printing to one decimal place.
If you want help with that, then post your code (read the howto sticky first).
A picture of the setup also might help.
Leo..

Untested...

unsigned int total; // holds <= 64 analogReads
byte numReadings = 64;
float offset = 511.5; // calibrate zero current
float span = 0.07315; // calibrate max current | ~0.07315 is for 30A sensor
float current; // holds final current

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

void loop() {
  total = 0; // reset
  for (int i = 0; i < numReadings; i++) total += analogRead(A0);
  current = (total / numReadings - offset) * span;

  Serial.print("Current is  ");
  Serial.print(current);
  //Serial.print(current, 1); // one decimal place
  Serial.println("  Amp");
  delay(500); // human readable
}

Thank you Wawa, today I tried to continue the calibration of the ACS712 but I had a shortcircuit on the breadboard and fried my atmega328p.

Might want to program multiple analogReads with averaging and printing to one decimal place.

That is what I do on my program, I take the average of 10000 analogReads of the output voltage of the ACS712, and after that I calculate the current using the offset (2.5V) and the sensivity (0.066mV/A).

Note that a bidirectional 30Amp ACS712 has a unidirectional resolution of about 400 A/D values.
That's a granularity of 30/400= 0.075A = 75mA.

Here I don't get it, where did you got the 400 readings for each 30A (positive and negative)?
What I think and observe is that this sensor does not have a discrete jump of 75mA steps, but it has a resolution that is small in comparison with the error, or at least that is what I can see with currents between 0 and 1A.

Tomorrow I will be doing some tests again with the new atmega328p

lfreddi:
Here I don't get it, where did you got the 400 readings for each 30A (positive and negative)?

Output range of the sensor is 0.5volt to 4.5volt on a 5volt supply (actually 10-90% of VCC).
That's a span of 4volt for 60Amp (-30Amp to +30Amp).
4volt span is 4/5 of Arduino's A/D range of 1024 = ~820 A/D values for 60Amp = ~410 A/D values for 30Amp.

Or this way:
5volt/1024 = ~4.88mV per A/D value (step).
66mV per Amp, so 66/4.88 = 13.5 A/D values per Amp.
Leo..

1 Like

Or this way:
5volt/1024 = ~4.88mV per A/D value (step).
66mV per Amp, so 66/4.88 = 13.5 A/D values per Amp.
Leo..

Thank you for this explanation!
Today I will try to calibrate the ACS712 again

Okey, so here I mounted my "#1 test circuit" (you can see it on the attachment).
I took a 10 minute measure from the output voltage of ACS712 to define the output voltage offset averaging all the results.

In my code every measure is made by taking 5.000 analogReads of ADC2 and averaging them.
Then I made an excel sheet with all the data and took an average of all the readings, as you can see it is almost 2,498V.

The problem here is that the output voltage fluctuates a lot, if you see the "Offset_ACS712" image, you can see that if you take an average of 2,498, then you may get a "ghost reading" of 5 steps (on the right end of the plot). These 5 steps represent an error of:

( 5 steps * (5V/1024) ) / (0.066 mV/A) = 0,37A = Max_error

This is huge!

How can I try to minimize this error?

Is the ACS far enough away from magnetic influences (transformers).
Is this 12volt supply regulated/clean.
How far is the 1000uF cap and the 100uF cap away from the LM7805 (should be less than 1").
Why didn't you use a 100n ceramic cap on the 5volt pin of the MCU (required).
Why did you connect the Aref pin to 5volt. Shouldn't be AFAIK.
Show us a picture of the layout.

A ratiometric ACS712 does NOT output 2.5volt, but half of it's supply voltage without current.
Therefore you should not measure voltage, but display A/D value.
The code I posted uses 64 readings to average. More than enough.
Leo..

Is the ACS far enough away from magnetic influences (transformers).

Yes, there isn't any external magnetic field around the breadboard

Is this 12volt supply regulated/clean.

It is a regulated power supply, an UTP-1303 from UNI-T. During the test I took readings of the supply voltage too, and it didn't change sensibly.

How far is the 1000uF cap and the 100uF cap away from the LM7805 (should be less than 1").

The capacitors were more than 1" away from the LM7805

Why didn't you use a 100n ceramic cap on the 5volt pin of the MCU (required).

I didn't draw it, but there was a 10nF cap between 5V and GND, far away from the LM7805

Why did you connect the Aref pin to 5volt. Shouldn't be AFAIK.

I thought that since the ACS712 gets it's reference from the 5V supply, it was a good idea to connect to 5V the AREF pin

Show us a picture of the layout.

Attached. There are other things on the board too, but they are not working in this circuit, the coil isn't energized.
Tomorrow i will take away everything from the board and follow your recommendations to do this test again and check the results.

I will average 5000 analogReads again, displaying the RAW values (not voltage), with the 1000uF and (100uf + 100nF) caps close to the LM7805, in a clean breadboard.

lfreddi:
I thought that since the ACS712 gets it's reference from the 5V supply, it was a good idea to connect to 5V the AREF pin

It's internally connected AFAIK (default Aref mode), so no need to also do that externally.

Just use the code I gave you, and see how much zero current jumps.

Then adjust the that 511.5 value until current is as close to zero as you can get (re-upload every time).
Can pull in another decimal place, like 511.52
Leo..

Hall effect current sensors are inherently very noisy, usually you would chose a suitable filter capacitor
value to limit the bandwidth to only what you want as this reduces noise. Noise power is proportional
to bandwidth and these sensors are 80kHz bandwidth - if you only need 10Hz bandwidth clearly
there is a huge amount of noise you can lose this way.

Hall effect current sensors are inherently very noisy, usually you would chose a suitable filter capacitor
value to limit the bandwidth to only what you want as this reduces noise. Noise power is proportional
to bandwidth and these sensors are 80kHz bandwidth - if you only need 10Hz bandwidth clearly
there is a huge amount of noise you can lose this way.

If today my test fails again and I get a lot of noise, I will try to desolder the 1nF filter capacitor that comes in the breakout board and solder a 100nF capacitor as filter capacitor, that should reduce the noise (in theory) by 2/3 of total noise, reducing the bandwith.

Well, here I have done the coorections in the circuit, guided by Wawa.
I have mounted the "Test circuit 2" indicated in the attachments. There is a schematic and a photo.
I followed the procedure indicated by Wawa and I took 10 minutes of readings and averaged them to get my offset current error. Then I corrected the RAW offset current to get finally the value of 511.3525 offset.

This is the subrutine to make the readings:

float get_corriente(int n_muestras) {
  float value = 0.0000;
  float raw = 0.0000;
  for(int i=0; i<n_muestras; i++) {
    raw = raw + analogRead(Ipanel);    
                                  }
  raw = raw / n_muestras;
  raw = raw - 511.3525;
  value = raw * 0.073242;  // (60A/((4/5)*1024) = 0.073242 A/RAW)
  return(value);
}

In my code:
n_muestras = 5000
Ipanel = ADC2

Then, I tested the circuit following this procedure:
I put a multimeter (UT132C) in ammeter 10A mode, red wire to 12V, black wire to IN+ of ACS712, then IN- of ACS712 to a 10 ohm resistor, and the other terminal of the resistor to GND.
I got these readings:
Multimeter: 1,04 A
Circuit: 0,1013 A

I thought it would compensate the error by multiplaying with a factor (in this case multiply by 10.266), but it didn't work. It is not a scale factor problem. Any ideas?

Test circuit 2.jpg

Just tested my code on an Uno, and I get 37.42Amp and -37.42Amp when I connect A0 to +5volt or ground.
As expected for a bidirectional 30A sensor.
Don't have an ACS available, and can't test your incomplete code.
Leo..

I'm not on the pc I do programming, but the full code should be something like this:

#define Ipanel 16   // (ADC2 pin)

float current = 0.00000;

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

void loop() {
current = get_corriente(5000);
Serial.print("Current value: ");
Serial.print(current);
Serial.println(" A");
delay(500);
}


float get_corriente(int n_muestras) {
  float value = 0.0000;
  float raw = 0.0000;
  for(int i=0; i<n_muestras; i++) {
    raw = raw + analogRead(Ipanel);    
                                  }
  raw = raw / n_muestras;
  raw = raw - 511.3525;
  value = raw * 0.073242;  // (60A/((4/5)*1024) = 0.073242 A/RAW)
  return(value);
}

I'm starting to think that maybe this ACS712 has a malfunction, I will buy another one and try again on the following days

Seems you're trying to squeeze more out of a hall-based ACS sensor than possible.
Most seems to have a 1-2% total error.

If this is for 12volt DC only, then you might want to try an INA219 or INA226,
with external shunt for the 30A range you seem to need.
Leo..

GitHub - asmshamim/ACS712-Current-Sensor-Library: Calibration Error Solved During AC Current Flow throw the Sensor AC Current calibration error solved