embedded_devices/devices/texas_instruments/ina226/
mod.rs1use self::address::Address;
87
88use embedded_devices_derive::{forward_register_fns, sensor};
89use embedded_interfaces::TransportError;
90use uom::si::electric_current::ampere;
91use uom::si::electrical_resistance::ohm;
92use uom::si::f64::{ElectricCurrent, ElectricPotential, ElectricalResistance, Power};
93
94pub mod address;
95pub mod registers;
96
97#[cfg_attr(feature = "defmt", derive(defmt::Format))]
98#[derive(Debug, thiserror::Error)]
99pub enum InitError<BusError> {
100 #[error("transport error")]
102 Transport(#[from] TransportError<(), BusError>),
103 #[error("invalid die id {0:#04x}")]
105 InvalidDieId(u16),
106 #[error("invalid manufacturer id {0:#04x}")]
108 InvalidManufacturerId(u16),
109}
110
111#[derive(Debug, thiserror::Error)]
112pub enum MeasurementError<BusError> {
113 #[error("transport error")]
115 Transport(#[from] TransportError<(), BusError>),
116 #[error("conversion timeout")]
118 Timeout,
119 #[error("overflow in measurement")]
122 Overflow(Measurement),
123}
124
125#[derive(Debug, thiserror::Error)]
126pub enum ContinuousMeasurementError<BusError> {
127 #[error("transport error")]
129 Transport(#[from] TransportError<(), BusError>),
130 #[error("overflow in measurement")]
133 Overflow(Measurement),
134}
135
136#[derive(Debug, embedded_devices_derive::Measurement)]
138pub struct Measurement {
139 pub shunt_voltage: ElectricPotential,
141 #[measurement(Voltage)]
143 pub bus_voltage: ElectricPotential,
144 #[measurement(Current)]
146 pub current: ElectricCurrent,
147 #[measurement(Power)]
149 pub power: Power,
150}
151
152#[maybe_async_cfg::maybe(
159 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
160 sync(feature = "sync"),
161 async(feature = "async")
162)]
163pub struct INA226<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> {
164 delay: D,
166 interface: I,
168 shunt_resistance: ElectricalResistance,
170 max_expected_current: ElectricCurrent,
172 current_lsb_na: i64,
174}
175
176pub trait INA226Register {}
177
178#[maybe_async_cfg::maybe(
179 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), I2cDevice),
180 sync(feature = "sync"),
181 async(feature = "async")
182)]
183impl<D, I> INA226<D, embedded_interfaces::i2c::I2cDevice<I, hal::i2c::SevenBitAddress>>
184where
185 I: hal::i2c::I2c<hal::i2c::SevenBitAddress> + hal::i2c::ErrorType,
186 D: hal::delay::DelayNs,
187{
188 #[inline]
194 pub fn new_i2c(delay: D, interface: I, address: Address) -> Self {
195 Self {
196 delay,
197 interface: embedded_interfaces::i2c::I2cDevice::new(interface, address.into()),
198 shunt_resistance: Default::default(),
199 max_expected_current: Default::default(),
200 current_lsb_na: 1,
201 }
202 }
203}
204
205#[forward_register_fns]
206#[sensor(Voltage, Current, Power)]
207#[maybe_async_cfg::maybe(
208 idents(
209 hal(sync = "embedded_hal", async = "embedded_hal_async"),
210 RegisterInterface,
211 ResettableDevice
212 ),
213 sync(feature = "sync"),
214 async(feature = "async")
215)]
216impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> INA226<D, I> {
217 pub async fn init(
222 &mut self,
223 shunt_resistance: ElectricalResistance,
224 max_expected_current: ElectricCurrent,
225 ) -> Result<(), InitError<I::BusError>> {
226 use crate::device::ResettableDevice;
227 use registers::{DieId, ManufacturerId};
228
229 self.reset().await?;
232 self.delay.delay_us(500).await;
233
234 let manufacturer_id = self.read_register::<ManufacturerId>().await?.read_id();
236 if manufacturer_id != ManufacturerId::default().read_id() {
237 return Err(InitError::InvalidManufacturerId(manufacturer_id));
238 }
239 let die_id = self.read_register::<DieId>().await?.read_id();
240 if die_id != DieId::default().read_id() {
241 return Err(InitError::InvalidDieId(die_id));
242 }
243
244 self.calibrate(shunt_resistance, max_expected_current).await?;
245
246 Ok(())
247 }
248
249 pub async fn calibrate(
252 &mut self,
253 shunt_resistance: ElectricalResistance,
254 max_expected_current: ElectricCurrent,
255 ) -> Result<(), TransportError<(), I::BusError>> {
256 self.shunt_resistance = shunt_resistance;
257 self.max_expected_current = max_expected_current;
258
259 let shunt_resistance = shunt_resistance.get::<ohm>();
260 let max_expected_current = max_expected_current.get::<ampere>();
261
262 self.current_lsb_na = ((1_000_000_000f64 / (1 << 15) as f64) * max_expected_current) as i64;
263 let shunt_resistance_mohm = (1_000.0 * shunt_resistance) as i64;
264
265 let cal = 5_120_000_000 / (self.current_lsb_na * shunt_resistance_mohm);
267 self.write_register(self::registers::Calibration::default().with_raw_value(cal as u16))
268 .await?;
269
270 Ok(())
271 }
272
273 pub async fn read_measurements(&mut self) -> Result<Measurement, MeasurementError<I::BusError>> {
276 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
277 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
278 let current = self.read_register::<self::registers::Current>().await?;
279 let power = self.read_register::<self::registers::Power>().await?;
280 let flags = self.read_register::<self::registers::MaskEnable>().await?;
281
282 let measurement = Measurement {
283 shunt_voltage: shunt_voltage.read_value(),
284 bus_voltage: bus_voltage.read_value(),
285 current: current.read_current(self.current_lsb_na),
286 power: power.read_power(self.current_lsb_na),
287 };
288
289 if flags.read_math_overflow_flag() {
290 Err(MeasurementError::Overflow(measurement))
291 } else {
292 Ok(measurement)
293 }
294 }
295}
296
297#[maybe_async_cfg::maybe(
298 idents(
299 hal(sync = "embedded_hal", async = "embedded_hal_async"),
300 RegisterInterface,
301 ResettableDevice
302 ),
303 sync(feature = "sync"),
304 async(feature = "async")
305)]
306impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::device::ResettableDevice
307 for INA226<D, I>
308{
309 type Error = TransportError<(), I::BusError>;
310
311 async fn reset(&mut self) -> Result<(), Self::Error> {
313 self.write_register(self::registers::Configuration::default().with_reset(true))
314 .await?;
315 Ok(())
316 }
317}
318
319#[maybe_async_cfg::maybe(
320 idents(
321 hal(sync = "embedded_hal", async = "embedded_hal_async"),
322 RegisterInterface,
323 OneshotSensor
324 ),
325 sync(feature = "sync"),
326 async(feature = "async")
327)]
328impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
329 for INA226<D, I>
330{
331 type Error = MeasurementError<I::BusError>;
332 type Measurement = Measurement;
333
334 async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
338 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
339
340 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::ShuntAndBusTriggered))
342 .await?;
343
344 let mut measurement_time_us = reg_conf.total_conversion_time_us();
346 measurement_time_us += measurement_time_us / 10; self.delay.delay_us(1000 + measurement_time_us).await;
348
349 const TRIES: u8 = 5;
351 for _ in 0..TRIES {
352 let flags = self.read_register::<self::registers::MaskEnable>().await?;
353 if !flags.read_conversion_ready_flag() {
354 self.delay.delay_us(1000).await;
355 continue;
356 }
357
358 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
359 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
360 let current = self.read_register::<self::registers::Current>().await?;
361 let power = self.read_register::<self::registers::Power>().await?;
363
364 let measurement = Measurement {
365 shunt_voltage: shunt_voltage.read_value(),
366 bus_voltage: bus_voltage.read_value(),
367 current: current.read_current(self.current_lsb_na),
368 power: power.read_power(self.current_lsb_na),
369 };
370
371 if flags.read_math_overflow_flag() {
372 return Err(MeasurementError::Overflow(measurement));
373 } else {
374 return Ok(measurement);
375 }
376 }
377
378 Err(MeasurementError::Timeout)
379 }
380}
381
382#[maybe_async_cfg::maybe(
383 idents(
384 hal(sync = "embedded_hal", async = "embedded_hal_async"),
385 RegisterInterface,
386 ContinuousSensor
387 ),
388 sync(feature = "sync"),
389 async(feature = "async")
390)]
391impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
392 for INA226<D, I>
393{
394 type Error = ContinuousMeasurementError<I::BusError>;
395 type Measurement = Measurement;
396
397 async fn start_measuring(&mut self) -> Result<(), Self::Error> {
399 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
400 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::ShuntAndBusContinuous))
401 .await?;
402 Ok(())
403 }
404
405 async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
407 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
408 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::PowerDown))
409 .await?;
410 Ok(())
411 }
412
413 async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
415 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
416 let mut measurement_time_us = reg_conf.total_conversion_time_us();
417 measurement_time_us += measurement_time_us / 10; Ok(measurement_time_us)
419 }
420
421 async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
423 let flags = self.read_register::<self::registers::MaskEnable>().await?;
424 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
425 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
426 let current = self.read_register::<self::registers::Current>().await?;
427 let power = self.read_register::<self::registers::Power>().await?;
429
430 let measurement = Measurement {
431 shunt_voltage: shunt_voltage.read_value(),
432 bus_voltage: bus_voltage.read_value(),
433 current: current.read_current(self.current_lsb_na),
434 power: power.read_power(self.current_lsb_na),
435 };
436
437 if flags.read_math_overflow_flag() {
438 Err(ContinuousMeasurementError::Overflow(measurement))
439 } else {
440 Ok(Some(measurement))
441 }
442 }
443
444 async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
446 let flags = self.read_register::<self::registers::MaskEnable>().await?;
447 Ok(flags.read_conversion_ready_flag())
448 }
449
450 async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
453 loop {
454 let flags = self.read_register::<self::registers::MaskEnable>().await?;
455 if flags.read_conversion_ready_flag() {
456 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
457 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
458 let current = self.read_register::<self::registers::Current>().await?;
459 let power = self.read_register::<self::registers::Power>().await?;
461
462 let measurement = Measurement {
463 shunt_voltage: shunt_voltage.read_value(),
464 bus_voltage: bus_voltage.read_value(),
465 current: current.read_current(self.current_lsb_na),
466 power: power.read_power(self.current_lsb_na),
467 };
468
469 if flags.read_math_overflow_flag() {
470 return Err(ContinuousMeasurementError::Overflow(measurement));
471 } else {
472 return Ok(measurement);
473 }
474 }
475
476 self.delay.delay_us(100).await;
477 }
478 }
479}