There are a LOT of articles and codes flying in the internet world, but sadly they are too much bookish. Here, after some headbanging, I am sharing ACS712 current sensor practical formula that worked well for me.

When working with Arduino Uno in real world, you would have to realize that the supply voltages will fluctuate, especially when Arduino Uno is powered by computer’s USB port. One has to decouple/filter the supply voltage and take into consideration the voltages in calculations.

The ideal codes readily available on the Internet assumes a perfect 5 volt supply, which is not the case. Since this sensor is ratio metric, wrongly assumed  supply voltage will give wrong result. Therefore, you may see drift in final output readings.

I had made this code to display result via serial read, and to use internal voltage measurement of Arduino, to calculate the result. Credit to voltmeter goes to google search for internal Arduino Uno (atmega328) voltmeter LINK . Thank you author for sensitivity formula LINK.

Enjoy

ACS712 Arduino Uno Code

// Globals
float vcc = 0;

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

//**************************************************//
void loop()
{
vcc = readVcc() / 1000.0;
Serial.print(“Vcc: “);
Serial.print(vcc);

long average = 0;
for (int i = 0; i < 100; i++) {
average = average + analogRead(A0);
delay(1);
}
average = average / 100;

float sensorValue = average * (5.0 / 1023.0);
Serial.print(” sense: “);
Serial.print(sensorValue, 3);

float acoffset = vcc / 2.0;
Serial.print(” offst: “);
Serial.print(acoffset, 3);

float sensitivity = 0.185 * (vcc / 5.0);
Serial.print(” sensi: “);
Serial.print(sensitivity, 4);

float amps = (sensorValue – acoffset) / sensitivity;
Serial.print(” Amperes: “);
Serial.print (amps);
Serial.println(“…”);
delay(1000);
}

//**************************************************//
// Voltage reading function at Arduinos end
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif

delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA, ADSC)); // measuring

uint8_t low  = ADCL; // must read ADCL first – it then locks ADCH
uint8_t high = ADCH; // unlocks both

long result = (high << 8) | low;

result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}
//**************************************************//
// END //