1extern crate i2cdev;
2use i2cdev::core::*;
3#[cfg(any(target_os = "linux"))]
4use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};
5use std::{thread::sleep, time::Duration};
6
7#[cfg(not(any(target_os = "linux")))]
8mod stub;
9#[cfg(not(any(target_os = "linux")))]
10use crate::stub::{LinuxI2CDevice, LinuxI2CError};
11
12pub mod units;
13use crate::units::*;
14
15enum RegAddrs {
16 Cfg = 0x00,
17 ShuntVoltage = 0x01,
18 BusVoltage = 0x02,
19 Power = 0x03,
20 Current = 0x04,
21 Calibration = 0x05,
22}
23
24pub struct Ina219 {
25 shunt_resistance: ResistanceUnit,
26 max_expected_current: CurrentUnit,
27 current_lsb: CurrentUnit,
28 power_lsb: PowerUnit,
29 i2c_address: u8,
30 device: LinuxI2CDevice,
31}
32
33impl Ina219 {
34 pub fn new(
36 shunt_resistance: ResistanceUnit,
37 max_expected_current: CurrentUnit,
38 address: u8,
39 ) -> Result<Self, LinuxI2CError> {
40 Ok(
41 Self {
42 shunt_resistance: shunt_resistance,
43 max_expected_current: max_expected_current,
44 current_lsb: CurrentUnit::milliamps(0.0),
45 power_lsb: PowerUnit::milliwatts(0.0),
46 i2c_address: address,
47 device: LinuxI2CDevice::new("/dev/i2c-1", address as u16)?
48 }
49 )
50 }
51
52 pub fn init(&mut self) -> Result<(), LinuxI2CError> {
54 sleep(Duration::from_millis(650)); let current_lsb_val = self.max_expected_current.get_val() / 32768.0;
56 self.current_lsb.set_val(current_lsb_val);
57
58 let power_lsb_val = 20.0 * current_lsb_val;
59 self.power_lsb.set_val(power_lsb_val);
60 self.device.write(&[RegAddrs::Cfg as u8, 0x1F as u8, 0xFF as u8])?; Ok(())
62 }
63
64 fn calibrate(&mut self) -> Result<(), LinuxI2CError> {
65 let cal = (0.04096 / (self.current_lsb.get_val() * self.shunt_resistance.get_val())).trunc() as u16;
66 self.device.write(
67 &[RegAddrs::Calibration as u8, (cal >> 8) as u8, cal as u8]
68 )?;
69 Ok(())
70 }
71
72 pub fn shunt_voltage(&mut self) -> Result<VoltageUnit, LinuxI2CError> {
73 let mut buf: [u8; 2] = [0; 2];
74 self.calibrate()?;
75 self.device.write(&[RegAddrs::ShuntVoltage as u8])?;
76 self.device.read(&mut buf)?;
77 let val = (i16::from_be_bytes(buf)) as f64;
78 Ok(VoltageUnit::volts(val*0.00001)) }
80
81 pub fn bus_voltage(&mut self) -> Result<VoltageUnit, LinuxI2CError> {
82 let mut buf: [u8; 2] = [0; 2];
83 self.calibrate()?;
84 self.device.write(&[RegAddrs::BusVoltage as u8])?;
85 self.device.read(&mut buf)?;
86 let val = (i16::from_be_bytes(buf) >> 3) as f64;
87 Ok(VoltageUnit::volts(val*0.004)) }
89
90 pub fn power(&mut self) -> Result<PowerUnit, LinuxI2CError> {
91 let mut buf: [u8; 2] = [0; 2];
92 self.calibrate()?;
93 self.device.write(&[RegAddrs::Power as u8])?;
94 self.device.read(&mut buf)?;
95 let val = (i16::from_be_bytes(buf)) as f64;
96 Ok(PowerUnit::watts(val * self.power_lsb.get_val()))
97 }
98
99 pub fn load_current(&mut self) -> Result<CurrentUnit, LinuxI2CError> {
100 let mut buf: [u8; 2] = [0; 2];
101 self.calibrate()?;
102 self.device.write(&[RegAddrs::Current as u8])?;
103 self.device.read(&mut buf)?;
104 let val = ((i16::from_be_bytes(buf)) as f64) * self.current_lsb.get_val();
105 Ok(CurrentUnit::amps(val))
106 }
107}