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 //