{"id":13893978,"url":"https://github.com/RobTillaart/INA219","last_synced_at":"2025-07-17T08:31:46.755Z","repository":{"id":82983907,"uuid":"533718710","full_name":"RobTillaart/INA219","owner":"RobTillaart","description":"Arduino library for INA219 voltage, current and power sensor","archived":false,"fork":false,"pushed_at":"2024-08-14T15:51:59.000Z","size":46,"stargazers_count":22,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-19T06:33:08.259Z","etag":null,"topics":["arduino","current","power","sensor"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobTillaart.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"RobTillaart","custom":"https://www.paypal.me/robtillaart"}},"created_at":"2022-09-07T10:36:29.000Z","updated_at":"2024-10-21T17:22:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"ccbe106b-eb17-4942-b36b-1fe5ed19dc8a","html_url":"https://github.com/RobTillaart/INA219","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FINA219","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FINA219/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FINA219/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobTillaart%2FINA219/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobTillaart","download_url":"https://codeload.github.com/RobTillaart/INA219/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226243893,"owners_count":17594452,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","current","power","sensor"],"created_at":"2024-08-06T18:01:21.081Z","updated_at":"2025-07-17T08:31:46.749Z","avatar_url":"https://github.com/RobTillaart.png","language":"C++","funding_links":["https://github.com/sponsors/RobTillaart","https://www.paypal.me/robtillaart"],"categories":["C++"],"sub_categories":[],"readme":"\n[![Arduino CI](https://github.com/RobTillaart/INA219/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)\n[![Arduino-lint](https://github.com/RobTillaart/INA219/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/INA219/actions/workflows/arduino-lint.yml)\n[![JSON check](https://github.com/RobTillaart/INA219/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/INA219/actions/workflows/jsoncheck.yml)\n[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/INA219.svg)](https://github.com/RobTillaart/INA219/issues)\n\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/INA219/blob/master/LICENSE)\n[![GitHub release](https://img.shields.io/github/release/RobTillaart/INA219.svg?maxAge=3600)](https://github.com/RobTillaart/INA219/releases)\n[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/INA219.svg)](https://registry.platformio.org/libraries/robtillaart/INA219)\n\n\n# INA219\n\nArduino library for INA219 voltage, current and power sensor.\n\n\n## Description\n\n**Experimental** library for the INA219 power sensor.\nMinimal tested, so usage remarks and comments are welcome.\n\nRead datasheet for details.\n\n**USE WITH CARE**\n\nThe INA219 is a voltage, current and power measurement device. \nA few important maxima, see datasheet, chapter 7, esp 7.5\n\n|   description   |  max  |   unit  |  notes  |\n|:----------------|------:|--------:|:--------|\n|  bus voltage    |  32   |  Volt   |  depends on BRNG setting\n|  shunt voltage  |  320  |  mVolt  |  depends on PGA setting\n\n\n\n#### 0.4.0 Breaking change\n\nVersion 0.4.0 fixed negative values for **getShuntVoltage()**.\nOlder versions are obsolete now.\n\n\n#### 0.2.0 Breaking change\n\nVersion 0.2.0 introduced a breaking change.\nYou cannot set the pins in **begin()** any more.\nThis reduces the dependency of processor dependent Wire implementations.\nThe user has to call **Wire.begin()** and can optionally set the Wire pins \nbefore calling **begin()**.\n\n\n#### Special characters\n\n- Ω == Ohm = ALT-234 (Windows)\n- µ == micro = ALT-0181 (Windows)\n\n\n#### Related\n\n- https://www.ti.com/product/INA219#tech-docs\n- https://www.ti.com/product/INA219#params\n- https://www.ti.com/document-viewer/INA219/datasheet\n- https://github.com/RobTillaart/INA219  26 Volt, I2C, 12 bit\n- https://github.com/RobTillaart/INA226  36 Volt, I2C, 16 bit\n- https://github.com/RobTillaart/INA228  85 Volt, I2C, 20 bit\n- https://github.com/RobTillaart/INA236  48 Volt, I2C, 16 bit\n- https://github.com/RobTillaart/INA239  85 Volt, SPI, 16 bit\n- https://github.com/RobTillaart/INA260  36 Volt, SPI, 16 bit\n- https://github.com/RobTillaart/INA3221_RT  26 Volt, I2C, 13 bits (3 channel)\n- https://www.adafruit.com/product/5832\n- https://www.mateksys.com/?portfolio=i2c-ina-bm\n- https://github.com/RobTillaart/printHelpers  (for scientific notation)\n\n\n\n## I2C\n\n#### Address\n\nThe sensor can be configured to use 1 of 16 I2C addresses between 0x40 and 0x4F.\nThe address depends on how the A0 and A1 address lines are connected to the SCL, SDA, GND and VCC pins.\n(datasheet chapter 8.5.5.1 Serial Bus Address)\n\n\n#### Performance\n\nDatasheet states it supports 1 KHz .. 2.56 MHz.\nNote: higher speeds and longer wires need smaller pull up resistors.\n\nSome timings in micros for **INA.getMode()** on an Arduino UNO.\nThis is just one readRegister call, similar to most functions.\n\nAbove 600 KHz there is little performance gain.\n\n|  speed  |  time  |  speed  |  time  |  speed  |  time  |  speed  |  time  |\n|:-------:|:------:|:-------:|:------:|:-------:|:------:|:-------:|:------:|\n|  100000 |   560  |  150000 |   396  |  200000 |   320  |  250000 |   272  |\n|  300000 |   232  |  350000 |   208  |  400000 |   196  |  450000 |   176  |\n|  500000 |   172  |  550000 |   164  |  600000 |   152  |  650000 |   152  |\n|  700000 |   144  |  750000 |   144  |  800000 |   140  |         |        |\n\nuse **INA219_test_I2C.ino**\n\n\n## Interface\n\n```cpp\n#include \"INA219.h\"\n```\n\n\n#### Constructor\n\n- **INA219(const uint8_t address, TwoWire \\*wire = Wire)** Constructor to set\nthe address and optional Wire interface.\n- **bool begin()** initializes the class.\nReturns true if the INA219 address (set in the constructor) is on the I2C bus.\n- **bool isConnected()** Returns true if the INA219 address (set in the constructor) is on the I2C bus.\n- **uint8_t getAddress()** Returns the INA219 address set in the constructor.\n\n\n#### Core Functions\n\nNote the power and the current are not meaningful without calibrating the sensor. \nAlso the value is not meaningful if there is no shunt connected.\n\n- **float getShuntVoltage()** idem, in volts.\n- **float getBusVoltage()** idem. in volts. Max 32 Volt.\n- **float getCurrent()** returns the current through the shunt in Ampere.\n- **float getPower()** returns the current x BusVoltage in Watt.\n\nThe library has helper functions to convert above output to a more appropriate scale of units.\n\nHelper functions for the milli scale.\n\n- **float getBusVoltage_mV()** idem, in milliVolts.\nNote: returns -100 if the math overflow bit is set.\n- **float getShuntVoltage_mV()** idem, in milliVolts.\n- **float getCurrent_mA()** idem, in milliAmpere.\n- **float getPower_mW()** idem, in milliWatt.\n\nHelper functions for the micro scale.\n\n- **float getBusVoltage_uV()** idem, in microVolts.\n- **float getShuntVoltage_uV()** idem, in microVolts.\n- **float getCurrent_uA()** idem, in microAmpere.\n- **float getPower_uW()** idem, in microWatt.\n\n\n##### Indicator flags\n\n- **bool getMathOverflowFlag()** internal math overflow.\n- **bool getConversionFlag()** conversion is ready.\nEspecially useful in non-continuous modi.\n\n\n#### Configuration\n\n- **bool reset()** software power on reset. \nThis implies that calibration with **setMaxCurrentShunt()** needs to be redone.\nSee section below.\nReturns false if it could not write settings to device.\n- **bool setBusVoltageRange(uint8_t voltage = 16)** set to 16 or 32.\nValues \u003c= 16 map to 16 and values between 16 and 32 map to 32.\nReturns false if voltage is above 32.\nReturns false if it could not write settings to device.\n- **uint8_t getBusVoltageRange()** returns 16 or 32. (Volts)\n- **bool setGain(uint8_t factor)** factor = 1, 2, 4, 8 (default).\nDetermines the shunt voltage range. 40, 80, 160 or 320 mV. \nReturns false if factor is not a valid value.\nReturns false if it could not write settings to device.\n- **uint8_t getGain()** returns set factor.\n- **int getMaxShuntVoltage()** returns 40, 80, 160 or 320 (mV).\n320 is the sensors default.\n\n\n#### Configuration BUS and SHUNT\n\n**Note:**\nThe internal conversions runs in the background in the device.\nIf a conversion is finished the measured value is stored in the appropriate register. \nThe last obtained values can always be read from the registers, so they will not block.\nResult can be that you get the very same value if no new data is available yet.\nThis is especially true if you increase the number of samples.\n(See also discussion in INA219 issue 11).\n\nUsing more samples reduces the noise level, but one will miss the faster \nchanges in voltage or current.\nDepending on your project needs you can choose one over the other.\n\nAs a rule of thumb one could take the time between two I2C reads of \na register as an upper limit.\nThis would result in a fresh measurement every time one reads the register. \nNB it is always possible to average readings fetched from the device\nin your own code.\n\nUse one of these three so set **bus** resolution and sampling.\n\n- **bool setBusResolution(uint8_t bits)** bits = 9..12, always 1 sample.\nReturns false if parameter out of range.\nReturns false if it could not write settings to device.\n- **bool setBusSamples(uint8_t value)** value = 0..7 =\u003e maps to 2^value samples.\nAlways 12 bits.\nReturns false if parameter out of range.\nReturns false if it could not write settings to device.\n- **bool setBusADC(uint8_t mask = 0x03)** see table below. \nCheck datasheet for all details.\nReturns false if parameter out of range (mask \u003e 0x0F).\nReturns false if it could not write settings to device.\n- **uint8_t getBusADC()** returns mask, see table below.\n\n\nUse one of these three so set **shunt** resolution and sampling.\n\n- **bool setShuntResolution(uint8_t bits)** bits = 9..12, always 1 sample.\nReturns false if parameter out of range.\nReturns false if it could not write settings to device.\n- **bool setShuntSamples(uint8_t value)** value = 0..7 =\u003e maps to 2^value samples.\nAlways 12 bits.\nReturns false if parameter out of range.\nReturns false if it could not write settings to device.\n- **bool setShuntADC(uint8_t mask = 0x03)** see table below. \nCheck datasheet for all details.\nReturns false if parameter out of range (mask \u003e 0x0F).\nReturns false if it could not write settings to device.\n- **uint8_t getShuntADC()** returns mask, see table below.\n\n\n#### Resolution samples table\n\nmask = both resolution + averaging multiple samples.\nminus - == don't care\n\n\n|  bit mask  |  value  |  resolution  |  samples      | conversion time |\n|:----------:|:-------:|:-------------|:--------------|:---------------:|\n|    0-00    |  0 / 4  |     9 bit    |    1 sample   |      84 μs      |\n|    0-01    |  1 / 5  |    10 bit    |    1 sample   |     148 μs      |\n|    0-10    |  2 / 6  |    11 bit    |    1 sample   |     276 μs      |\n|    0-11    |  3 / 7  |    12 bit    |    1 sample   |     532 μs      |\n|            |         |              |               |                 |\n|    1000    |    8    |    12 bit    |    1 sample   |     532 μs      |\n|    1001    |    9    |    12 bit    |    2 samples  |    1.06 ms      |\n|    1010    |   10    |    12 bit    |    4 samples  |    2.13 ms      |\n|    1011    |   11    |    12 bit    |    8 samples  |    4.26 ms      |\n|    1100    |   12    |    12 bit    |   16 samples  |    8.51 ms      |\n|    1101    |   13    |    12 bit    |   32 samples  |   17.02 ms      |\n|    1110    |   14    |    12 bit    |   64 samples  |   34.05 ms      |\n|    1111    |   15    |    12 bit    |  128 samples  |   68.10 ms      |\n\n- note that a new value set can substantially increase the conversion time.\n- note that you cannot set e.g. 9 bits and 16 samples.\n- note that there are 3 ways to set 12 bits 1 sample.\n\n\n#### Operating mode\n\nSee details datasheet,\n\n- **bool setMode(uint8_t mode = 7)** mode = 0..7.\nThe default value 7 == ShuntBusContinuous mode.\nReturns false if parameter out of range (mode \u003e 7).\nReturns false if it could not write settings to device.\n- **uint8_t getMode()** returns the mode (0..7) set.\n\nDescriptive mode functions (convenience wrappers around **setMode()**).\n\n- **bool shutDown()** mode 0\n- **bool setModeShuntTrigger()** mode 1 - how to trigger to be investigated.\n- **bool setModeBusTrigger()** mode 2\n- **bool setModeShuntBusTrigger()** mode 3\n- **bool setModeADCOff()** mode 4\n- **bool setModeShuntContinuous()** mode 5\n- **bool setModeBusContinuous()** mode 6\n- **bool setModeShuntBusContinuous()** mode 7 - default\n\n\n#### Calibration\n\nSee datasheet.\n\nCalibration is mandatory to get **getCurrent()** and **getPower()** to work.\n\n- **bool setMaxCurrentShunt(float ampere = 20.0, float ohm = 0.002)** \nset the calibration register based upon the shunt and the max ampere. \nFrom this the LSB is derived. \nNote the function will round up the LSB to nearest round value by default. \nThis may cause loss of precision. The function may force normalization if underflow detected.\nThe user **must** check the return value == true, otherwise the calibration register is **not** set.\nReturns false if parameter out of range.\nReturns false if it could not write settings to device.\n- **bool isCalibrated()** returns true if CurrentLSB has been calculated by **setMaxCurrentShunt()**. \n- **float getCurrentLSB()** returns the LSB in Ampere == precision of the calibration.\n- **float getCurrentLSB_mA()** returns the LSB in milliAmpere.\n- **float getCurrentLSB_uA()** returns the LSB in microAmpere.\n- **float getShunt()** returns the value set for the shunt in Ohm.\n- **float getMaxCurrent()** returns the value for the maxCurrent which can be corrected.\n\nTo print these values one might use https://github.com/RobTillaart/printHelpers \nto get the values in scientific notation like \"3.5e-6\"\n\n\n#### Debugging\n\n- **uint16_t getRegister(uint8_t reg)** fetch values from registers directly.\nMeant for debugging only, reg = 0..5. Check datasheet for the details.\n\n|  reg  |  description    |  RW  |\n|:-----:|:----------------|:----:|\n|   0   |  configuration  |  RW  |\n|   1   |  shunt voltage  |  R   |\n|   2   |  bus voltage    |  R   |\n|   3   |  power          |  R   |\n|   4   |  current        |  R   |\n|   5   |  calibration    |  RW  |\n\n\n## Future\n\n#### Must\n\n- find time to test more\n  - test different loads\n  - all functions.\n- update documentation\n\n\n#### Should\n\n- sync INA226 where meaningful\n- improve error handling\n  - low level I2C, readRegister() +  writeRegister()\n  - other? parameters\n- create unit tests\n- test performance\n  - verify conversion time\n- write and verify examples\n- add a **setCurrentLSB(uint16_t mA)** function ?\n  - maxAmpere as derived value\n- disconnected load.\n  - can it be recognized? =\u003e current drop?\n\n#### Could\n\n- clean up magic numbers in the code\n- calibration\n  - autocorrect \\_current_LSB  round number\n  - maxCurrent? how much?\n  - can the calibration math be optimized\n    - integer only?\n    - less iterations?\n    - local var for current_lsb?\n    - does this matter as it is often a one time action?\n\n- cache configuration ? ==\u003e 2 bytes\n  - what is gained? both getting and setting is faster.\n    a few milliseconds per call?\n  - about a dozen times used,\n  - flag for forced read in functions **setMode(uint8_t mode, bool forced = false)**\n- create defines for several masks / magic numbers\n\n\n#### Wont\n\n- initial current 20A and shunt 0.002 Ω in **begin()**\n  - can't be sure so user is responsible\n\n\n## Support\n\nIf you appreciate my libraries, you can support the development and maintenance.\nImprove the quality of the libraries by providing issues and Pull Requests, or\ndonate through PayPal or GitHub sponsors.\n\nThank you,\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FINA219","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRobTillaart%2FINA219","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRobTillaart%2FINA219/lists"}