STM32 drives INA226 to measure current, voltage, and power

 INA226 + STM32 is a rock-solid combo for precision DC current, bus voltage, and power. Here’s a clean, copy-ready guide with wiring, calibration math, and working HAL code.




STM32 + INA226 (I²C) — Measure Current, Bus Voltage & Power

1) What the INA226 gives you

  • Bus voltage (VBUS): up to 36 V, LSB = 1.25 mV

  • Shunt voltage (VSHUNT) across your sense resistor, LSB = 2.5 µV

  • Current (after you program a calibration)

  • Power (after calibration), Power_LSB = 25 × Current_LSB

  • Programmable averaging, conversion times, and alert (over-current, over-voltage, power, etc.)


2) Typical wiring (single-supply)

  • Shunt resistor (RSHUNT) in series with the load on the low side or high side (INA226 supports both; high side is common).

  • Connect:

    • VIN+ to load side (after shunt toward load)

    • VIN− to source side (before shunt toward supply)

    • VBUS internally sensed from VIN+ (no extra wire for bus voltage)

    • SDA / SCL → STM32 I²C pins (e.g., PB9/PB8 on many Nucleo boards)

    • A0, A1 to GND/VCC for I²C address select (0x40–0x4F)

    • ALERT (optional) to an STM32 EXTI-capable GPIO for interrupts

    • Decoupling 0.1 µF close to INA226 VCC

I²C address: base 0x40 when A1=A0=GND (others up to 0x4F).


3) Key registers (16-bit)

RegisterAddrNotes
Configuration0x00Averaging, conv. times, mode
Shunt Voltage0x012.5 µV/bit (signed)
Bus Voltage0x021.25 mV/bit (unsigned)
Power0x0325×Current_LSB (W/bit), needs CAL
Current0x04Current_LSB (A/bit), needs CAL
Calibration0x05Sets Current_LSB & scaling
Mask/Enable0x06ALERT config
Alert Limit0x07Threshold (unit depends on mask)

All registers are big-endian (MSB first).


4) Calibration math (do this once!)

  1. Choose RSHUNT and your IMAX (expected max current).

  2. Pick Current_LSB ≈ IMAX / 32768 (A/bit).

  3. Compute CAL (write to Calibration register):

    CAL=0.00512Current_LSB×RSHUNT\text{CAL} = \frac{0.00512}{\text{Current\_LSB} \times R_{\text{SHUNT}}}

    (CAL is a 16-bit integer; clamp to ≤ 0x7FFF if needed.)

  4. Then:

    • Current (A) = Current_Reg × Current_LSB

    • Power (W) = Power_Reg × (25 × Current_LSB)

Example

  • RSHUNT = 0.010 Ω, IMAX = 3.0 A

  • Current_LSB = 3.0 / 32768 = 9.1552734e-5 A/bit (≈ 91.55 µA/bit)

  • CAL = 0.00512 / (9.1552734e-5 × 0.01) ≈ 5592 = 0x15D8

  • Power_LSB = 25 × Current_LSB = 0.0022888 W/bit (≈ 2.289 mW/bit)


5) Recommended configuration

  • Averaging (AVG): e.g., 16–64 (trade noise vs speed)

  • VBUS/VSHUNT conversion time: 1100 µs (or 140 µs…8.244 ms)

  • Mode: Shunt+Bus, continuous

Configuration register (0x00) fields (typical):

  • AVG = 0b010 (16x) or 0b011 (64x)

  • VBUSCT = 0b100 (1.1 ms)

  • VSHCT = 0b100 (1.1 ms)

  • MODE = 0b111 (Shunt+Bus continuous)


6) STM32 HAL code (I²C)

6.1 Helpers

#include "main.h" extern I2C_HandleTypeDef hi2c1; // or your I2C handle #define INA226_ADDR (0x40 << 1) // 7-bit addr <<1 for HAL #define REG_CONFIG 0x00 #define REG_SHUNT 0x01 #define REG_BUS 0x02 #define REG_POWER 0x03 #define REG_CURRENT 0x04 #define REG_CAL 0x05 #define REG_MASK_ENABLE 0x06 #define REG_ALERT_LIMIT 0x07 static HAL_StatusTypeDef ina226_write16(uint8_t reg, uint16_t val) { uint8_t buf[3]; buf[0] = reg; buf[1] = (uint8_t)(val >> 8); buf[2] = (uint8_t)(val & 0xFF); return HAL_I2C_Master_Transmit(&hi2c1, INA226_ADDR, buf, 3, HAL_MAX_DELAY); } static HAL_StatusTypeDef ina226_read16(uint8_t reg, uint16_t *val) { uint8_t data[2]; HAL_StatusTypeDef st = HAL_I2C_Master_Transmit(&hi2c1, INA226_ADDR, &reg, 1, HAL_MAX_DELAY); if (st != HAL_OK) return st; st = HAL_I2C_Master_Receive(&hi2c1, INA226_ADDR, data, 2, HAL_MAX_DELAY); if (st != HAL_OK) return st; *val = ((uint16_t)data[0] << 8) | data[1]; return HAL_OK; }

