ARM Mbed library for TI INA226. High-Side or Low-Side Measurement, Bi-Directional Current and Power Monitor with I2C Compatible Interface.
ina226.cpp
- Committer:
- Branilson Luiz
- Date:
- 2019-09-09
- Revision:
- 0:ed5e54b4383d
File content as of revision 0:ed5e54b4383d:
/* * Copyright (c) 2019 Branilson Luiz * INA226.cpp - Class file for the INA226 Bi-directional Current/Power Monitor * Mbed Library. * Version: 1.0.0 * * branilson (at) gmail dot com * Github: https://github.com/branilson/ina226_mbed_library * * This program is free software: you can redistribute it and/or modify it un- * der the terms of the version 3 GNU General Public License as published by * the Free Software Foundation. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT- * NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #include "ina226.hpp" ina226::ina226(I2C& i2c, uint8_t address, int frequency) : _i2c(i2c), i2c_addr(address), i2c_freq(frequency) { _i2c.frequency(i2c_freq); } int ina226::setConfig(ina226_averages_t avg, ina226_busConvTime_t busConvTime, ina226_shuntConvTime_t shuntConvTime, ina226_mode_t mode) { uint16_t config = 0; config |= (avg << 9 | busConvTime << 6 | shuntConvTime << 3 | mode); return writeRegister16(REG_CONFIG, config); } int ina226::setCalibration(float rShuntValue, float iMaxExpected) { float test = iMaxExpected*rShuntValue; if ((test <= vShuntMax) && (test > -vShuntMax)) { uint16_t calibrationValue; float minimumLSB; rShunt = rShuntValue; minimumLSB = iMaxExpected / 32768; currentLSB = (uint16_t)(minimumLSB * 100000000); currentLSB /= 100000000; currentLSB /= 0.0001; currentLSB = ceil(currentLSB); currentLSB *= 0.0001; powerLSB = currentLSB * 25; calibrationValue = (uint16_t)((0.00512) / (currentLSB * rShuntValue)); return writeRegister16(REG_CALIBRATION, calibrationValue); } else { return -1; // Return in case of invalid parameters entered } } float ina226::readShuntVoltage(void) { return (readRegister16(REG_SHUNT_VOLTAGE) * 0.0000025); } float ina226::readCurrent(void) { return (readRegister16(REG_CURRENT) * currentLSB); } float ina226::readPower(void) { return (readRegister16(REG_POWER) * powerLSB); } float ina226::readBusVoltage(void) { int16_t voltage; voltage = readRegister16(REG_BUS_VOLTAGE); return (voltage * 0.00125); } int ina226::readManufacturerID(void) { return (readRegister16(REG_MANUFACTURER_ID)); } int ina226::readDieID(void) { return (readRegister16(REG_DIE_ID)); } int ina226::readCalibration(void) { return (readRegister16(REG_CALIBRATION)); } ina226_averages_t ina226::getAverages(void) { uint16_t value; value = readRegister16(REG_CONFIG); value &= 0b0000111000000000; value >>= 9; return (ina226_averages_t)value; } ina226_busConvTime_t ina226::getBusConversionTime(void) { uint16_t value; value = readRegister16(REG_CONFIG); value &= 0b0000000111000000; value >>= 6; return (ina226_busConvTime_t)value; } ina226_shuntConvTime_t ina226::getShuntConversionTime(void) { uint16_t value; value = readRegister16(REG_CONFIG); value &= 0b0000000000111000; value >>= 3; return (ina226_shuntConvTime_t)value; } ina226_mode_t ina226::getMode(void) { uint16_t value; value = readRegister16(REG_CONFIG); value &= 0b0000000000000111; return (ina226_mode_t)value; } void ina226::enableShuntOverVoltageAlert(void) { writeRegister16(REG_MASK, BIT_SOL); } void ina226::enableShuntUnderVoltageAlert(void) { writeRegister16(REG_MASK, BIT_SUL); } void ina226::enableBusOvertVoltageAlert(void) { writeRegister16(REG_MASK, BIT_BOL); } void ina226::enableBusUnderVoltageAlert(void) { writeRegister16(REG_MASK, BIT_BUL); } void ina226::enableOverPowerAlert(void) { writeRegister16(REG_MASK, BIT_POL); } void ina226::enableConversionReadyAlert(void) { writeRegister16(REG_MASK, BIT_CNVR); } // Workaround using Shunt Over/Under Voltage feature void ina226::setOverCurrentLimit(float current) { // Use enableShuntOverVoltageAlert() or enableBusUnderVoltageAlert() before uint16_t shunt_voltage = current * rShunt * 400000; // vShunt LSB = 2.5uV writeRegister16(REG_ALERT, shunt_voltage); } void ina226::setBusVoltageLimit(float voltage) { uint16_t value = voltage / 0.00125; writeRegister16(REG_ALERT, value); } void ina226::setShuntVoltageLimit(float voltage) { uint16_t value = voltage * 400000; // vShunt LSB = 2.5uV writeRegister16(REG_ALERT, value); } void ina226::setPowerLimit(float watts) { uint16_t value = watts / powerLSB; writeRegister16(REG_ALERT, value); } void ina226::setAlertInvertedPolarity(bool inverted) { uint16_t temp = getMask(); if (inverted) { temp |= BIT_APOL; } else { temp &= ~BIT_APOL; } setMask(temp); } void ina226::setAlertLatch(bool latch) { uint16_t temp = getMask(); if (latch) { temp |= BIT_LEN; } else { temp &= ~BIT_LEN; } setMask(temp); } bool ina226::isMathOverflow(void) { return ((getMask() & BIT_OVF) == BIT_OVF); } bool ina226::isAlert(void) { return ((getMask() & BIT_AFF) == BIT_AFF); } int16_t ina226::readRegister16(uint8_t reg) { char data[2]; _i2c.write(i2c_addr, reinterpret_cast<char*>(®), 1); _i2c.read(i2c_addr, data, 2); uint16_t value = data[0] << 8 | data[1]; return value; } int ina226::writeRegister16(uint8_t reg, uint16_t val) { char data[3]; data[0] = reg; data[1] = (val >> 8) & 0xff; data[2] = val & 0xff; return _i2c.write(i2c_addr, data, 3); } void ina226::setMask(uint16_t mask) { writeRegister16(REG_MASK, mask); } uint16_t ina226::getMask(void) { return readRegister16(REG_MASK); }