RobTillaart / INA226

Arduino library for INA226 power sensor
MIT License
54 stars 14 forks source link
ampere arduino power sensor voltage

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

INA226

Arduino library for the INA226 power sensor.

Description

Experimental library for the INA226 power sensor. Not all functionality is tested / investigated.

Read datasheet for details.

==> USE WITH CARE

The INA226 is a voltage, current and power measurement device. A few important maxima, see datasheet, chapter 6.

description max unit notes
bus voltage 36 Volt unclear for how long.
shunt voltage 80 mVolt
current 20 Ampere

0.5.0 Breaking change

Version 0.5.0 introduced a breaking change. You cannot set the pins in begin() any more. This reduces the dependency of processor dependent Wire implementations. The user has to call Wire.begin() and can optionally set the Wire pins before calling begin().

Special characters

Related

I2C

Address

The sensor can have 16 different I2C addresses, which depends on how the A0 and A1 address lines are connected to the SCL, SDA, GND and VCC pins.

See table - from datasheet table 2, page 18.

A1 A0 Addr HEX
GND GND 64 0x40
GND VS 65 0x41
GND SDA 66 0x42
GND SCL 67 0x43
VS GND 68 0x44
VS VS 69 0x45
VS SDA 70 0x46
VS SCL 71 0x47
SDA GND 72 0x48
SDA VS 73 0x49
SDA SDA 74 0x4A
SDA SCL 75 0x4B
SCL GND 76 0x4C
SCL VS 77 0x4D
SCL SDA 78 0x4E
SCL SCL 79 0x4F

Performance

To be elaborated, example sketch available.

(From Datasheet)
The INA226 supports the transmission protocol for fast mode (1 kHz to 400 kHz) and high-speed mode (1 kHz to 2.94 MHz). All data bytes are transmitted most significant byte first.

About Measurements

Calibration with setMaxCurrentShunt() is mandatory to get getCurrent() and getPower() to work.

Some initial tests shows that the readings do not 100% add up. I expect this is caused by fluctuations in my power supply used and more important that the ADC is multiplexed so there is time between the bus voltage measurement and the shunt voltage measurement. If the current has changed a bit these values are not necessary in line.

Did some measurements with a load of 194 ohm and a shunt of 0.002 ohm that is a factor 10e5 Being on the edge of the sensitivity of the ADC measurements of current were up to ~9% too low. Possible cause is that some maths is done in 16 bit so numbers are truncated, not rounded.

(see issue #2) Sensors may have a different shunt resistor than the 0.002 I have. You should always check and verify what is on the shunt and even verify with a DMM that this value is correct. With the calibration function setMaxCurrentShunt() one can just set the actual value and even compensate slightly if readings are structural too low or too high.

I noted that the getPower() function does not always equal getBusVoltage() times getCurrent(). Cause is rounding/trunking maths and time of measurement. You might prefer to multiply those values yourself to get extra digits. Please be aware that more digits is not always more exact (think significant digits).

The example sketch INA226_setMaxCurrentShunt.ino switches between two calibration modes. It shows the INA266 sensor needs time to accommodate to this change. In practice you should call setMaxCurrentShunt() only once in setup().

Also see #30 for another typical deviation problem.

Interface

#include "INA226.h"

Constructor

Core Functions

Note the power and the current are not meaningful without calibrating the sensor. Also the value is not meaningful if there is no shunt connected.

The library has helper functions to convert above output to a more appropriate scale of units.

Helper functions for the milli scale.

Helper functions for the micro scale.

Configuration

Note: The internal conversions runs in the background in the device. If a conversion is finished the measured value is stored in the appropriate register. The last obtained values can always be read from the registers, so they will not block. Result can be that you get the very same value if no new data is available yet. This is especially true if you increase the number of samples. (See also discussion in INA219 issue 11).

Using more samples reduces the noise level, but one will miss the faster changes in voltage or current. Depending on your project needs you can choose one over the other.

As a rule of thumb one could take the time between two I2C reads of a register as an upper limit. This would result in a fresh measurement every time one reads the register. NB it is always possible to average readings fetched from the device in your own code.

enum description value # samples notes
INA226_1_SAMPLE 0 1 default
INA226_4_SAMPLES 1 4
INA226_16_SAMPLES 2 16
INA226_64_SAMPLES 3 64
INA226_128_SAMPLES 4 128
INA226_256_SAMPLES 5 256
INA226_512_SAMPLES 6 512
INA226_1024_SAMPLES 7 1024
enum description BVCT SVCT time notes
INA226_140_us 0 140 us
INA226_204_us 1 204 us
INA226_332_us 2 332 us
INA226_588_us 3 588 us
INA226_1100_us 4 1.1 ms default
INA226_2100_us 5 2.1 ms
INA226_4200_us 6 4.2 ms
INA226_8300_us 7 8.3 ms

Note: times are typical, check datasheet for operational range. (max is ~10% higher)

Note: total conversion time can take up to 1024 * 8.3 ms ~ 10 seconds.

Calibration

See datasheet.

Calibration is mandatory to get getCurrent() and getPower() to work.

To print these values in scientific notation use https://github.com/RobTillaart/printHelpers

About normalization

setMaxCurrentShunt() will round the current_LSB to nearest round value (typical 0.001) by default (normalize == true).

Note: in 0.5.1 the setMaxCurrentShunt() function is rewritten after it showed a bug when normalize flag was set to true. See https://github.com/RobTillaart/INA226/pull/29 for details of the discussion.

Error codes setMaxCurrentShunt

descriptive name error value meaning
INA226_ERR_NONE 0x0000 OK
INA226_ERR_SHUNTVOLTAGE_HIGH 0x8000 maxCurrent * shunt > 80 mV
INA226_ERR_MAXCURRENT_LOW 0x8001 maxCurrent < 0.001
INA226_ERR_SHUNT_LOW 0x8002 shunt < 0.001
INA226_ERR_NORMALIZE_FAILED 0x8003 not possible to normalize.

Operating mode

See datasheet, partially tested.

Mode = 4 is not used, is also a shutdown() unknown if there is a difference with mode == 0.

Descriptive mode functions (convenience wrappers).

Alert functions

See datasheet, not tested yet.

description alert register value a.k.a.
INA226_SHUNT_OVER_VOLTAGE 0x8000 SOL
INA226_SHUNT_UNDER_VOLTAGE 0x4000 SUL
INA226_BUS_OVER_VOLTAGE 0x2000 BOL
INA226_BUS_UNDER_VOLTAGE 0x1000 BUL
INA226_POWER_OVER_LIMIT 0x0800 POL
INA226_CONVERSION_READY 0x0400
description alert flags value
INA226_ALERT_FUNCTION_FLAG 0x0010
INA226_CONVERSION_READY_FLAG 0x0008
INA226_MATH_OVERFLOW_FLAG 0x0004
INA226_ALERT_POLARITY_FLAG 0x0002
INA226_ALERT_LATCH_ENABLE_FLAG 0x0001

The alert line falls when alert is reached.

Meta information

Debugging

Adjusting the range of the INA226

use at own risk In issue #26 a hack is made to scale the INA226 to 300A by using a very small shunt. The library has a minimal limit for the shunt of 0.001 ohm. This limit can be overruled to support other ranges like the one discussed in #26. Overruling can be done by patching the following value in the INA226.h file.

#define INA226_MINIMAL_SHUNT             (0.001)

Be aware that

Future

Must

Should

Could

Won't

Support

If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.

Thank you,