ARM Mbed library for TI INA226. High-Side or Low-Side Measurement, Bi-Directional Current and Power Monitor with I2C Compatible Interface.

Committer:
Branilson Luiz
Date:
Mon Sep 09 02:34:29 2019 -0300
Revision:
0:ed5e54b4383d
First commit.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Branilson Luiz 0:ed5e54b4383d 1 /*
Branilson Luiz 0:ed5e54b4383d 2 * Copyright (c) 2019 Branilson Luiz
Branilson Luiz 0:ed5e54b4383d 3 * INA226.cpp - Class file for the INA226 Bi-directional Current/Power Monitor
Branilson Luiz 0:ed5e54b4383d 4 * Mbed Library.
Branilson Luiz 0:ed5e54b4383d 5 * Version: 1.0.0
Branilson Luiz 0:ed5e54b4383d 6 *
Branilson Luiz 0:ed5e54b4383d 7 * branilson (at) gmail dot com
Branilson Luiz 0:ed5e54b4383d 8 * Github: https://github.com/branilson/ina226_mbed_library
Branilson Luiz 0:ed5e54b4383d 9 *
Branilson Luiz 0:ed5e54b4383d 10 * This program is free software: you can redistribute it and/or modify it un-
Branilson Luiz 0:ed5e54b4383d 11 * der the terms of the version 3 GNU General Public License as published by
Branilson Luiz 0:ed5e54b4383d 12 * the Free Software Foundation.
Branilson Luiz 0:ed5e54b4383d 13 * This program is distributed in the hope that it will be useful, but WITHOUT
Branilson Luiz 0:ed5e54b4383d 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT-
Branilson Luiz 0:ed5e54b4383d 15 * NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
Branilson Luiz 0:ed5e54b4383d 16 * details.
Branilson Luiz 0:ed5e54b4383d 17 * You should have received a copy of the GNU General Public License along with
Branilson Luiz 0:ed5e54b4383d 18 * this program. If not, see <http://www.gnu.org/licenses/>.
Branilson Luiz 0:ed5e54b4383d 19 */
Branilson Luiz 0:ed5e54b4383d 20
Branilson Luiz 0:ed5e54b4383d 21
Branilson Luiz 0:ed5e54b4383d 22 #include "ina226.hpp"
Branilson Luiz 0:ed5e54b4383d 23
Branilson Luiz 0:ed5e54b4383d 24 ina226::ina226(I2C& i2c, uint8_t address, int frequency)
Branilson Luiz 0:ed5e54b4383d 25 : _i2c(i2c),
Branilson Luiz 0:ed5e54b4383d 26 i2c_addr(address),
Branilson Luiz 0:ed5e54b4383d 27 i2c_freq(frequency) {
Branilson Luiz 0:ed5e54b4383d 28 _i2c.frequency(i2c_freq);
Branilson Luiz 0:ed5e54b4383d 29 }
Branilson Luiz 0:ed5e54b4383d 30
Branilson Luiz 0:ed5e54b4383d 31 int ina226::setConfig(ina226_averages_t avg,
Branilson Luiz 0:ed5e54b4383d 32 ina226_busConvTime_t busConvTime,
Branilson Luiz 0:ed5e54b4383d 33 ina226_shuntConvTime_t shuntConvTime,
Branilson Luiz 0:ed5e54b4383d 34 ina226_mode_t mode) {
Branilson Luiz 0:ed5e54b4383d 35 uint16_t config = 0;
Branilson Luiz 0:ed5e54b4383d 36 config |= (avg << 9 | busConvTime << 6 | shuntConvTime << 3 | mode);
Branilson Luiz 0:ed5e54b4383d 37 return writeRegister16(REG_CONFIG, config);
Branilson Luiz 0:ed5e54b4383d 38 }
Branilson Luiz 0:ed5e54b4383d 39
Branilson Luiz 0:ed5e54b4383d 40 int ina226::setCalibration(float rShuntValue, float iMaxExpected) {
Branilson Luiz 0:ed5e54b4383d 41 float test = iMaxExpected*rShuntValue;
Branilson Luiz 0:ed5e54b4383d 42 if ((test <= vShuntMax) && (test > -vShuntMax)) {
Branilson Luiz 0:ed5e54b4383d 43 uint16_t calibrationValue;
Branilson Luiz 0:ed5e54b4383d 44 float minimumLSB;
Branilson Luiz 0:ed5e54b4383d 45 rShunt = rShuntValue;
Branilson Luiz 0:ed5e54b4383d 46 minimumLSB = iMaxExpected / 32768;
Branilson Luiz 0:ed5e54b4383d 47 currentLSB = (uint16_t)(minimumLSB * 100000000);
Branilson Luiz 0:ed5e54b4383d 48 currentLSB /= 100000000;
Branilson Luiz 0:ed5e54b4383d 49 currentLSB /= 0.0001;
Branilson Luiz 0:ed5e54b4383d 50 currentLSB = ceil(currentLSB);
Branilson Luiz 0:ed5e54b4383d 51 currentLSB *= 0.0001;
Branilson Luiz 0:ed5e54b4383d 52 powerLSB = currentLSB * 25;
Branilson Luiz 0:ed5e54b4383d 53 calibrationValue = (uint16_t)((0.00512) / (currentLSB * rShuntValue));
Branilson Luiz 0:ed5e54b4383d 54 return writeRegister16(REG_CALIBRATION, calibrationValue);
Branilson Luiz 0:ed5e54b4383d 55 } else {
Branilson Luiz 0:ed5e54b4383d 56 return -1; // Return in case of invalid parameters entered
Branilson Luiz 0:ed5e54b4383d 57 }
Branilson Luiz 0:ed5e54b4383d 58 }
Branilson Luiz 0:ed5e54b4383d 59
Branilson Luiz 0:ed5e54b4383d 60 float ina226::readShuntVoltage(void) {
Branilson Luiz 0:ed5e54b4383d 61 return (readRegister16(REG_SHUNT_VOLTAGE) * 0.0000025);
Branilson Luiz 0:ed5e54b4383d 62 }
Branilson Luiz 0:ed5e54b4383d 63
Branilson Luiz 0:ed5e54b4383d 64 float ina226::readCurrent(void) {
Branilson Luiz 0:ed5e54b4383d 65 return (readRegister16(REG_CURRENT) * currentLSB);
Branilson Luiz 0:ed5e54b4383d 66 }
Branilson Luiz 0:ed5e54b4383d 67
Branilson Luiz 0:ed5e54b4383d 68 float ina226::readPower(void) {
Branilson Luiz 0:ed5e54b4383d 69 return (readRegister16(REG_POWER) * powerLSB);
Branilson Luiz 0:ed5e54b4383d 70 }
Branilson Luiz 0:ed5e54b4383d 71
Branilson Luiz 0:ed5e54b4383d 72 float ina226::readBusVoltage(void) {
Branilson Luiz 0:ed5e54b4383d 73 int16_t voltage;
Branilson Luiz 0:ed5e54b4383d 74 voltage = readRegister16(REG_BUS_VOLTAGE);
Branilson Luiz 0:ed5e54b4383d 75 return (voltage * 0.00125);
Branilson Luiz 0:ed5e54b4383d 76 }
Branilson Luiz 0:ed5e54b4383d 77
Branilson Luiz 0:ed5e54b4383d 78 int ina226::readManufacturerID(void) {
Branilson Luiz 0:ed5e54b4383d 79 return (readRegister16(REG_MANUFACTURER_ID));
Branilson Luiz 0:ed5e54b4383d 80 }
Branilson Luiz 0:ed5e54b4383d 81
Branilson Luiz 0:ed5e54b4383d 82 int ina226::readDieID(void) {
Branilson Luiz 0:ed5e54b4383d 83 return (readRegister16(REG_DIE_ID));
Branilson Luiz 0:ed5e54b4383d 84 }
Branilson Luiz 0:ed5e54b4383d 85
Branilson Luiz 0:ed5e54b4383d 86 int ina226::readCalibration(void) {
Branilson Luiz 0:ed5e54b4383d 87 return (readRegister16(REG_CALIBRATION));
Branilson Luiz 0:ed5e54b4383d 88 }
Branilson Luiz 0:ed5e54b4383d 89
Branilson Luiz 0:ed5e54b4383d 90 ina226_averages_t ina226::getAverages(void) {
Branilson Luiz 0:ed5e54b4383d 91 uint16_t value;
Branilson Luiz 0:ed5e54b4383d 92 value = readRegister16(REG_CONFIG);
Branilson Luiz 0:ed5e54b4383d 93 value &= 0b0000111000000000;
Branilson Luiz 0:ed5e54b4383d 94 value >>= 9;
Branilson Luiz 0:ed5e54b4383d 95 return (ina226_averages_t)value;
Branilson Luiz 0:ed5e54b4383d 96 }
Branilson Luiz 0:ed5e54b4383d 97
Branilson Luiz 0:ed5e54b4383d 98 ina226_busConvTime_t ina226::getBusConversionTime(void) {
Branilson Luiz 0:ed5e54b4383d 99 uint16_t value;
Branilson Luiz 0:ed5e54b4383d 100 value = readRegister16(REG_CONFIG);
Branilson Luiz 0:ed5e54b4383d 101 value &= 0b0000000111000000;
Branilson Luiz 0:ed5e54b4383d 102 value >>= 6;
Branilson Luiz 0:ed5e54b4383d 103 return (ina226_busConvTime_t)value;
Branilson Luiz 0:ed5e54b4383d 104 }
Branilson Luiz 0:ed5e54b4383d 105
Branilson Luiz 0:ed5e54b4383d 106 ina226_shuntConvTime_t ina226::getShuntConversionTime(void) {
Branilson Luiz 0:ed5e54b4383d 107 uint16_t value;
Branilson Luiz 0:ed5e54b4383d 108 value = readRegister16(REG_CONFIG);
Branilson Luiz 0:ed5e54b4383d 109 value &= 0b0000000000111000;
Branilson Luiz 0:ed5e54b4383d 110 value >>= 3;
Branilson Luiz 0:ed5e54b4383d 111 return (ina226_shuntConvTime_t)value;
Branilson Luiz 0:ed5e54b4383d 112 }
Branilson Luiz 0:ed5e54b4383d 113
Branilson Luiz 0:ed5e54b4383d 114 ina226_mode_t ina226::getMode(void) {
Branilson Luiz 0:ed5e54b4383d 115 uint16_t value;
Branilson Luiz 0:ed5e54b4383d 116 value = readRegister16(REG_CONFIG);
Branilson Luiz 0:ed5e54b4383d 117 value &= 0b0000000000000111;
Branilson Luiz 0:ed5e54b4383d 118 return (ina226_mode_t)value;
Branilson Luiz 0:ed5e54b4383d 119 }
Branilson Luiz 0:ed5e54b4383d 120
Branilson Luiz 0:ed5e54b4383d 121 void ina226::enableShuntOverVoltageAlert(void) {
Branilson Luiz 0:ed5e54b4383d 122 writeRegister16(REG_MASK, BIT_SOL);
Branilson Luiz 0:ed5e54b4383d 123 }
Branilson Luiz 0:ed5e54b4383d 124
Branilson Luiz 0:ed5e54b4383d 125 void ina226::enableShuntUnderVoltageAlert(void) {
Branilson Luiz 0:ed5e54b4383d 126 writeRegister16(REG_MASK, BIT_SUL);
Branilson Luiz 0:ed5e54b4383d 127 }
Branilson Luiz 0:ed5e54b4383d 128
Branilson Luiz 0:ed5e54b4383d 129 void ina226::enableBusOvertVoltageAlert(void) {
Branilson Luiz 0:ed5e54b4383d 130 writeRegister16(REG_MASK, BIT_BOL);
Branilson Luiz 0:ed5e54b4383d 131 }
Branilson Luiz 0:ed5e54b4383d 132
Branilson Luiz 0:ed5e54b4383d 133 void ina226::enableBusUnderVoltageAlert(void) {
Branilson Luiz 0:ed5e54b4383d 134 writeRegister16(REG_MASK, BIT_BUL);
Branilson Luiz 0:ed5e54b4383d 135 }
Branilson Luiz 0:ed5e54b4383d 136
Branilson Luiz 0:ed5e54b4383d 137 void ina226::enableOverPowerAlert(void) {
Branilson Luiz 0:ed5e54b4383d 138 writeRegister16(REG_MASK, BIT_POL);
Branilson Luiz 0:ed5e54b4383d 139 }
Branilson Luiz 0:ed5e54b4383d 140
Branilson Luiz 0:ed5e54b4383d 141 void ina226::enableConversionReadyAlert(void) {
Branilson Luiz 0:ed5e54b4383d 142 writeRegister16(REG_MASK, BIT_CNVR);
Branilson Luiz 0:ed5e54b4383d 143 }
Branilson Luiz 0:ed5e54b4383d 144
Branilson Luiz 0:ed5e54b4383d 145 // Workaround using Shunt Over/Under Voltage feature
Branilson Luiz 0:ed5e54b4383d 146 void ina226::setOverCurrentLimit(float current) {
Branilson Luiz 0:ed5e54b4383d 147 // Use enableShuntOverVoltageAlert() or enableBusUnderVoltageAlert() before
Branilson Luiz 0:ed5e54b4383d 148 uint16_t shunt_voltage = current * rShunt * 400000; // vShunt LSB = 2.5uV
Branilson Luiz 0:ed5e54b4383d 149 writeRegister16(REG_ALERT, shunt_voltage);
Branilson Luiz 0:ed5e54b4383d 150 }
Branilson Luiz 0:ed5e54b4383d 151
Branilson Luiz 0:ed5e54b4383d 152 void ina226::setBusVoltageLimit(float voltage) {
Branilson Luiz 0:ed5e54b4383d 153 uint16_t value = voltage / 0.00125;
Branilson Luiz 0:ed5e54b4383d 154 writeRegister16(REG_ALERT, value);
Branilson Luiz 0:ed5e54b4383d 155 }
Branilson Luiz 0:ed5e54b4383d 156
Branilson Luiz 0:ed5e54b4383d 157 void ina226::setShuntVoltageLimit(float voltage) {
Branilson Luiz 0:ed5e54b4383d 158 uint16_t value = voltage * 400000; // vShunt LSB = 2.5uV
Branilson Luiz 0:ed5e54b4383d 159 writeRegister16(REG_ALERT, value);
Branilson Luiz 0:ed5e54b4383d 160 }
Branilson Luiz 0:ed5e54b4383d 161
Branilson Luiz 0:ed5e54b4383d 162 void ina226::setPowerLimit(float watts) {
Branilson Luiz 0:ed5e54b4383d 163 uint16_t value = watts / powerLSB;
Branilson Luiz 0:ed5e54b4383d 164 writeRegister16(REG_ALERT, value);
Branilson Luiz 0:ed5e54b4383d 165 }
Branilson Luiz 0:ed5e54b4383d 166
Branilson Luiz 0:ed5e54b4383d 167 void ina226::setAlertInvertedPolarity(bool inverted) {
Branilson Luiz 0:ed5e54b4383d 168 uint16_t temp = getMask();
Branilson Luiz 0:ed5e54b4383d 169 if (inverted) {
Branilson Luiz 0:ed5e54b4383d 170 temp |= BIT_APOL;
Branilson Luiz 0:ed5e54b4383d 171 } else {
Branilson Luiz 0:ed5e54b4383d 172 temp &= ~BIT_APOL;
Branilson Luiz 0:ed5e54b4383d 173 }
Branilson Luiz 0:ed5e54b4383d 174 setMask(temp);
Branilson Luiz 0:ed5e54b4383d 175 }
Branilson Luiz 0:ed5e54b4383d 176
Branilson Luiz 0:ed5e54b4383d 177 void ina226::setAlertLatch(bool latch) {
Branilson Luiz 0:ed5e54b4383d 178 uint16_t temp = getMask();
Branilson Luiz 0:ed5e54b4383d 179 if (latch) {
Branilson Luiz 0:ed5e54b4383d 180 temp |= BIT_LEN;
Branilson Luiz 0:ed5e54b4383d 181 } else {
Branilson Luiz 0:ed5e54b4383d 182 temp &= ~BIT_LEN;
Branilson Luiz 0:ed5e54b4383d 183 }
Branilson Luiz 0:ed5e54b4383d 184 setMask(temp);
Branilson Luiz 0:ed5e54b4383d 185 }
Branilson Luiz 0:ed5e54b4383d 186
Branilson Luiz 0:ed5e54b4383d 187 bool ina226::isMathOverflow(void) {
Branilson Luiz 0:ed5e54b4383d 188 return ((getMask() & BIT_OVF) == BIT_OVF);
Branilson Luiz 0:ed5e54b4383d 189 }
Branilson Luiz 0:ed5e54b4383d 190
Branilson Luiz 0:ed5e54b4383d 191 bool ina226::isAlert(void) {
Branilson Luiz 0:ed5e54b4383d 192 return ((getMask() & BIT_AFF) == BIT_AFF);
Branilson Luiz 0:ed5e54b4383d 193 }
Branilson Luiz 0:ed5e54b4383d 194
Branilson Luiz 0:ed5e54b4383d 195 int16_t ina226::readRegister16(uint8_t reg) {
Branilson Luiz 0:ed5e54b4383d 196 char data[2];
Branilson Luiz 0:ed5e54b4383d 197 _i2c.write(i2c_addr, reinterpret_cast<char*>(&reg), 1);
Branilson Luiz 0:ed5e54b4383d 198 _i2c.read(i2c_addr, data, 2);
Branilson Luiz 0:ed5e54b4383d 199 uint16_t value = data[0] << 8 | data[1];
Branilson Luiz 0:ed5e54b4383d 200 return value;
Branilson Luiz 0:ed5e54b4383d 201 }
Branilson Luiz 0:ed5e54b4383d 202
Branilson Luiz 0:ed5e54b4383d 203 int ina226::writeRegister16(uint8_t reg, uint16_t val) {
Branilson Luiz 0:ed5e54b4383d 204 char data[3];
Branilson Luiz 0:ed5e54b4383d 205 data[0] = reg;
Branilson Luiz 0:ed5e54b4383d 206 data[1] = (val >> 8) & 0xff;
Branilson Luiz 0:ed5e54b4383d 207 data[2] = val & 0xff;
Branilson Luiz 0:ed5e54b4383d 208 return _i2c.write(i2c_addr, data, 3);
Branilson Luiz 0:ed5e54b4383d 209 }
Branilson Luiz 0:ed5e54b4383d 210
Branilson Luiz 0:ed5e54b4383d 211 void ina226::setMask(uint16_t mask) {
Branilson Luiz 0:ed5e54b4383d 212 writeRegister16(REG_MASK, mask);
Branilson Luiz 0:ed5e54b4383d 213 }
Branilson Luiz 0:ed5e54b4383d 214
Branilson Luiz 0:ed5e54b4383d 215 uint16_t ina226::getMask(void) {
Branilson Luiz 0:ed5e54b4383d 216 return readRegister16(REG_MASK);
Branilson Luiz 0:ed5e54b4383d 217 }