Measure a motor’s current with an ACS712 and an Arduino
Beginner
Or see every lesson.
- 465parts on the bench
- 43boards running now
- 1.00xreal time, on every board
The ACS712 is the red current sensor board in most Arduino sensor kits. The current you want to measure goes through its blue screw terminal, and a pin on the other end gives the Arduino a voltage that moves with the current. It can measure a motor, an LED strip or a battery charger, and the copper the current runs through never touches the Arduino’s side of the chip.
The circuit above is an Uno with an ACS712 5 A board in a 6 V gear motor’s lead and a 16x2 I2C LCD. Hold the button and the motor starts: the screen shows the current now and the highest it has seen. It runs in your browser on the sketch below.
What you need
- An Arduino Uno
- An ACS712 current sensor board (5 A, 20 A or 30 A)
- A small DC gear motor and a 6 V supply
- A push button
- A 16x2 LCD with an I2C backpack
- A half-size breadboard and jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| ACS712 VCC | 5 V | It needs 4.5 to 5.5 V; it is not a 3.3 V part |
| ACS712 GND | GND | |
| ACS712 OUT | A0 | An analog reading |
| ACS712 IP+ and IP- | In the motor’s lead | Supply side on IP+, so the reading goes up |
| LCD SDA and SCL | A4 and A5 | Backpack address 0x27 |
| LCD VCC and GND | 5 V and GND |
Half the supply, plus a little per amp
With no current, the ACS712 puts out half its supply: 2.5 V on 5 V, so A0 reads about 512. Current into IP+ pushes the output up, and current the other way pulls it down. The 5 A board moves 185 millivolts for every amp, the 20 A board 100 mV and the 30 A board 66 mV. The number after the part number on the chip tells you which you have.
One step of the Uno’s ADC is 4.89 millivolts. On the 5 A board that is 26 mA a step, on the 20 A board 49 mA and on the 30 A board 74 mA. So pick the smallest board that covers your current: a 30 A board cannot see a 50 mA LED.
The output also has noise on it, about 21 mV from top to bottom on the 5 A board. That is several ADC steps, which is why every ACS712 sketch averages a batch of readings.
The sketch, step by step
The sketch uses Rob Tillaart’s ACS712 library. ACS712 ACS(A0, 5.0, 1023, 185) tells it the pin, the ADC’s 5 V and 1023 steps, and the 5 A board’s 185 mV an amp. Change 185 to 100 or 66 for the bigger boards.
At power-on nothing is flowing, so autoMidPoint() averages A0 for 40 ms and calls that zero. In the circuit above the serial monitor prints "Midpoint: 511". The true zero is 511.5 steps, so with the motor off the meter reads about 12 mA: half a step and a little noise. A real board’s zero is a few millivolts off as well, which is why you measure it rather than assume 512.
Then for a fifth of a second at a time it takes quick averages of ten readings with mA_DC(10), keeps the highest, and shows their average. Hold the button and the peak jumps to "1004": a stopped motor is just its 6 ohm winding, so on 6 V it pulls an amp for a moment. As it spins up it makes its own voltage that fights the supply, and the current falls to 150 mA, which the meter shows as 163: the same half step of offset from the midpoint.
void loop() {
float sum = 0;
int n = 0;
unsigned long began = millis();
while (millis() - began < 200) {
float mA = ACS.mA_DC(10);
if (mA > peak) peak = mA;
sum += mA;
n++;
}
float mA = sum / n;
showLine(0, "Now ", mA);
showLine(1, "Peak ", peak);
Serial.print("mA: ");
Serial.print(mA, 0);
Serial.print(" peak: ");
Serial.println(peak, 0);
}ACS712 or INA219?
The ACS712 measures the magnetic field around the current, so the current loop can be at any voltage, even mains, and it can read AC with mA_AC(). It costs almost nothing in the circuit: 1.2 milliohms. But it is coarse on a 10-bit ADC and noisy.
The INA219 measures the voltage across a 0.1 ohm resistor with its own 12-bit converter and talks I2C. It resolves a tenth of a milliamp and also gives the supply voltage, but it only works on DC up to 26 V and shares its ground with the circuit. For a battery project, pick the INA219; for a motor, a heater or anything AC, the ACS712.
Try it in the editor
Switch the board to the 30 A model in its properties and change 185 to 66 in the sketch: the running current now reads in 74 mA steps. Or add a buzzer that sounds when the current passes 800 mA, the start of a stall alarm for a robot that has hit a wall.
Common mistakes
Calling autoMidPoint() with the load already running. It takes whatever the output is at that moment as zero, so the motor’s own current then reads as nothing.
Powering it from 3.3 V. The chip needs 4.5 to 5.5 V. On a 3.3 V board, run it from 5 V and divide OUT down, or pick a 3.3 V current sensor.
Assuming exactly 2.5 V on USB power. The output is in proportion to the supply, so on a USB port’s 4.8 V the zero is 2.4 V. Reading the ADC against the same supply cancels that out.
Using the 30 A board for small currents. Its 66 mV an amp is 74 mA a step on an Uno.
Questions
How do I connect an ACS712 to an Arduino?
VCC to 5 V, GND to GND and OUT to an analog pin such as A0. The current you want to measure goes through the screw terminal, IP+ and IP-, in series with the load.
Why does my ACS712 read about 512 with no current?
That is right: its output rests at half the supply, 2.5 V on 5 V. Current one way raises it and the other way lowers it, so it can measure both directions and AC.
Why does my ACS712 reading jump around?
The sensor has about 21 mV of noise on the 5 A board, several ADC steps. Average 50 to 100 readings, for example with mA_DC(100) in the ACS712 library.
What does Mokxi not model on the ACS712?
The common board’s 1 nF filter lets through more noise than the datasheet’s 2 kHz figure Mokxi uses, so a real board jumps more. The chip’s offset, its 1.5% error, temperature drift and heating are not modeled either.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.