6.2 Init (config + calibration)

// Example: AVG=16, VBUSCT=1.1ms, VSHCT=1.1ms, MODE=Shunt+Bus Continuous HAL_StatusTypeDef ina226_init(void) { uint16_t config = 0; // AVG[2:0]=0b010 (16x) -> bits 11:9 config |= (0x2 << 9); // VBUSCT[2:0]=0b100 (1.1ms) -> bits 8:6 config |= (0x4 << 6); // VSHCT[2:0]=0b100 (1.1ms) -> bits 5:3 config |= (0x4 << 3); // MODE[2:0]=0b111 (Shunt+Bus continuous) -> bits 2:0 config |= 0x7; if (ina226_write16(REG_CONFIG, config) != HAL_OK) return HAL_ERROR; // Calibration for Rshunt=0.01Ω, Imax=3A (CAL=0x15D8 from example) if (ina226_write16(REG_CAL, 0x15D8) != HAL_OK) return HAL_ERROR; return HAL_OK; }

6.3 Read & convert to units

// Match these to your calibration choices: static const float CURRENT_LSB = 9.1552734375e-5f; // A/bit (example) static const float POWER_LSB = 25.0f * 9.1552734375e-5f; // W/bit HAL_StatusTypeDef ina226_read_measurements(float *bus_V, float *shunt_V, float *current_A, float *power_W) { uint16_t raw; // Bus voltage (1.25 mV/bit) if (ina226_read16(REG_BUS, &raw) != HAL_OK) return HAL_ERROR; *bus_V = (float)raw * 0.00125f; // Shunt voltage is signed (2.5 µV/bit) if (ina226_read16(REG_SHUNT, &raw) != HAL_OK) return HAL_ERROR; int16_t shunt_raw = (int16_t)raw; *shunt_V = (float)shunt_raw * 2.5e-6f; // Current (A) from CURRENT register if (ina226_read16(REG_CURRENT, &raw) != HAL_OK) return HAL_ERROR; int16_t curr_raw = (int16_t)raw; *current_A = (float)curr_raw * CURRENT_LSB; // Power (W) from POWER register if (ina226_read16(REG_POWER, &raw) != HAL_OK) return HAL_ERROR; *power_W = (float)raw * POWER_LSB; return HAL_OK; }

7) Using ALERT (optional)

  • Configure Mask/Enable to select alert source (e.g., over-current).

  • Write Alert Limit with a threshold in the corresponding units (depends on alert function).

  • Route ALERT to an EXTI pin; in ISR, read Mask/Enable to clear/identify cause.

Example idea: over-current alert → set Alert Limit = threshold / Current_LSB (in Current register’s units) and enable the Conversion Ready bit to pace reads.


8) Accuracy tips

  • Choose RSHUNT so that your typical/peak current uses a healthy fraction of the shunt’s full-scale voltage (keep power dissipation acceptable: P=I2RP=I^2R).

  • Prefer low TCR (e.g., 50 ppm/°C) 1% or 0.5% shunts; 2512 or 1206 packages for thermal stability.

  • Use averaging for noisy loads; raise conversion time for better resolution.

  • Kelvin-connect the shunt; keep high-current paths short and away from sense lines.

  • If measuring at high bus voltages, respect creepage/clearance on the PCB.


9) Quick checklist

  • I²C at 100–400 kHz, pull-ups 2.2–4.7 kΩ

  • Correct I²C address from A0/A1 strap

  • Write CONFIG, then CAL

  • Use correct LSB scales (1.25 mV, 2.5 µV, Current_LSB, 25×Current_LSB)

  • Convert signed registers properly (shunt, current)

  • Optional: set ALERT mask & limit, handle EXTI


10) Troubleshooting

  • All zeros? Check CAL register was written and mode is continuous.

  • Crazy values? Endianness, wrong LSBs, or mis-wired VIN+/VIN-.

  • I²C NACK? Address pins (A0/A1), pull-ups, or wrong 8-bit vs 7-bit address in HAL.

  • Noisy readings? Increase averaging and conversion time; improve shunt layout.

评论

此博客中的热门博文

Detailed Explanation of STM32 HAL Library Clock System

How To Connect Stm32 To PC?

How to add a GPS sensor to ESP32 for Wokwi?