INA3221 Triple-Channel Current/Voltage Monitor Driver (ina3221-dd)
A no_std Rust driver for the Texas Instruments INA3221 triple-channel, high-side current and bus voltage monitor. This driver leverages the device-driver crate with a declarative YAML manifest (device.yaml) for a robust, type-safe register map definition. The low-level API covers 100% of the INA3221's registers, with device.yaml providing a comprehensive and accurate description of all registers and their fields verified against the official datasheet.
Overview
The ina3221-dd driver offers:
- Declarative Configuration: The INA3221 register map is defined in
device.yaml, enablingdevice-driverto generate a type-safe, low-level register access API. - Unified Async/Blocking API: Uses the
bisynccrate to provide both asynchronous (Ina3221Async) and blocking (Ina3221) drivers from the same codebase, with no feature flags required. - High-Level and Low-Level APIs:
- High-level methods simplify tasks like reading bus/shunt voltages and calculating current.
- Low-level API (via the
llfield) offers direct, type-safe access to all registers defined indevice.yaml.
- Triple-Channel Monitoring: Monitor three independent power rails simultaneously.
no_stdandno-alloc: Optimized for bare-metal and RTOS environments.- Optional Logging: Supports
defmtand thelogfacade for debugging.
Features
- Three Independent Channels: Monitor voltage and current on three separate power rails.
- Bus Voltage Measurement: 0V to 26V range with 8mV resolution.
- Shunt Voltage Measurement: ±163.8mV range with 40µV resolution.
- Current Calculation: Derive current from shunt voltage and known shunt resistor value.
- Configurable Averaging: 1 to 1024 samples for noise reduction.
- Configurable Conversion Time: 140µs to 8.244ms per channel.
- Multiple Operating Modes: Continuous, single-shot, or power-down.
- Alert Functions:
- Critical and warning alert limits per channel.
- Summation alert for combined channel monitoring.
- Power-valid detection for supply sequencing.
- Four I2C Addresses: 0x40, 0x41, 0x42, 0x43 (configurable via A0 pin).
- Device Identification: Read manufacturer ID (0x5449 = "TI") and die ID (0x3220).
Getting Started
-
Add
ina3221-ddtoCargo.toml:[] = "0.1.0" # For blocking usage (Ina3221): = "1.0.0" # For async usage (Ina3221Async): = "1.0.0" -
Instantiate the driver with your I2C bus:
-
Blocking:
use ; let i2c_bus = /* your I2C bus */; let mut ina = new; // Read bus voltage (in millivolts) let bus_voltage = ina.get_bus_voltage_mv?; // Read shunt voltage (in microvolts) let shunt_voltage = ina.get_shunt_voltage_uv?; // Calculate current (with 100mΩ shunt resistor) let current_ma = ina.get_current_ma?; // Verify device identity let manufacturer_id = ina.get_manufacturer_id?; // Should be 0x5449 let die_id = ina.get_die_id?; // Should be 0x3220 -
Async:
use ; let i2c_bus = /* your async I2C bus */; let mut ina = new; // Read bus voltage (in millivolts) let bus_voltage = ina.get_bus_voltage_mv.await?; // Read shunt voltage (in microvolts) let shunt_voltage = ina.get_shunt_voltage_uv.await?; // Calculate current (with 100mΩ shunt resistor) let current_ma = ina.get_current_ma.await?;
-
I2C Addresses
The INA3221 supports four I2C addresses based on the A0 pin connection:
| A0 Pin Connection | I2C Address | Constant |
|---|---|---|
| GND | 0x40 | INA3221_I2C_ADDR_GND |
| VS | 0x41 | INA3221_I2C_ADDR_VS |
| SDA | 0x42 | INA3221_I2C_ADDR_SDA |
| SCL | 0x43 | INA3221_I2C_ADDR_SCL |
Low-Level API Usage
The driver provides direct access to all INA3221 registers through the low-level API via ina.ll. This API is automatically generated from device.yaml and provides type-safe access to all register fields.
Reading Registers
// Read configuration register
let config = ina.ll.configuration.read?;
let ch1_enabled = config.ch_1_enable;
let averaging = config.averaging_mode;
let operating_mode = config.operating_mode;
// Read raw shunt voltage register
let shunt = ina.ll.channel_1_shunt_voltage.read?;
let sign = shunt.sign;
let data = shunt.shunt_data;
// Read manufacturer ID
let mfr_id = ina.ll.manufacturer_id.read?;
Writing Registers
// Configure the device
ina.ll.configuration.write?;
// Set alert limits
ina.ll.channel_1_critical_alert_limit.write?;
Modifying Registers
Use .modify() to read-modify-write, preserving other fields:
// Change only the averaging mode, preserve other settings
ina.ll.configuration.modify?;
Async Low-Level API
Append _async to method names for async usage:
let config = ina.ll.configuration.read_async.await?;
ina.ll.configuration.modify_async.await?;
Register Map
The complete INA3221 register map is defined in device.yaml:
| Address | Register | Description |
|---|---|---|
| 0x00 | Configuration | Operating modes, conversion times, averaging |
| 0x01-0x06 | Channel Voltages | Shunt and bus voltage for channels 1-3 |
| 0x07-0x0C | Alert Limits | Critical and warning limits per channel |
| 0x0D | Shunt Voltage Sum | Sum of enabled channel shunt voltages |
| 0x0E | Shunt Voltage Sum Limit | Limit for summed shunt voltage |
| 0x0F | Mask/Enable | Alert configuration and status flags |
| 0x10-0x11 | Power Valid Limits | Upper and lower limits for power-valid detection |
| 0xFE | Manufacturer ID | Returns 0x5449 ("TI") |
| 0xFF | Die ID | Returns 0x3220 |
Examples
Examples for ESP32 using esp-hal are included. Both examples demonstrate high-level convenience methods and low-level register API usage.
- Async Example:
examples/test_ina3221_async.rs - Blocking Example:
examples/test_ina3221_blocking.rs
Feature Flags
default = []: No default features; async and blocking drivers are always available.std: Enablesstdfeatures forthiserror.log: Enableslogfacade logging.defmt: Enablesdefmtlogging for embedded debugging.
Current Calculation
The INA3221 measures shunt voltage across an external shunt resistor. To calculate current:
Current (A) = Shunt Voltage (V) / Shunt Resistance (Ω)
The driver's get_current_ma() method handles this calculation:
// With a 100mΩ (0.1Ω) shunt resistor
let current_ma = ina.get_current_ma?;
// With a 10mΩ (0.01Ω) shunt resistor for higher currents
let current_ma = ina.get_current_ma?;
Contributing
Contributions are welcome! You can contribute by:
- Adding high-level convenience methods for additional features.
- Enhancing documentation with examples or clarifications.
- Reporting issues or suggesting improvements.
- Testing on different hardware platforms.
Please submit issues, fork the repository, and create pull requests.
License
This project is dual-licensed under the MIT License or Apache License 2.0, at your option.