Files
OpenMQTTGateway/lib/Arduino-INA226/INA226.cpp

333 lines
6.6 KiB
C++

/*
INA226.cpp - Class file for the INA226 Bi-directional Current/Power Monitor Arduino Library.
Version: 1.0.0
(c) 2014 Korneliusz Jarzebski
www.jarzebski.pl
This program is free software: you can redistribute it and/or modify
it under 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 FITNESS 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/>.
*/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <WSWire.h>
#include "INA226.h"
bool INA226::begin(uint8_t address)
{
Wire.begin();
inaAddress = address;
return true;
}
bool INA226::configure(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);
vBusMax = 36;
vShuntMax = 0.08192f;
writeRegister16(INA226_REG_CONFIG, config);
return true;
}
bool INA226::calibrate(float rShuntValue, float iMaxExpected)
{
uint16_t calibrationValue;
rShunt = rShuntValue;
float iMaxPossible, minimumLSB;
iMaxPossible = vShuntMax / rShunt;
minimumLSB = iMaxExpected / 32767;
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 * rShunt));
writeRegister16(INA226_REG_CALIBRATION, calibrationValue);
return true;
}
float INA226::getMaxPossibleCurrent(void)
{
return (vShuntMax / rShunt);
}
float INA226::getMaxCurrent(void)
{
float maxCurrent = (currentLSB * 32767);
float maxPossible = getMaxPossibleCurrent();
if (maxCurrent > maxPossible)
{
return maxPossible;
} else
{
return maxCurrent;
}
}
float INA226::getMaxShuntVoltage(void)
{
float maxVoltage = getMaxCurrent() * rShunt;
if (maxVoltage >= vShuntMax)
{
return vShuntMax;
} else
{
return maxVoltage;
}
}
float INA226::getMaxPower(void)
{
return (getMaxCurrent() * vBusMax);
}
float INA226::readBusPower(void)
{
return (readRegister16(INA226_REG_POWER) * powerLSB);
}
float INA226::readShuntCurrent(void)
{
return (readRegister16(INA226_REG_CURRENT) * currentLSB);
}
float INA226::readShuntVoltage(void)
{
float voltage;
voltage = readRegister16(INA226_REG_SHUNTVOLTAGE);
return (voltage * 0.0000025);
}
float INA226::readBusVoltage(void)
{
int16_t voltage;
voltage = readRegister16(INA226_REG_BUSVOLTAGE);
return (voltage * 0.00125);
}
ina226_averages_t INA226::getAverages(void)
{
uint16_t value;
value = readRegister16(INA226_REG_CONFIG);
value &= 0b0000111000000000;
value >>= 9;
return (ina226_averages_t)value;
}
ina226_busConvTime_t INA226::getBusConversionTime(void)
{
uint16_t value;
value = readRegister16(INA226_REG_CONFIG);
value &= 0b0000000111000000;
value >>= 6;
return (ina226_busConvTime_t)value;
}
ina226_shuntConvTime_t INA226::getShuntConversionTime(void)
{
uint16_t value;
value = readRegister16(INA226_REG_CONFIG);
value &= 0b0000000000111000;
value >>= 3;
return (ina226_shuntConvTime_t)value;
}
ina226_mode_t INA226::getMode(void)
{
uint16_t value;
value = readRegister16(INA226_REG_CONFIG);
value &= 0b0000000000000111;
return (ina226_mode_t)value;
}
void INA226::setMaskEnable(uint16_t mask)
{
writeRegister16(INA226_REG_MASKENABLE, mask);
}
uint16_t INA226::getMaskEnable(void)
{
return readRegister16(INA226_REG_MASKENABLE);
}
void INA226::enableShuntOverLimitAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_SOL);
}
void INA226::enableShuntUnderLimitAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_SUL);
}
void INA226::enableBusOvertLimitAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_BOL);
}
void INA226::enableBusUnderLimitAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_BUL);
}
void INA226::enableOverPowerLimitAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_POL);
}
void INA226::enableConversionReadyAlert(void)
{
writeRegister16(INA226_REG_MASKENABLE, INA226_BIT_CNVR);
}
void INA226::setBusVoltageLimit(float voltage)
{
uint16_t value = voltage / 0.00125;
writeRegister16(INA226_REG_ALERTLIMIT, value);
}
void INA226::setShuntVoltageLimit(float voltage)
{
uint16_t value = voltage * 25000;
writeRegister16(INA226_REG_ALERTLIMIT, value);
}
void INA226::setPowerLimit(float watts)
{
uint16_t value = watts / powerLSB;
writeRegister16(INA226_REG_ALERTLIMIT, value);
}
void INA226::setAlertInvertedPolarity(bool inverted)
{
uint16_t temp = getMaskEnable();
if (inverted)
{
temp |= INA226_BIT_APOL;
} else
{
temp &= ~INA226_BIT_APOL;
}
setMaskEnable(temp);
}
void INA226::setAlertLatch(bool latch)
{
uint16_t temp = getMaskEnable();
if (latch)
{
temp |= INA226_BIT_LEN;
} else
{
temp &= ~INA226_BIT_LEN;
}
setMaskEnable(temp);
}
bool INA226::isMathOverflow(void)
{
return ((getMaskEnable() & INA226_BIT_OVF) == INA226_BIT_OVF);
}
bool INA226::isAlert(void)
{
return ((getMaskEnable() & INA226_BIT_AFF) == INA226_BIT_AFF);
}
int16_t INA226::readRegister16(uint8_t reg)
{
int16_t value;
Wire.beginTransmission(inaAddress);
#if ARDUINO >= 100
Wire.write(reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
delay(1);
Wire.beginTransmission(inaAddress);
Wire.requestFrom(inaAddress, 2);
while(!Wire.available()) {};
#if ARDUINO >= 100
uint8_t vha = Wire.read();
uint8_t vla = Wire.read();
#else
uint8_t vha = Wire.receive();
uint8_t vla = Wire.receive();
#endif;
Wire.endTransmission();
value = vha << 8 | vla;
return value;
}
void INA226::writeRegister16(uint8_t reg, uint16_t val)
{
uint8_t vla;
vla = (uint8_t)val;
val >>= 8;
Wire.beginTransmission(inaAddress);
#if ARDUINO >= 100
Wire.write(reg);
Wire.write((uint8_t)val);
Wire.write(vla);
#else
Wire.send(reg);
Wire.send((uint8_t)val);
Wire.send(vla);
#endif
Wire.endTransmission();
}