ARM Mbed library for TI INA226. High-Side or Low-Side Measurement, Bi-Directional Current and Power Monitor with I2C Compatible Interface.
ina226.cpp@0:ed5e54b4383d, 2019-09-09 (annotated)
- Committer:
- Branilson Luiz
- Date:
- Mon Sep 09 02:34:29 2019 -0300
- Revision:
- 0:ed5e54b4383d
First commit.
Who changed what in which revision?
User | Revision | Line number | New 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*>(®), 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 | } |