341 lines
12 KiB
Markdown
Raw Normal View History

2021-05-30 14:22:31 +02:00
[![Arduino CI](https://github.com/RobTillaart/INA226/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
2021-11-05 19:39:16 +01:00
[![Arduino-lint](https://github.com/RobTillaart/INA226/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/INA226/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/INA226/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/INA226/actions/workflows/jsoncheck.yml)
2021-05-30 14:22:31 +02:00
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/INA226/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/INA226.svg?maxAge=3600)](https://github.com/RobTillaart/INA226/releases)
# INA226
2021-12-20 08:48:45 +01:00
Arduino library for the INA226 power sensor.
2021-05-30 14:22:31 +02:00
## Description
2023-04-04 12:40:56 +02:00
**Experimental** library for the INA226 power sensor.
2021-05-30 14:22:31 +02:00
Not all functionality is tested / investigated.
2023-04-04 12:40:56 +02:00
Read datasheet for details.
2021-05-30 14:22:31 +02:00
==> **USE WITH CARE**
2022-07-02 10:42:38 +02:00
The INA226 is a voltage, current and power measurement device.
A few important maxima, see datasheet, chapter 6.
2021-05-30 14:22:31 +02:00
2022-02-08 17:18:33 +01:00
| description | max | unit | notes |
|:--------------|------:|-------:|:------|
| bus voltage | 36 | Volt | unclear for how long.
2021-05-30 14:22:31 +02:00
| shunt voltage | 80 | mVolt |
2021-06-22 15:22:35 +02:00
| current | 20 | Ampere |
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Special characters
- Ω == Ohm = ALT-234 (Windows)
- µ == micro = ALT-0181 (Windows)
#### Links
Relates to https://github.com/RobTillaart/INA219
## I2C
#### Address
2022-07-02 10:42:38 +02:00
The sensor can have 16 different I2C addresses,
which depends on how the A0 and A1 address lines
2021-11-05 19:39:16 +01:00
are connected to the SCL, SDA, GND and VCC pins.
2021-05-30 14:22:31 +02:00
See datasheet - table 2 - datasheet.
2023-04-04 12:40:56 +02:00
#### Performance
To be elaborated, example sketch available.
2022-11-14 18:55:30 +01:00
2021-05-30 14:22:31 +02:00
2021-06-22 15:22:35 +02:00
## About Measurements
2022-07-02 10:42:38 +02:00
Calibration with **setMaxCurrentShunt()** is mandatory to get
**getCurrent()** and **getPower()** to work.
2021-06-22 15:22:35 +02:00
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
2022-07-02 10:42:38 +02:00
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.
2021-06-22 15:22:35 +02:00
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.
2021-06-22 20:38:00 +02:00
Possible cause is that some maths is done in 16 bit so numbers are truncated, not rounded.
2021-06-22 15:22:35 +02:00
(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.
2022-02-08 17:18:33 +01:00
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.
2023-04-04 12:40:56 +02:00
Please be aware that more digits is not always more exact (think significant digits).
2021-05-30 14:22:31 +02:00
2021-06-22 20:38:00 +02:00
The example sketch **INA226_setMaxCurrentShunt.ino** switches between two calibration modes.
It shows the **INA266** sensor needs time to accommodate to this change.
2022-02-08 17:18:33 +01:00
In practice you should call **setMaxCurrentShunt()** only once in **setup()**.
2021-05-30 14:22:31 +02:00
## Interface
2023-04-04 12:40:56 +02:00
```cpp
#include "INA226.h"
```
2021-05-30 14:22:31 +02:00
2021-06-22 15:22:35 +02:00
2023-04-04 12:40:56 +02:00
#### Constructor
2021-05-30 14:22:31 +02:00
2022-07-02 10:42:38 +02:00
- **INA226(const uint8_t address, TwoWire \*wire = Wire)** Constructor to set
the address and optional Wire interface.
- **bool begin(const uint8_t sda, const uint8_t scl)** for ESP32 and ESP8266;
initializes the class. Sets I2C pins.
Returns true if the INA226 address is on the I2C bus.
2023-04-04 12:40:56 +02:00
- **bool begin()** UNO ea. initializes the class.
2021-05-30 14:22:31 +02:00
returns true if the INA226 address is on the I2C bus.
- **bool isConnected()** returns true if the INA226 address is on the I2C bus.
2022-07-02 10:42:38 +02:00
- **uint8_t getAddress()** returns the address set in the constructor.
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Core Functions
2021-05-30 14:22:31 +02:00
2022-07-02 10:42:38 +02:00
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.
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
- **float getShuntVoltage()** idem, in volts.
- **float getBusVoltage()** idem. in volts. Max 36 Volt.
2022-02-08 17:18:33 +01:00
- **float getCurrent()** is the current through the shunt in Ampere.
- **float getPower()** is the current x BusVoltage in Watt.
2021-06-22 20:38:00 +02:00
2023-04-04 12:40:56 +02:00
Helper functions for the milli scale.
- **float getBusVoltage_mV()** idem, in milliVolts.
- **float getShuntVoltage_mV()** idem, in milliVolts.
- **float getCurrent_mA()** idem, in milliAmpere.
- **float getPower_mW()** idem, in milliWatt.
Helper functions for the micro scale.
2021-06-22 20:38:00 +02:00
2023-04-04 12:40:56 +02:00
- **float getBusVoltage_mV()** idem, in microVolts.
- **float getShuntVoltage_uV()** idem, in microVolts.
- **float getCurrent_uA()** idem, in microAmpere.
2022-02-08 17:18:33 +01:00
- **float getPower_uW()** idem, in microWatt.
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Configuration
2021-05-30 14:22:31 +02:00
2022-02-08 17:18:33 +01:00
Note: the conversion time runs in the background and if done value is stored in a register.
2023-04-04 12:40:56 +02:00
The core functions read from the registers, so they are not blocked.
They return the same value if no new data is available / ready.
2022-02-08 17:18:33 +01:00
- **void reset()** software power on reset.
This implies calibration with **setMaxCurrentShunt()** needs to be redone.
- **bool setAverage(uint8_t avg = 0)** see table below.
(0 = default ==> 1 read), returns false if parameter > 7.
- **uint8_t getAverage()** returns the value set. See table below.
Note this is not the count of samples.
- **bool setBusVoltageConversionTime(uint8_t bvct = 4)** see table below.
(4 = default ==> 1.1 ms), returns false if parameter > 7.
- **uint8_t getBusVoltageConversionTime()** return the value set.
Note the value returned is not a unit of time.
- **bool setShuntVoltageConversionTime(uint8_t svct = 4)** see table below.
(4 = default ==> 1.1 ms), returns false if parameter > 7.
- **uint8_t getShuntVoltageConversionTime()** return the value set.
Note the value returned is not a unit of time.
2021-05-30 14:22:31 +02:00
| Average | # samples | notes |
|:-------:|----------:|--------:|
| 0 | 1 | default |
| 1 | 4 | |
| 2 | 16 | |
| 3 | 64 | |
| 4 | 128 | |
| 5 | 256 | |
| 6 | 512 | |
| 7 | 1024 | |
| BVCT SVCT | time | notes |
|:---------:|----------:|--------:|
| 0 | 140 us |
| 1 | 204 us |
| 2 | 332 us |
| 3 | 588 us |
| 4 | 1.1 ms | default |
| 5 | 2.1 ms |
| 6 | 4.2 ms |
| 7 | 8.3 ms |
2022-08-28 07:32:00 +02:00
Note: times are typical, check datasheet for operational range.
(max is ~10% higher)
2021-05-30 14:22:31 +02:00
2022-08-28 07:32:00 +02:00
Note: total conversion time can take up to 1024 \* 8.3 ms ~ 10 seconds.
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Calibration
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
See datasheet.
2021-05-30 14:22:31 +02:00
2021-06-22 15:22:35 +02:00
Calibration is mandatory to get **getCurrent()** and **getPower()** to work.
2023-04-04 12:40:56 +02:00
- **int setMaxCurrentShunt(float ampere = 20.0, float ohm = 0.002, bool normalize = true)**
set the calibration register based upon the shunt and the max Ampere.
2022-08-28 07:32:00 +02:00
From this the LSB is derived.
The function may force normalization if underflow is detected.
2023-04-04 12:40:56 +02:00
Returns Error code, see below.
- **bool isCalibrated()** returns true if CurrentLSB has been calculated by **setMaxCurrentShunt()**.
Value should not be zero.
2022-02-08 17:18:33 +01:00
- **float getCurrentLSB()** returns the LSB in Ampere == precision of the calibration.
2023-04-04 12:40:56 +02:00
- **float getCurrentLSB_mA()** returns the LSB in milliAmpere.
- **float getCurrentLSB_uA()** returns the LSB in microAmpere.
- **float getShunt()** returns the value set for the shunt in ohm.
2021-06-22 20:38:00 +02:00
- **float getMaxCurrent()** returns the value for the maxCurrent which can be corrected.
2021-05-30 14:22:31 +02:00
2022-08-28 07:32:00 +02:00
To print these values in scientific notation use https://github.com/RobTillaart/printHelpers
#### About normalization
**setMaxCurrentShunt()** will round the LSB to nearest round value (typical 0.001) by default (normalize == true).
- The user **must** check the return value == 0x000, otherwise the calibration register is **not** set.
- Normalization typically gives smaller steps => improve precision
- Normalization can cause that the maxCurrent passed cannot be reached any more.
Solution is not to normalize if this max range is needed.
#### Error codes setMaxCurrentShunt
2023-04-04 12:40:56 +02:00
| 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
2022-02-08 17:18:33 +01:00
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Operating mode
2021-05-30 14:22:31 +02:00
See datasheet, partially tested.
2023-04-04 12:40:56 +02:00
Mode = 4 is not used, is also a **shutdown()** unknown if there is a difference with mode == 0.
2021-05-30 14:22:31 +02:00
2021-06-22 15:22:35 +02:00
- **bool setMode(uint8_t mode = 7)** mode = 0 .. 7
- **bool shutDown()** mode 0 - not tested yet
- **bool setModeShuntTrigger()** mode 1 - not tested yet - how to trigger to be investigated
2023-04-04 12:40:56 +02:00
- **bool setModeBusTrigger()** mode 2 - not tested yet
- **bool setModeShuntBusTrigger()** mode 3 - not tested yet
2021-06-22 15:22:35 +02:00
- **bool setModeShuntContinuous()** mode 5
- **bool setModeBusContinuous()** mode 6
2023-04-04 12:40:56 +02:00
- **bool setModeShuntBusContinuous()** mode 7 - default.
2021-05-30 14:22:31 +02:00
- **uint8_t getMode()** returns the mode (0..7) set by one of the functions above.
2023-04-04 12:40:56 +02:00
#### Alert functions
2021-05-30 14:22:31 +02:00
See datasheet, not tested yet.
2022-07-02 10:42:38 +02:00
- **void setAlertRegister(uint16_t mask)** by setting the mask
one of five types of over- or underflow can be detected.
2021-12-20 08:48:45 +01:00
Another feature that can be set is the conversion ready flag.
2022-07-02 10:42:38 +02:00
- **uint16_t getAlertFlag()** returns the mask set by **setAlertRegister()**.
2021-05-30 14:22:31 +02:00
- **void setAlertLimit(uint16_t limit)** sets the limit that belongs to the chosen Alert Flag
2022-07-02 10:42:38 +02:00
- **uint16_t getAlertLimit()** returns the limit set by **setAlertLimit()**.
2021-05-30 14:22:31 +02:00
| 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.
2023-04-04 12:40:56 +02:00
#### Meta information
2021-05-30 14:22:31 +02:00
- **uint16_t getManufacturerID()** should return 0x5449
- **uint16_t getDieID()** should return 0x2260
2023-04-04 12:40:56 +02:00
#### debugging
2022-02-08 17:18:33 +01:00
- **uint16_t getRegister(uint8_t reg)** fetch registers directly, for debugging only.
2021-05-30 14:22:31 +02:00
## Operational
2021-06-22 15:22:35 +02:00
See examples..
2021-05-30 14:22:31 +02:00
2021-12-20 08:48:45 +01:00
## Future
2021-05-30 14:22:31 +02:00
2023-04-04 12:40:56 +02:00
#### Must
2022-08-28 07:32:00 +02:00
#### Should
- test different loads (low edge).
- test examples.
- investigate alert functions / interface.
- disconnected load.
2022-02-08 17:18:33 +01:00
- can it be recognized? => current drop?
2022-08-28 07:32:00 +02:00
#### Could
2022-07-02 10:42:38 +02:00
- make defines of "magic" numbers
2022-08-28 07:32:00 +02:00
- const floats (most used only once)
2023-04-04 12:40:56 +02:00
- default address 0x40 ?
2022-08-28 07:32:00 +02:00
#### Won't
- **lastError()** do we need this?
- no
- if **BVCT SVCT** is set to 6 or 7
- does the long timing affects RTOS? ==> yield()
- wait for issue
- expand unit tests possible?
- need virtual device => too much work
- cache configuration ? ==> 2 bytes.
- what is gained? updates are faster. footprint code?
- how often operational?
- 15 times used..
2023-04-04 12:40:56 +02:00
- can the calibration math be optimized?
- integer only?
- less iterations?
- would cause rounding errors
2022-08-28 07:32:00 +02:00
2022-07-16 09:47:39 +02:00
## Resources
2022-08-28 07:32:00 +02:00
2022-07-16 09:47:39 +02:00
- [TI - INA226 Details](https://www.ti.com/product/INA226#params)
- [TI - INA226 datasheet](https://www.ti.com/document-viewer/INA226/datasheet)
2022-08-28 07:32:00 +02:00