1 /**************************************************************************/
4 @author K. Townsend (microBuilder.eu)
6 @brief Driver for the TI INA219 current/power monitor
10 The INA219 is an I2C-based current/power monitor that monitors the
11 voltage drop across a shunt resistor, as well as the supply voltage.
19 int16_t current_mA = 0;
21 int16_t busvoltage = 0;
22 int16_t shuntvoltage = 0;
23 int16_t loadVoltage = 0;
27 shuntvoltage = ina219GetShuntVoltage();
28 busvoltage = ina219GetBusVoltage();
29 power = ina219GetPower();
30 current = ina219GetCurrent();
31 power_mW = ina219GetPower_mW();
32 current_mA = ina219GetCurrent_mA();
33 loadVoltage = busvoltage + (shuntvoltage / 100);
34 printf("%-15s %6d = %d.%dmV (%duV) \r\n", "Shunt Voltage:", shuntvoltage, shuntvoltage / 100, shuntvoltage % 100, shuntvoltage * 10);
35 printf("%-15s %6d = %d.%dV \r\n", "Bus Voltage:", busvoltage, busvoltage / 1000, busvoltage % 1000);
36 printf("%-15s %6d = %d.%dV \r\n", "Load Voltage:", loadVoltage, loadVoltage / 1000, loadVoltage % 1000);
37 printf("%-15s %6d = %dmW \r\n", "Power:", power, power_mW);
38 printf("%-15s %6d = %dmA \r\n", "Current:", current, current_mA);
46 Software License Agreement (BSD License)
48 Copyright (c) 2012 Kevin Townsend
51 Redistribution and use in source and binary forms, with or without
52 modification, are permitted provided that the following conditions are met:
53 1. Redistributions of source code must retain the above copyright
54 notice, this list of conditions and the following disclaimer.
55 2. Redistributions in binary form must reproduce the above copyright
56 notice, this list of conditions and the following disclaimer in the
57 documentation and/or other materials provided with the distribution.
58 3. Neither the name of the copyright holders nor the
59 names of its contributors may be used to endorse or promote products
60 derived from this software without specific prior written permission.
62 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
63 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
64 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
65 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
66 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
67 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
68 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
69 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
70 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
71 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 /**************************************************************************/
75 #include "core/systick/systick.h"
77 extern volatile uint8_t I2CMasterBuffer
[I2C_BUFSIZE
];
78 extern volatile uint8_t I2CSlaveBuffer
[I2C_BUFSIZE
];
80 // The following multipliers are used to convert raw current and power
81 // values to mA and mW, taking into account the current config settings
82 uint32_t ina219_currentDivider_mA
= 0;
83 uint32_t ina219_powerDivider_mW
= 0;
85 /**************************************************************************/
87 @brief Sends a single command byte over I2C
89 /**************************************************************************/
90 static void ina219WriteRegister (uint8_t reg
, uint16_t value
)
92 // Clear write buffers
94 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
96 I2CMasterBuffer
[i
] = 0x00;
101 I2CMasterBuffer
[0] = INA219_ADDRESS
; // I2C device address
102 I2CMasterBuffer
[1] = reg
; // Register
103 I2CMasterBuffer
[2] = value
>> 8; // Upper 8-bits
104 I2CMasterBuffer
[3] = value
& 0xFF; // Lower 8-bits
108 /**************************************************************************/
110 @brief Reads a 16 bit values over I2C
112 /**************************************************************************/
113 static void ina219Read16(uint8_t reg
, uint16_t *value
)
115 // Clear write buffers
117 for ( i
= 0; i
< I2C_BUFSIZE
; i
++ )
119 I2CMasterBuffer
[i
] = 0x00;
124 I2CMasterBuffer
[0] = INA219_ADDRESS
; // I2C device address
125 I2CMasterBuffer
[1] = reg
; // Command register
126 // Append address w/read bit
127 I2CMasterBuffer
[2] = INA219_ADDRESS
| INA219_READ
;
130 // Shift values to create properly formed integer
131 *value
= ((I2CSlaveBuffer
[0] << 8) | I2CSlaveBuffer
[1]);
134 /**************************************************************************/
136 @brief Configures to INA219 to be able to measure up to 32V and 2A
137 of current. Each unit of current corresponds to 100uA, and
138 each unit of power corresponds to 2mW. Counter overflow
141 @note These calculations assume a 0.1 ohm resistor is present
143 /**************************************************************************/
144 void ina219SetCalibration_32V_2A(void)
146 // By default we use a pretty huge range for the input voltage,
147 // which probably isn't the most appropriate choice for system
148 // that don't use a lot of power. But all of the calculations
149 // are shown below if you want to change the settings. You will
150 // also need to change any relevant register settings, such as
151 // setting the VBUS_MAX to 16V instead of 32V, etc.
153 // VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
154 // VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
155 // RSHUNT = 0.1 (Resistor value in ohms)
157 // 1. Determine max possible current
158 // MaxPossible_I = VSHUNT_MAX / RSHUNT
159 // MaxPossible_I = 3.2A
161 // 2. Determine max expected current
162 // MaxExpected_I = 2.0A
164 // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
165 // MinimumLSB = MaxExpected_I/32767
166 // MinimumLSB = 0.000061 (61µA per bit)
167 // MaximumLSB = MaxExpected_I/4096
168 // MaximumLSB = 0,000488 (488µA per bit)
170 // 4. Choose an LSB between the min and max values
171 // (Preferrably a roundish number close to MinLSB)
172 // CurrentLSB = 0.0001 (100µA per bit)
174 // 5. Compute the calibration register
175 // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
176 // Cal = 4096 (0x1000)
178 // 6. Calculate the power LSB
179 // PowerLSB = 20 * CurrentLSB
180 // PowerLSB = 0.002 (2mW per bit)
182 // 7. Compute the maximum current and shunt voltage values before overflow
184 // Max_Current = Current_LSB * 32767
185 // Max_Current = 3.2767A before overflow
187 // If Max_Current > Max_Possible_I then
188 // Max_Current_Before_Overflow = MaxPossible_I
190 // Max_Current_Before_Overflow = Max_Current
193 // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
194 // Max_ShuntVoltage = 0.32V
196 // If Max_ShuntVoltage >= VSHUNT_MAX
197 // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
199 // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
202 // 8. Computer the Maximum Power
203 // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
204 // MaximumPower = 3.2 * 32V
205 // MaximumPower = 102.4W
207 // Set multipliers to convert raw current/power values
208 ina219_currentDivider_mA
= 10; // Current LSB = 100uA per bit (1000/100 = 10)
209 ina219_powerDivider_mW
= 2; // Power LSB = 1mW per bit (2/1)
211 // Set Calibration register to 'Cal' calculated above
212 ina219WriteRegister(INA219_REG_CALIBRATION
, 0x1000);
214 // Set Config register to take into account the settings above
215 uint16_t config
= INA219_CONFIG_BVOLTAGERANGE_32V
|
216 INA219_CONFIG_GAIN_8_320MV
|
217 INA219_CONFIG_BADCRES_12BIT
|
218 INA219_CONFIG_SADCRES_12BIT_1S_532US
|
219 INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS
;
220 ina219WriteRegister(INA219_REG_CONFIG
, config
);
223 /**************************************************************************/
225 @brief Configures to INA219 to be able to measure up to 32V and 1A
226 of current. Each unit of current corresponds to 40uA, and each
227 unit of power corresponds to 800µW. Counter overflow occurs at
230 @note These calculations assume a 0.1 ohm resistor is present
232 /**************************************************************************/
233 void ina219SetCalibration_32V_1A(void)
235 // By default we use a pretty huge range for the input voltage,
236 // which probably isn't the most appropriate choice for system
237 // that don't use a lot of power. But all of the calculations
238 // are shown below if you want to change the settings. You will
239 // also need to change any relevant register settings, such as
240 // setting the VBUS_MAX to 16V instead of 32V, etc.
242 // VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
243 // VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
244 // RSHUNT = 0.1 (Resistor value in ohms)
246 // 1. Determine max possible current
247 // MaxPossible_I = VSHUNT_MAX / RSHUNT
248 // MaxPossible_I = 3.2A
250 // 2. Determine max expected current
251 // MaxExpected_I = 1.0A
253 // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
254 // MinimumLSB = MaxExpected_I/32767
255 // MinimumLSB = 0.0000305 (30.5µA per bit)
256 // MaximumLSB = MaxExpected_I/4096
257 // MaximumLSB = 0.000244 (244µA per bit)
259 // 4. Choose an LSB between the min and max values
260 // (Preferrably a roundish number close to MinLSB)
261 // CurrentLSB = 0.0000400 (40µA per bit)
263 // 5. Compute the calibration register
264 // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
265 // Cal = 10240 (0x2800)
267 // 6. Calculate the power LSB
268 // PowerLSB = 20 * CurrentLSB
269 // PowerLSB = 0.0008 (800µW per bit)
271 // 7. Compute the maximum current and shunt voltage values before overflow
273 // Max_Current = Current_LSB * 32767
274 // Max_Current = 1.31068A before overflow
276 // If Max_Current > Max_Possible_I then
277 // Max_Current_Before_Overflow = MaxPossible_I
279 // Max_Current_Before_Overflow = Max_Current
282 // ... In this case, we're good though since Max_Current is less than MaxPossible_I
284 // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
285 // Max_ShuntVoltage = 0.131068V
287 // If Max_ShuntVoltage >= VSHUNT_MAX
288 // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
290 // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
293 // 8. Computer the Maximum Power
294 // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
295 // MaximumPower = 1.31068 * 32V
296 // MaximumPower = 41.94176W
298 // Set multipliers to convert raw current/power values
299 ina219_currentDivider_mA
= 25; // Current LSB = 40uA per bit (1000/40 = 25)
300 ina219_powerDivider_mW
= 1; // Power LSB = 800µW per bit
302 // Set Calibration register to 'Cal' calculated above
303 ina219WriteRegister(INA219_REG_CALIBRATION
, 0x2800);
305 // Set Config register to take into account the settings above
306 uint16_t config
= INA219_CONFIG_BVOLTAGERANGE_32V
|
307 INA219_CONFIG_GAIN_8_320MV
|
308 INA219_CONFIG_BADCRES_12BIT
|
309 INA219_CONFIG_SADCRES_12BIT_1S_532US
|
310 INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS
;
311 ina219WriteRegister(INA219_REG_CONFIG
, config
);
314 /**************************************************************************/
316 @brief Configures to INA219 to be able to measure up to 16V and 500mA
317 of current. Each unit of current corresponds to 25uA, and each
318 unit of power corresponds to 500µW. Counter overflow occurs at
321 @note These calculations assume a 0.1 ohm resistor is present
323 /**************************************************************************/
324 void ina219SetCalibration_16V_500mA(void)
327 // VSHUNT_MAX = 0.08 (Assumes Gain 2, 80mV, can also be 0.32, 0.16, 0.04)
328 // RSHUNT = 0.1 (Resistor value in ohms)
330 // 1. Determine max possible current
331 // MaxPossible_I = VSHUNT_MAX / RSHUNT
332 // MaxPossible_I = 0.8A
334 // 2. Determine max expected current
335 // MaxExpected_I = 0.5A
337 // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
338 // MinimumLSB = MaxExpected_I/32767
339 // MinimumLSB = 0.0000153 (15.3µA per bit)
340 // MaximumLSB = MaxExpected_I/4096
341 // MaximumLSB = 0.0001221 (122µA per bit)
343 // 4. Choose an LSB between the min and max values
344 // (Preferrably a roundish number close to MinLSB)
345 // CurrentLSB = 0.0000250 (25µA per bit)
347 // 5. Compute the calibration register
348 // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
349 // Cal = 16384 (0x4000)
351 // 6. Calculate the power LSB
352 // PowerLSB = 20 * CurrentLSB
353 // PowerLSB = 0.0005 (500µW per bit)
355 // 7. Compute the maximum current and shunt voltage values before overflow
357 // Max_Current = Current_LSB * 32767
358 // Max_Current = 0.819175 (819 mA before overflow)
360 // If Max_Current > Max_Possible_I then
361 // Max_Current_Before_Overflow = MaxPossible_I
363 // Max_Current_Before_Overflow = Max_Current
366 // Max_Current_Before_Overflow = 0.8A
368 // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
369 // Max_ShuntVoltage = 0.8 * 0.1
370 // Max_ShuntVoltage = 0.08V
372 // If Max_ShuntVoltage >= VSHUNT_MAX
373 // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
375 // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
378 // 8. Computer the Maximum Power
379 // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
380 // MaximumPower = 0.8 * 16V
381 // MaximumPower = 12.8W
383 // Set multipliers to convert raw current/power values
384 ina219_currentDivider_mA
= 40; // Current LSB = 25uA per bit (1000/25 = 40)
385 ina219_powerDivider_mW
= 1; // Power LSB = 500µW per bit
387 // Set Calibration register to 'Cal' calculated above
388 ina219WriteRegister(INA219_REG_CALIBRATION
, 0x4000);
390 // Set Config register to take into account the settings above
391 uint16_t config
= INA219_CONFIG_BVOLTAGERANGE_16V
|
392 INA219_CONFIG_GAIN_2_80MV
|
393 INA219_CONFIG_BADCRES_12BIT
|
394 INA219_CONFIG_SADCRES_12BIT_1S_532US
|
395 INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS
;
396 ina219WriteRegister(INA219_REG_CONFIG
, config
);
399 /**************************************************************************/
401 @brief Configures to INA219 to be able to measure up to 16V and 200mA
402 of current. Each unit of current corresponds to 10uA, and each
403 unit of power corresponds to 200µW. Counter overflow occurs at
406 @note These calculations assume a 0.1 ohm resistor is present
408 /**************************************************************************/
409 void ina219SetCalibration_16V_200mA(void)
412 // VSHUNT_MAX = 0.04 (Assumes Gain 1, 40mV, can also be 0.32, 0.16, 0.08)
413 // RSHUNT = 0.1 (Resistor value in ohms)
415 // 1. Determine max possible current
416 // MaxPossible_I = VSHUNT_MAX / RSHUNT
417 // MaxPossible_I = 0.4A
419 // 2. Determine max expected current
420 // MaxExpected_I = 0.2A
422 // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
423 // MinimumLSB = MaxExpected_I/32767
424 // MinimumLSB = 0.000006104 (6.104µA per bit)
425 // MaximumLSB = MaxExpected_I/4096
426 // MaximumLSB = 0,000048828 (48.82µA per bit)
428 // 4. Choose an LSB between the min and max values
429 // CurrentLSB = 0.000010 (10µA per bit)
431 // 5. Compute the calibration register
432 // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
433 // Cal = 40960 (0xA000)
435 // 6. Calculate the power LSB
436 // PowerLSB = 20 * CurrentLSB
437 // PowerLSB = 0.0002 (200µW per bit)
439 // 7. Compute the maximum current and shunt voltage values before overflow
441 // Max_Current = Current_LSB * 32767
442 // Max_Current = 0.32767 (328 mA before overflow)
444 // If Max_Current > Max_Possible_I then
445 // Max_Current_Before_Overflow = MaxPossible_I
447 // Max_Current_Before_Overflow = Max_Current
450 // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
451 // Max_ShuntVoltage = 0.032767V
453 // If Max_ShuntVoltage >= VSHUNT_MAX
454 // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
456 // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
459 // 8. Computer the Maximum Power
460 // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
461 // MaximumPower = 0.32767 * 16V
462 // MaximumPower = 5.24W
464 // Set multipliers to convert raw current/power values
465 ina219_currentDivider_mA
= 100; // Current LSB = 10uA per bit (1000/10 = 100)
466 ina219_powerDivider_mW
= 1; // Power LSB = 200µW per bit
468 // Set Calibration register to 'Cal' calculated above
469 ina219WriteRegister(INA219_REG_CALIBRATION
, 0xA000);
471 // Set Config register to take into account the settings above
472 uint16_t config
= INA219_CONFIG_BVOLTAGERANGE_16V
|
473 INA219_CONFIG_GAIN_1_40MV
|
474 INA219_CONFIG_BADCRES_12BIT
|
475 INA219_CONFIG_SADCRES_12BIT_1S_532US
|
476 INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS
;
477 ina219WriteRegister(INA219_REG_CONFIG
, config
);
480 /**************************************************************************/
482 @brief Initialises the I2C block
484 /**************************************************************************/
485 void ina219Init(void)
487 // Reset INA219 (set to default values)
488 ina219WriteRegister(INA219_REG_CONFIG
, INA219_CONFIG_RESET
);
490 // Setup chip for 32V and 2A by default
491 ina219SetCalibration_32V_2A();
494 /**************************************************************************/
496 @brief Gets the shunt voltage (16-bit signed integer, so +-32767)
498 /**************************************************************************/
499 int16_t ina219GetShuntVoltage(void)
502 ina219Read16(INA219_REG_SHUNTVOLTAGE
, &value
);
506 /**************************************************************************/
508 @brief Gets the shunt voltage (16-bit signed integer, so +-32767)
510 /**************************************************************************/
511 int16_t ina219GetBusVoltage(void)
514 ina219Read16(INA219_REG_BUSVOLTAGE
, &value
);
515 // Shift to the right 3 to drop CNVR and OVF and then multiply by LSB
516 return (value
>> 3) * 4;
519 /**************************************************************************/
521 @brief Gets the raw power value (16-bit signed integer, so +-32767)
523 /**************************************************************************/
524 int16_t ina219GetPower(void)
527 ina219Read16(INA219_REG_POWER
, &value
);
531 /**************************************************************************/
533 @brief Gets the power value in mW, taking into account the config
534 settings and power LSB
536 /**************************************************************************/
537 int16_t ina219GetPower_mW(void)
540 ina219Read16(INA219_REG_POWER
, &value
);
541 return value
/ ina219_powerDivider_mW
;
544 /**************************************************************************/
546 @brief Gets the raw current value (16-bit signed integer, so +-32767)
548 /**************************************************************************/
549 int16_t ina219GetCurrent(void)
552 ina219Read16(INA219_REG_CURRENT
, &value
);
556 /**************************************************************************/
558 @brief Gets the current value in mA, taking into account the
559 config settings and current LSB
561 /**************************************************************************/
562 int16_t ina219GetCurrent_mA(void)
565 ina219Read16(INA219_REG_CURRENT
, &value
);
566 return value
/ ina219_currentDivider_mA
;