Motors are among the most common causes of electrical failures in industrial machinery, robotics, and hobbyist electronics. A motor that stalls, overloads, or loses a phase can draw 5–10 times its rated current within milliseconds, generating enough heat to destroy windings, scorch motor drivers, and trip circuit breakers—or worse, start fires if protection is absent. Fortunately, detecting these fault conditions is straightforward with current sensing, and the ACS712 and INA219 modules available in India make implementation accessible to any maker or engineer.
This tutorial covers the physics of motor overcurrent, explains Hall-effect and shunt-resistor current sensing methods, provides working Arduino code for the ACS712 and INA219, and shows you how to build overload and stall detection logic that responds in under 10 milliseconds.
1. Motor Current Profiles: Normal vs. Fault
Understanding what normal motor current looks like is the prerequisite for detecting abnormal conditions. A DC brush motor exhibits these characteristic current signatures:
- Startup inrush: For the first 50–200 ms, current can reach 3–8× rated current as the motor accelerates from standstill. This is normal and should not trigger fault protection.
- Running (no load): Motor draws only enough current to overcome friction and rotational losses—typically 10–30% of rated current.
- Running (full load): Rated current as specified on the nameplate, e.g. 2 A for a 12V/24W motor.
- Overload: Mechanical load exceeds rated capacity. Motor slows, back-EMF drops, current rises above rated. Duration matters—brief overloads (seconds) are often acceptable; sustained overloads destroy windings.
- Stall / locked rotor: Motor shaft is physically blocked. Back-EMF drops to zero, current jumps to 5–10× rated (limited only by winding resistance). If not detected quickly, windings overheat and burn within seconds.
BLDC (brushless DC) and stepper motors show similar patterns but require phase-current monitoring. Three-phase AC induction motors also follow the same inrush → rated → overload progression, scaled by the 230V/400V supply.
2. Current Sensing Methods
Hall-Effect Current Sensor (ACS712 type)
A conductor carrying current generates a magnetic field proportional to the current. A Hall-effect IC placed perpendicular to this field produces a voltage output proportional to field strength, and therefore to current. Key advantages: complete electrical isolation between the current path and the signal circuit, measurement of both AC and DC, no insertion loss (the bus bar through the IC has milliohm resistance).
Shunt Resistor + Instrumentation Amplifier (INA219)
A precision low-value resistor (shunt) is inserted in series with the current path. Ohm’s law: V = I × R. A differential amplifier measures the small voltage drop across the shunt. The INA219 integrates the shunt voltage measurement, gain amplification, and a 12-bit ADC with I2C output in one chip. Disadvantages: not isolated from the current path (floating ground issues in some circuits), insertion loss (shunt resistance drops voltage), limited to lower voltages than Hall-effect sensors.
Current Transformer (CT) for AC only
A toroidal transformer with the AC bus wire as the primary. Measures true RMS current in AC circuits without electrical connection. Not suitable for DC measurement. Used in energy monitors and industrial MCCBs.
3. ACS712 Hall-Effect Current Sensor
The ACS712 from Allegro Microsystems is available in three current ranges: ±5A (sensitivity 185 mV/A), ±20A (100 mV/A), and ±30A (66 mV/A). At zero current, the output is VCC/2 = 2.5V (with 5V supply). Above zero current the voltage rises; below zero it falls. This allows bidirectional current measurement.
Wiring the ACS712
- IP+ and IP− pins in series with the motor current path (load current flows through these)
- VCC → 5V, GND → GND (signal side power)
- VOUT → Arduino analog input (A0)
- FILTER pin: leave unconnected or add a 1–10 nF capacitor to GND to reduce noise
// ACS712-20A on Arduino Uno (5V ADC reference)
// Sensitivity: 100 mV/A, zero = 2.5V (512 counts)
const float SENSITIVITY_mVperA = 100.0;
const float VCC = 5000.0; // mV
const float ZERO_COUNTS = 512.0;
const float COUNTS_PER_mV = 1023.0 / VCC;
float readCurrentA() {
// Average 50 samples for noise reduction
long sum = 0;
for (int i = 0; i < 50; i++) {
sum += analogRead(A0);
delayMicroseconds(200);
}
float avgCounts = sum / 50.0;
float voltage_mV = (avgCounts / 1023.0) * VCC;
float current_A = (voltage_mV - VCC / 2.0) / SENSITIVITY_mVperA;
return current_A;
}
void setup() {
Serial.begin(115200);
}
void loop() {
float current = readCurrentA();
Serial.print("Current: ");
Serial.print(current, 3);
Serial.println(" A");
delay(100);
}
ACS712 Accuracy Considerations
The ACS712 has a total output error of ±1.5% at 25°C, rising to ±4% over the full temperature range. The Arduino’s 10-bit ADC resolves 5000 mV / 1024 = 4.9 mV per count. With 100 mV/A sensitivity, the best resolution is 4.9/100 = 0.049A ≈ 50 mA per LSB. For detecting overloads that push current 2× above rated, this resolution is more than sufficient. For detecting sub-amp variation in precise positioning, use the INA219 instead.
4. INA219 Shunt Current Sensor
The INA219 uses a precision 12-bit ADC to measure the differential voltage across a shunt resistor and calculates current with a resolution as fine as 0.8 mA. The I2C interface (address configurable to 0x40–0x4F via A0/A1 pins) allows multiple sensors on a single bus.
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219; // default address 0x40
void setup() {
Serial.begin(115200);
Wire.begin();
if (!ina219.begin()) {
Serial.println("INA219 not found!");
while (1);
}
// For 2A max: use setCalibration_16V_400mA() or custom calibration
ina219.setCalibration_32V_2A();
}
void loop() {
float busvoltage_V = ina219.getBusVoltage_V();
float current_mA = ina219.getCurrent_mA();
float power_mW = ina219.getPower_mW();
Serial.print("Bus Voltage: "); Serial.print(busvoltage_V); Serial.println(" V");
Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA");
Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW");
delay(500);
}
The CJMCU-219 INA219 breakout available at Zbotic includes the 0.1Ω shunt resistor pre-soldered, setting maximum current to ±3.2A at maximum gain. For higher currents, replace the onboard shunt with a lower value (e.g. 10 mΩ for 32A range) and update the library calibration value.
5. Overload Detection Logic
A simple threshold comparison is insufficient—it would trip on every motor startup. The correct approach is a time-delayed overload based on the thermal model of the motor winding.
Simple Threshold with Startup Inhibit
const float RATED_CURRENT_A = 2.0; // motor nameplate
const float OVERLOAD_FACTOR = 1.5; // trip at 150% rated
const unsigned long STARTUP_IGNORE_MS = 500; // ignore first 500ms
const unsigned long OVERLOAD_TRIP_MS = 3000; // trip after 3s continuous overload
float overloadThreshold = RATED_CURRENT_A * OVERLOAD_FACTOR; // 3.0A
unsigned long motorStartTime = 0;
unsigned long overloadStartTime = 0;
bool motorRunning = false;
bool faultTripped = false;
void startMotor() {
motorStartTime = millis();
motorRunning = true;
overloadStartTime = 0;
// ... enable motor driver
}
void checkOverload(float current_A) {
if (faultTripped) return;
if (!motorRunning) return;
// Ignore startup inrush
if (millis() - motorStartTime < STARTUP_IGNORE_MS) return;
if (current_A > overloadThreshold) {
if (overloadStartTime == 0) {
overloadStartTime = millis(); // start timing overload
} else if (millis() - overloadStartTime >= OVERLOAD_TRIP_MS) {
// Sustained overload — trip!
faultTripped = true;
motorRunning = false;
// ... disable motor driver
Serial.println("FAULT: Overload tripped!");
}
} else {
overloadStartTime = 0; // reset timer if current drops
}
}
Thermal Model (I²t Protection)
A more sophisticated approach accumulates heat energy (proportional to I²) and trips when the accumulated value exceeds a threshold—mimicking a bimetallic relay. The winding cools when current drops below rated:
float thermalAccumulator = 0.0;
const float THERMAL_TRIP_LEVEL = 100.0;
const float COOLING_RATE = 0.5; // per second
void updateThermalModel(float current_A, float dt_s) {
float excess = (current_A / RATED_CURRENT_A) - 1.0;
if (excess > 0) {
thermalAccumulator += excess * excess * dt_s; // heat in
} else {
thermalAccumulator -= COOLING_RATE * dt_s; // cool down
if (thermalAccumulator < 0) thermalAccumulator = 0;
}
if (thermalAccumulator >= THERMAL_TRIP_LEVEL) {
// trip!
}
}
6. Stall Detection Algorithm
A stall condition is characterised by: (1) current sustained well above rated (typically 5–10×), and (2) zero mechanical rotation. The most reliable detection combines current sensing with a rotation signal—a Hall-effect encoder or an optical slot sensor on the motor shaft.
Current-Only Stall Detection
If you lack a rotation sensor, stall can be inferred from sustained very-high current that exceeds the normal overload range:
const float STALL_CURRENT_A = RATED_CURRENT_A * 5.0; // stall = 5× rated
const unsigned long STALL_TRIP_MS = 200; // trip stall in 200ms (much faster than overload)
unsigned long stallStartTime = 0;
void checkStall(float current_A) {
if (faultTripped || !motorRunning) return;
if (millis() - motorStartTime < STARTUP_IGNORE_MS) return;
if (current_A > STALL_CURRENT_A) {
if (stallStartTime == 0) stallStartTime = millis();
else if (millis() - stallStartTime >= STALL_TRIP_MS) {
faultTripped = true;
motorRunning = false;
Serial.println("FAULT: Motor stall detected!");
}
} else {
stallStartTime = 0;
}
}
Combined Current + Speed Stall Detection
Connect a Hall-effect encoder or optical interrupter to a GPIO interrupt pin. Count pulses per second (RPM). Stall condition: high current AND zero speed after startup:
volatile long encoderCount = 0;
void IRAM_ATTR encoderISR() { encoderCount++; }
void setup() {
attachInterrupt(digitalPinToInterrupt(ENCODER_PIN), encoderISR, RISING);
}
bool isStalled(float current_A) {
static long lastCount = 0;
static unsigned long lastCheck = 0;
if (millis() - lastCheck < 500) return false; // check every 500ms
long currentCount = encoderCount;
long delta = currentCount - lastCount;
lastCount = currentCount;
lastCheck = millis();
bool highCurrent = current_A > RATED_CURRENT_A * 2.0;
bool noRotation = (delta == 0);
return (highCurrent && noRotation);
}
7. AC Motor Current Monitoring
For 230V single-phase or 400V three-phase AC motors, the ACS712 can still be used in the neutral or phase wire—the Hall-effect sensor is isolated from the microcontroller regardless of the mains voltage. However, the MCU circuit must be properly isolated from the mains (use an isolated DC-DC converter for the ACS712 power supply, and optocouplers or isolation amplifiers between the ACS712 output and the MCU). Never connect the ACS712 output directly to an MCU while the ACS712 is in a mains circuit without isolation—the fault condition would present lethal voltage on the MCU pins.
For AC current monitoring specifically, a Current Transformer (CT sensor, e.g. YHDC SCT-013) is safer because it is inherently isolated. The CT secondary output (typically 0–1V AC or with a burden resistor) feeds a rectifier + smoothing capacitor to produce a DC voltage proportional to RMS current, readable by the ADC.
8. Hardware Protection Circuits
Software detection alone is insufficient for stall protection—if the firmware crashes or hangs, the motor continues to draw stall current. Hardware protection layers to include:
- PTC resettable fuse: Self-resetting polymer fuse that opens when current exceeds its rating. Insert in series with the motor supply. Resets automatically when cool. Choose a rating 150–200% of rated motor current.
- Overcurrent comparator: An LM393 comparator monitors the ACS712 output. If voltage exceeds a preset threshold (overload level), the comparator output immediately disables the motor driver via its EN pin—no firmware latency involved. Response time: <1 µs.
- Thermal cutout: Most quality motor drivers (L298N, DRV8833, TB6612) include an internal thermal shutdown at 150°C junction temperature. This is a last-resort protection, not a primary protection mechanism.
- Current-limiting motor driver: Modern BLDC controllers and stepper drivers allow setting a current limit in hardware. The driver chops the supply to maintain average current at the setpoint—preventing stall current runaway entirely.
9. Recommended Current Sensors at Zbotic
30A Range Current Sensor Module ACS712
Isolated Hall-effect sensing for high-current DC motors and AC loads up to 30A. 66mV/A sensitivity, 5V supply, direct Arduino ADC connection.
20A Range Current Sensor Module ACS712
The most popular range for DC motors up to 240W at 12V. 100mV/A sensitivity provides good resolution for overload threshold detection.
5A Range Current Sensor Module ACS712
Best sensitivity (185mV/A) for small motors and servos. Ideal for robotics joints, gimbal motors, and small pump overload detection.
CJMCU-219 INA219 I2C Bi-directional Current / Power Monitoring
High-precision I2C current sensor with 0.8mA resolution and simultaneous power measurement. Perfect for battery-powered motor systems and precision monitoring.
10. Frequently Asked Questions
Q: My ACS712 reads a non-zero current when no current flows. How do I fix this?
The ACS712 has an output offset that drifts with temperature (typically ±10 mA/°C zero error). Perform a software zero-calibration: read the sensor at known zero current (motor disconnected, not just stopped), store this as your baseline, and subtract it from all subsequent readings. Re-calibrate if the ambient temperature changes significantly.
Q: Can I use these sensors to detect a jammed conveyor belt?
Yes—this is a classic industrial application. A conveyor driven by an AC motor shows a distinctive current signature when jammed: current rises to near-stall level (5–8× rated) within 100–200 ms. Set your stall threshold at 4× rated current with a 300 ms delay to allow for brief momentary snags. Log the event with a timestamp for maintenance records.
Q: How many ACS712 sensors can I wire to one Arduino?
Each ACS712 uses one analog pin. An Arduino Uno has 6 analog inputs, so you can monitor 6 motors simultaneously. An ESP32 has up to 18 ADC channels but practical usable channels (considering ADC2 conflicts with WiFi) is about 10. The INA219’s I2C interface allows up to 16 sensors on a single bus by configuring different I2C addresses.
Q: What response time is achievable with software-based stall detection?
With the ACS712 and a 10 ms polling loop (Arduino analogRead + processing), you can achieve detection-to-shutdown in 10–50 ms. The INA219 with I2C at 400 kHz can update in 1 ms per read. For sub-millisecond response, use the hardware comparator approach: the LM393 or a dedicated overcurrent comparator IC (e.g. MAX9922) responds in 1–5 µs and directly disables the driver EN pin without any MCU involvement.
Q: Can I distinguish between overload and stall using current alone (no encoder)?
With some reliability. Stall typically produces current 5–10× rated (limited by winding resistance only), while overload produces 1.5–3× rated (back-EMF still partially opposes the supply). A dual-threshold approach works: >5× rated → immediate stall trip (200 ms delay); 1.5–5× rated → thermal overload trip (3–30 s delay). This is not foolproof—a very heavy overload and a partial stall can produce similar currents. An encoder provides definitive discrimination.
11. Conclusion
Motor current sensing is one of the most cost-effective protections you can add to any motor-driven system. A ₹150 ACS712 module and 50 lines of Arduino code can prevent ₹5,000 in motor and driver replacement costs—and in industrial applications, the calculation is even more compelling. The ACS712 is ideal for isolated measurement of DC and AC motors up to 30A, while the INA219 provides higher precision for battery-powered and low-current applications.
Build overload protection with a startup inhibit window, stall protection with a shorter trip delay, and a hardware comparator backup for fail-safe operation. Your motors will thank you.
Shop ACS712 (5A, 20A, 30A) and INA219 current sensors at Zbotic Sensors & Modules. Fast shipping across India.
Add comment