2828
2929#include < cstdint>
3030
31+ #include " i2c.h"
32+ #include " firmware/debug/debug_debug.h"
33+
3134namespace sensor {
3235namespace ina219 {
33- inline constexpr uint16_t RANGE_16V = 0x0000 ; // /< 0-16V Range
34- inline constexpr uint16_t RANGE_32V = 0x2000 ; // /< 0-32V Range
36+ inline constexpr uint8_t kI2CAddress = 0x40 ;
37+ namespace reg {
38+ inline constexpr uint8_t kConfig = 0x00 ;
39+ // static constexpr uint8_t SHUNTVOLTAGE = 0x01;
40+ inline constexpr uint8_t kBusvoltage = 0x02 ;
41+ inline constexpr uint8_t kPower = 0x03 ;
42+ inline constexpr uint8_t kCurrent = 0x04 ;
43+ inline constexpr uint8_t kCalibration = 0x05 ;
44+ namespace value {
45+ inline constexpr auto kReadDelayUs = 800 ;
46+ } // namespace value
47+ } // namespace reg
48+ inline constexpr uint16_t kRange16V = 0x0000 ; // /< 0-16V Range
49+ inline constexpr uint16_t kRange32V = 0x2000 ; // /< 0-32V Range
3550
3651inline constexpr uint16_t GAIN_40MV = 0x0000 ; // /< Gain 1, 40mV Range
3752inline constexpr uint16_t GAIN_80MV = 0x0800 ; // /< Gain 2, 80mV Range
3853inline constexpr uint16_t GAIN_160MV = 0x1000 ; // /< Gain 4, 160mV Range
3954inline constexpr uint16_t GAIN_320MV = 0x1800 ; // /< Gain 8, 320mV Range
4055
41- inline constexpr uint16_t BUS_RES_9BIT = 0x0080 ; // /< 9-bit bus res = 0..511
42- inline constexpr uint16_t BUS_RES_10BIT = 0x0100 ; // /< 10-bit bus res = 0..1023
43- inline constexpr uint16_t BUS_RES_11BIT = 0x0200 ; // /< 11-bit bus res = 0..2047
44- inline constexpr uint16_t BUS_RES_12BIT = 0x0400 ; // /< 12-bit bus res = 0..4097
56+ inline constexpr uint16_t kBusRes9Bit = 0x0080 ; // /< 9-bit bus res = 0..511
57+ inline constexpr uint16_t kBusRes10Bit = 0x0100 ; // /< 10-bit bus res = 0..1023
58+ inline constexpr uint16_t kBusRes11Bit = 0x0200 ; // /< 11-bit bus res = 0..2047
59+ inline constexpr uint16_t kBusRes12Bit = 0x0400 ; // /< 12-bit bus res = 0..4097
4560
4661inline constexpr uint16_t SHUNT_RES_9BIT_1S = 0x0000 ; // /< 1 x 9-bit shunt sample
4762inline constexpr uint16_t SHUNT_RES_10BIT_1S = 0x0008 ; // /< 1 x 10-bit shunt sample
@@ -53,23 +68,23 @@ inline constexpr uint16_t SHUNT_RES_12BIT_8S = 0x0058; ///< 8 x 12-bit shunt s
5368inline constexpr uint16_t SHUNT_RES_12BIT_16S = 0x0060 ; // /< 16 x 12-bit shunt samples averaged together
5469inline constexpr uint16_t SHUNT_RES_12BIT_32S = 0x0068 ; // /< 32 x 12-bit shunt samples averaged together
5570inline constexpr uint16_t SHUNT_RES_12BIT_64S = 0x0070 ; // /< 64 x 12-bit shunt samples averaged together
56- inline constexpr uint16_t SHUNT_RES_12BIT_128S = 0x0078 ; // /< 128 x 12-bit shunt samples averaged together
71+ inline constexpr uint16_t kShuntRes12Bit128S = 0x0078 ; // /< 128 x 12-bit shunt samples averaged together
5772
58- inline constexpr uint16_t MODE_POWER_DOWN = 0x0000 ;
59- inline constexpr uint16_t MODE_SHUNT_TRIG = 0x0001 ;
60- inline constexpr uint16_t MODE_BUS_TRIG = 0x0002 ;
61- inline constexpr uint16_t MODE_SHUNT_BUS_TRIG = 0x0003 ;
62- inline constexpr uint16_t MODE_ADC_OFF = 0x0004 ;
63- inline constexpr uint16_t MODE_SHUNT_CONT = 0x0005 ;
64- inline constexpr uint16_t MODE_BUS_CONT = 0x0006 ;
65- inline constexpr uint16_t MODE_SHUNT_BUS_CONT = 0x0007 ;
73+ inline constexpr uint16_t kModePowerDown = 0x0000 ;
74+ inline constexpr uint16_t kModeShuntTrig = 0x0001 ;
75+ inline constexpr uint16_t kModeBusTrig = 0x0002 ;
76+ inline constexpr uint16_t kModeShuntBusTrig = 0x0003 ;
77+ inline constexpr uint16_t kModeAdcOff = 0x0004 ;
78+ inline constexpr uint16_t kModeShuntCont = 0x0005 ;
79+ inline constexpr uint16_t kModeBusCont = 0x0006 ;
80+ inline constexpr uint16_t kModeShuntBusCont = 0x0007 ;
6681
6782struct Config {
68- uint16_t range = RANGE_32V ;
83+ uint16_t range = kRange32V ;
6984 uint16_t gain = GAIN_320MV ;
70- uint16_t bus_res = BUS_RES_12BIT ;
85+ uint16_t bus_res = kBusRes12Bit ;
7186 uint16_t shunt_res = SHUNT_RES_12BIT_1S ;
72- uint16_t mode = MODE_SHUNT_BUS_CONT ;
87+ uint16_t mode = kModeShuntBusCont ;
7388};
7489
7590namespace current {
@@ -89,25 +104,102 @@ inline constexpr int16_t kRangeMax = 64; // W
89104} // namespace power
90105} // namespace ina219
91106
92- class INA219 {
107+ class INA219 : I2c {
93108 public:
94- explicit INA219 (uint8_t address = 0 );
95-
96- void Configure (ina219::Config& config);
97- void Calibrate (float r_shunt_value = 0 .1f , float i_max_expected = 2 .0f );
109+ explicit INA219 (uint8_t address) : I2c(address == 0 ? sensor::ina219::kI2CAddress : address) {
110+ initialized_ = IsConnected ();
111+
112+ if (initialized_) {
113+ sensor::ina219::Config config;
114+ Configure (config);
115+ Calibrate (0 .1f , 2 .0f );
116+ }
117+ }
118+
119+ void Configure (sensor::ina219::Config& config) {
120+ switch (config.range ) {
121+ case sensor::ina219::kRange32V :
122+ info_.v_bus_max = 32 .0f ;
123+ break ;
124+ case sensor::ina219::kRange16V :
125+ info_.v_bus_max = 16 .0f ;
126+ break ;
127+ }
128+
129+ switch (config.gain ) {
130+ case sensor::ina219::GAIN_320MV :
131+ info_.v_shunt_max = 0 .32f ;
132+ break ;
133+ case sensor::ina219::GAIN_160MV :
134+ info_.v_shunt_max = 0 .16f ;
135+ break ;
136+ case sensor::ina219::GAIN_80MV :
137+ info_.v_shunt_max = 0 .08f ;
138+ break ;
139+ case sensor::ina219::GAIN_40MV :
140+ info_.v_shunt_max = 0 .04f ;
141+ break ;
142+ }
143+
144+ const uint16_t kConfig = config.range | config.gain | config.bus_res | config.shunt_res | config.mode ;
145+
146+ DEBUG_PRINTF (" kConfig=%x" , kConfig );
147+
148+ i2c::WriteReg (sensor::ina219::reg::kConfig , kConfig );
149+ }
150+
151+ void Calibrate (float r_shunt_value, float i_max_expected) {
152+ const float kMinimumLsb = i_max_expected / 32767 ;
153+
154+ info_.r_shunt = r_shunt_value;
155+
156+ info_.current_lsb = (static_cast <uint16_t >(kMinimumLsb * 100000000 ));
157+ info_.current_lsb /= 100000000 ;
158+ info_.current_lsb /= 0 .0001f ;
159+ info_.current_lsb = CeilingPos (info_.current_lsb );
160+ info_.current_lsb *= 0 .0001f ;
161+
162+ info_.power_lsb = info_.current_lsb * 20 ;
163+
164+ const auto kCalibrationValue = static_cast <uint16_t >((0 .04096f / (info_.current_lsb * info_.r_shunt )));
165+
166+ DEBUG_PRINTF (" kCalibrationValue=%x" , kCalibrationValue );
167+
168+ i2c::WriteReg (sensor::ina219::reg::kCalibration , kCalibrationValue );
169+ }
170+
171+ float GetShuntCurrent () {
172+ const float kValue = ReadRegister16DelayUs (sensor::ina219::reg::kCurrent , sensor::ina219::reg::value::kReadDelayUs ) * info_.current_lsb ;
173+ return kValue ;
174+ }
175+
176+ float GetBusVoltage () { return GetBusVoltageRaw () * 0 .001f ; }
177+
178+ float GetBusPower () {
179+ const float kValue = ReadRegister16DelayUs (sensor::ina219::reg::kPower , sensor::ina219::reg::value::kReadDelayUs ) * info_.power_lsb ;
180+ return kValue ;
181+ }
182+
183+ bool Initialize () { return initialized_; }
98184
99- bool Initialize () { return initialized_; }
185+ private:
186+ int16_t GetBusVoltageRaw () {
187+ auto voltage = ReadRegister16DelayUs (sensor::ina219::reg::kBusvoltage , sensor::ina219::reg::value::kReadDelayUs );
188+ voltage = static_cast <uint16_t >(voltage >> 3 );
100189
101- float GetShuntCurrent ();
102- float GetBusVoltage ();
103- float GetBusPower ();
190+ return static_cast <int16_t >(voltage * 4 );
191+ }
104192
105- private:
106- int16_t GetBusVoltageRaw ();
193+ float CeilingPos (float f) {
194+ const auto kI = static_cast <int >(f);
195+ if (f == static_cast <float >(kI )) {
196+ return static_cast <float >(kI );
197+ }
198+ return static_cast <float >(kI + 1 );
199+ }
107200
108201 private:
109- uint8_t address_{0 };
110- bool initialized_{false };
202+ bool initialized_{false };
111203
112204 struct Info {
113205 float current_lsb;
0 commit comments