embedded_devices/devices/texas_instruments/ina219/
mod.rs1use self::address::Address;
90
91use embedded_devices_derive::{forward_register_fns, sensor};
92use embedded_interfaces::TransportError;
93use uom::si::electric_current::ampere;
94use uom::si::electrical_resistance::ohm;
95use uom::si::f64::{ElectricCurrent, ElectricPotential, ElectricalResistance, Power};
96
97pub mod address;
98pub mod registers;
99
100#[derive(Debug, thiserror::Error)]
101pub enum MeasurementError<BusError> {
102 #[error("transport error")]
104 Transport(#[from] TransportError<(), BusError>),
105 #[error("conversion timeout")]
107 Timeout,
108 #[error("overflow in measurement")]
111 Overflow(Measurement),
112}
113
114#[derive(Debug, thiserror::Error)]
115pub enum ContinuousMeasurementError<BusError> {
116 #[error("transport error")]
118 Transport(#[from] TransportError<(), BusError>),
119 #[error("overflow in measurement")]
122 Overflow(Measurement),
123}
124
125#[derive(Debug, embedded_devices_derive::Measurement)]
127pub struct Measurement {
128 pub shunt_voltage: ElectricPotential,
130 #[measurement(Voltage)]
132 pub bus_voltage: ElectricPotential,
133 #[measurement(Current)]
135 pub current: ElectricCurrent,
136 #[measurement(Power)]
138 pub power: Power,
139}
140
141#[maybe_async_cfg::maybe(
147 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
148 sync(feature = "sync"),
149 async(feature = "async")
150)]
151pub struct INA219<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> {
152 delay: D,
154 interface: I,
156 shunt_resistance: ElectricalResistance,
158 max_expected_current: ElectricCurrent,
160 current_lsb_na: u32,
162}
163
164pub trait INA219Register {}
165
166#[maybe_async_cfg::maybe(
167 idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), I2cDevice),
168 sync(feature = "sync"),
169 async(feature = "async")
170)]
171impl<D, I> INA219<D, embedded_interfaces::i2c::I2cDevice<I, hal::i2c::SevenBitAddress>>
172where
173 I: hal::i2c::I2c<hal::i2c::SevenBitAddress> + hal::i2c::ErrorType,
174 D: hal::delay::DelayNs,
175{
176 #[inline]
182 pub fn new_i2c(delay: D, interface: I, address: Address) -> Self {
183 Self {
184 delay,
185 interface: embedded_interfaces::i2c::I2cDevice::new(interface, address.into()),
186 shunt_resistance: Default::default(),
187 max_expected_current: Default::default(),
188 current_lsb_na: 1,
189 }
190 }
191}
192
193#[forward_register_fns]
194#[sensor(Voltage, Current, Power)]
195#[maybe_async_cfg::maybe(
196 idents(
197 hal(sync = "embedded_hal", async = "embedded_hal_async"),
198 RegisterInterface,
199 ResettableDevice
200 ),
201 sync(feature = "sync"),
202 async(feature = "async")
203)]
204impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> INA219<D, I> {
205 pub async fn init(
210 &mut self,
211 shunt_resistance: ElectricalResistance,
212 max_expected_current: ElectricCurrent,
213 ) -> Result<(), TransportError<(), I::BusError>> {
214 use crate::device::ResettableDevice;
215
216 self.reset().await?;
217 self.calibrate(shunt_resistance, max_expected_current).await?;
218 Ok(())
219 }
220
221 pub async fn calibrate(
224 &mut self,
225 shunt_resistance: ElectricalResistance,
226 max_expected_current: ElectricCurrent,
227 ) -> Result<(), TransportError<(), I::BusError>> {
228 self.shunt_resistance = shunt_resistance;
229 self.max_expected_current = max_expected_current;
230
231 let shunt_resistance = shunt_resistance.get::<ohm>();
232 let max_expected_current = max_expected_current.get::<ampere>();
233
234 self.current_lsb_na = ((1_000_000_000f64 / (1 << 15) as f64) * max_expected_current) as u32;
235 let shunt_resistance_mohm = (1_000.0 * shunt_resistance) as u32;
236
237 let cal = 4_096_000_000 / (self.current_lsb_na * shunt_resistance_mohm / 10);
240 self.write_register(self::registers::Calibration::default().with_raw_value(cal as u16))
241 .await?;
242
243 Ok(())
244 }
245
246 pub async fn read_measurements(&mut self) -> Result<Measurement, MeasurementError<I::BusError>> {
249 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
250 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
251 let current = self.read_register::<self::registers::Current>().await?;
252 let power = self.read_register::<self::registers::Power>().await?;
253
254 let measurement = Measurement {
255 shunt_voltage: shunt_voltage.read_value(),
256 bus_voltage: bus_voltage.read_value(),
257 current: current.read_current(self.current_lsb_na),
258 power: power.read_power(self.current_lsb_na),
259 };
260
261 if bus_voltage.read_overflow() {
262 Err(MeasurementError::Overflow(measurement))
263 } else {
264 Ok(measurement)
265 }
266 }
267}
268
269#[maybe_async_cfg::maybe(
270 idents(
271 hal(sync = "embedded_hal", async = "embedded_hal_async"),
272 RegisterInterface,
273 ResettableDevice
274 ),
275 sync(feature = "sync"),
276 async(feature = "async")
277)]
278impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::device::ResettableDevice
279 for INA219<D, I>
280{
281 type Error = TransportError<(), I::BusError>;
282
283 async fn reset(&mut self) -> Result<(), Self::Error> {
285 self.write_register(self::registers::Configuration::default().with_reset(true))
286 .await?;
287 Ok(())
288 }
289}
290
291#[maybe_async_cfg::maybe(
292 idents(
293 hal(sync = "embedded_hal", async = "embedded_hal_async"),
294 RegisterInterface,
295 OneshotSensor
296 ),
297 sync(feature = "sync"),
298 async(feature = "async")
299)]
300impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
301 for INA219<D, I>
302{
303 type Error = MeasurementError<I::BusError>;
304 type Measurement = Measurement;
305
306 async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
310 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
311
312 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::ShuntAndBusTriggered))
314 .await?;
315
316 let measurement_time_us = reg_conf.read_bus_adc_resolution().conversion_time_us()
318 + reg_conf.read_shunt_adc_resolution().conversion_time_us();
319 self.delay.delay_us(1000 + measurement_time_us).await;
320
321 const TRIES: u8 = 5;
323 for _ in 0..TRIES {
324 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
325
326 if bus_voltage.read_conversion_ready() {
327 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
328 let current = self.read_register::<self::registers::Current>().await?;
329 let power = self.read_register::<self::registers::Power>().await?;
331
332 let measurement = Measurement {
333 shunt_voltage: shunt_voltage.read_value(),
334 bus_voltage: bus_voltage.read_value(),
335 current: current.read_current(self.current_lsb_na),
336 power: power.read_power(self.current_lsb_na),
337 };
338
339 if bus_voltage.read_overflow() {
340 return Err(MeasurementError::Overflow(measurement));
341 } else {
342 return Ok(measurement);
343 }
344 }
345
346 self.delay.delay_us(1000).await;
347 }
348
349 Err(MeasurementError::Timeout)
350 }
351}
352
353#[maybe_async_cfg::maybe(
354 idents(
355 hal(sync = "embedded_hal", async = "embedded_hal_async"),
356 RegisterInterface,
357 ContinuousSensor
358 ),
359 sync(feature = "sync"),
360 async(feature = "async")
361)]
362impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
363 for INA219<D, I>
364{
365 type Error = ContinuousMeasurementError<I::BusError>;
366 type Measurement = Measurement;
367
368 async fn start_measuring(&mut self) -> Result<(), Self::Error> {
370 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
371 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::ShuntAndBusContinuous))
372 .await?;
373 Ok(())
374 }
375
376 async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
378 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
379 self.write_register(reg_conf.with_operating_mode(self::registers::OperatingMode::PowerDown))
380 .await?;
381 Ok(())
382 }
383
384 async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
386 let reg_conf = self.read_register::<self::registers::Configuration>().await?;
387 let measurement_time_us = reg_conf.read_bus_adc_resolution().conversion_time_us()
388 + reg_conf.read_shunt_adc_resolution().conversion_time_us();
389 Ok(measurement_time_us)
390 }
391
392 async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
394 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
395 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
396 let current = self.read_register::<self::registers::Current>().await?;
397 let power = self.read_register::<self::registers::Power>().await?;
399
400 let measurement = Measurement {
401 shunt_voltage: shunt_voltage.read_value(),
402 bus_voltage: bus_voltage.read_value(),
403 current: current.read_current(self.current_lsb_na),
404 power: power.read_power(self.current_lsb_na),
405 };
406
407 if bus_voltage.read_overflow() {
408 Err(ContinuousMeasurementError::Overflow(measurement))
409 } else {
410 Ok(Some(measurement))
411 }
412 }
413
414 async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
416 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
417 Ok(bus_voltage.read_conversion_ready())
418 }
419
420 async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
423 loop {
424 let bus_voltage = self.read_register::<self::registers::BusVoltage>().await?;
425 if bus_voltage.read_conversion_ready() {
426 let shunt_voltage = self.read_register::<self::registers::ShuntVoltage>().await?;
427 let current = self.read_register::<self::registers::Current>().await?;
428 let power = self.read_register::<self::registers::Power>().await?;
430
431 let measurement = Measurement {
432 shunt_voltage: shunt_voltage.read_value(),
433 bus_voltage: bus_voltage.read_value(),
434 current: current.read_current(self.current_lsb_na),
435 power: power.read_power(self.current_lsb_na),
436 };
437
438 if bus_voltage.read_overflow() {
439 return Err(ContinuousMeasurementError::Overflow(measurement));
440 } else {
441 return Ok(measurement);
442 }
443 }
444
445 self.delay.delay_us(100).await;
446 }
447 }
448}