Catch a motor starting
A motor draws several times its running current for the first few tens of milliseconds, and that spike is what trips a supply or browns out a board. The INA219 can take a fresh reading every 532 µs, or average up to 128 of them into one. Short readings catch the spike; long ones give a steady number and hide it.
A start is a spike
A DC motor at rest has no speed to push back with, so for the first moments it draws what its winding resistance allows: often several times its running current. That spike lasts tens of milliseconds, and it is the current a supply or a fuse has to survive.
Wire the motor's supply through the block, POWER to LOAD, with the motor or its driver across the LOAD terminals, and the ESP32 only on the header.
Fast readings or steady ones
The chip makes one 12-bit reading of the shunt in 532 µs. It can instead average 2, 4 and so on up to 128 readings into one, which takes up to 68 ms and gives a much steadier number.
For a start, that steadiness is the problem: a 68 ms average of a 30 ms spike is mostly the running current. The drawing above is illustrative, but the rule is not. To catch a spike, use short readings. To report a steady current, average.
The sketch
It writes the config register itself: 32 V bus range, the widest gain, a single 532 µs reading, and the shunt only, since the bus voltage is not needed here.
Then it reads the shunt register as fast as I²C at 400 kHz allows, for 200 ms at a time, and prints the highest reading and the mean. One count is 10 µV, which on this block's 100 mΩ is 0.1 mA, so the conversion is one multiply.
Reading faster than the chip converts returns the same value more than once, which does no harm to a peak or a mean.
Reading the result
Switch the motor on and watch one line: the peak column jumps and the mean barely moves. The next line is back to the running current.
Change ONE_SAMPLE to AVERAGE_128 and do it again. The peak shrinks toward
the mean, and that difference is what a slow, averaged reading would have hidden.
The code
Sets the chip to measure only the shunt, a new reading every 532 µs, and reads it as fast as the bus allows. Every 200 ms it prints the highest current it saw and the mean. Switch a motor on and the peak column shows the start.
// TK119 INA219: catch a motor starting, on an ESP32-S3.
//
// Wiring, TK119 header left to right (parts up, pins down):
// GND -> ESP32 GND
// 3V3 -> ESP32 3V3
// SCL -> GPIO9 (the third pin: the clock comes first)
// SDA -> GPIO8
// Then the rail: the motor supply's + to POWER +, - to
// POWER -, and the motor or its driver across LOAD + and -.
//
// Arduino IDE: Tools > Board > esp32 > ESP32S3 Dev Module,
// Tools > USB CDC On Boot > Enabled, then Tools > Port.
// No library needed. Serial Monitor at 115200.
#include <Wire.h>
const int SDA_PIN = 8, SCL_PIN = 9;
const uint8_t ADDR = 0x40;
// Config: 32 V range, gain /8 (3.2 A), shunt only,
// continuous. ONE_SAMPLE is a new reading every 532 us;
// AVERAGE_128 is one reading every 68 ms, the mean of 128.
const uint16_t ONE_SAMPLE = 0x399D;
const uint16_t AVERAGE_128 = 0x39FD;
void writeReg(uint8_t reg, uint16_t value) {
Wire.beginTransmission(ADDR);
Wire.write(reg);
Wire.write(value >> 8);
Wire.write(value & 0xFF);
Wire.endTransmission();
}
int16_t readReg(uint8_t reg) {
Wire.beginTransmission(ADDR);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom(ADDR, (uint8_t)2);
uint8_t hi = Wire.read();
uint8_t lo = Wire.read();
return (int16_t)((hi << 8) | lo);
}
void setup() {
Serial.begin(115200);
delay(500);
Wire.begin(SDA_PIN, SCL_PIN);
Wire.setClock(400000);
writeReg(0x00, ONE_SAMPLE); // try AVERAGE_128 to compare
Serial.println("peak_mA mean_mA (each line is 200 ms)");
}
void loop() {
float peak = 0, sum = 0;
int n = 0;
unsigned long t0 = millis();
while (millis() - t0 < 200) {
// Shunt register: 10 uV a count, which is 0.1 mA here.
float ma = readReg(0x01) * 0.1;
if (ma > peak) peak = ma;
sum += ma;
n++;
}
Serial.printf("%7.1f %7.1f\n", peak, sum / n);
}Change ONE_SAMPLE to AVERAGE_128 in setup() and run the same test: the peak column falls toward the mean, because each reading is now the average of 68 ms. No library is used: the sketch writes the config register and reads the shunt register itself.
When it does not work
Check setup() wrote ONE_SAMPLE and not AVERAGE_128. Averaged over 68 ms, a start that lasts a few tens of milliseconds is smoothed into the running current. With ONE_SAMPLE the chip has a new reading every 532 µs, fast enough to catch it.
The start current is past 3.2 A, the top of the widest range, and the reading pins there. The true peak is higher than the column says. Past about 4.4 A the shunt is also beyond its 2 W rating, so keep a motor that large off this block, or limit its supply.
The motor is probably running from the same supply as the ESP32, and its start pulls that supply down. Give the motor its own supply through the block, joined to the ESP32 only by the ground, and switch it with a driver board rather than a GPIO pin.
A brushed motor's current genuinely ripples as its brushes move, and one 532 µs reading catches wherever the ripple happens to be. Use the mean column for the running current, and the peak column only for starts and stalls.
Edit this page — content/books/ina219/catch-a-motor-starting.mdx
Questions about this product
See what other owners have asked, and read their solutions.
TK119 INA219 Current and Voltage Monitor
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.