mirror of
https://github.com/1technophile/OpenMQTTGateway.git
synced 2026-02-20 00:32:04 +01:00
333 lines
6.6 KiB
C++
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();
|
|
}
|