GY-63_MS5611/libraries/INA226/INA226.cpp
2021-12-20 08:48:45 +01:00

335 lines
6.7 KiB
C++

// FILE: INA266.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.6
// DATE: 2021-05-18
// PURPOSE: Arduino library for INA266 power sensor
// URL: https://github.com/RobTillaart/INA226
//
// HISTORY:
// 0.1.0 2021-05-18 initial version
// 0.1.1 2021-06-21 improved calibration + added functions
// 0.1.2 2021-06-22 add check of parameters of several functions + unit tests
// add getShunt() , getMaxCurrent()
// 0.1.3 2021-06-22 add getCurrentLSB_uA() + improve examples
// fix for calibration
// 0.1.4 2021-08-07 fix getCurrent()
// 0.1.5 2021-11-05 update build-CI, add badges
// fix address in constructor.
// 0.1.6 2021-12-20 update library.json, license, minor edits
#include "INA226.h"
#define INA226_CONFIGURATION 0x00
#define INA226_SHUNT_VOLTAGE 0x01
#define INA226_BUS_VOLTAGE 0x02
#define INA226_POWER 0x03
#define INA226_CURRENT 0x04
#define INA226_CALIBRATION 0x05
#define INA226_MASK_ENABLE 0x06
#define INA226_ALERT_LIMIT 0x07
#define INA226_MANUFACTURER 0xFE
#define INA226_DIE_ID 0xFF
////////////////////////////////////////////////////////
//
// Constructor
//
INA226::INA226(const uint8_t address, TwoWire *wire)
{
_address = address;
_wire = wire;
// as these
_current_LSB = 0;
_maxCurrent = 0;
_shunt = 0;
}
#if defined (ESP8266) || defined(ESP32)
bool INA226::begin(const uint8_t sda, const uint8_t scl)
{
_wire = &Wire;
_wire->begin(sda, scl);
if (! isConnected()) return false;
return true;
}
#endif
bool INA226::begin()
{
_wire->begin();
if (! isConnected()) return false;
return true;
}
bool INA226::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
////////////////////////////////////////////////////////
//
// Core functions
//
float INA226::getShuntVoltage()
{
uint16_t val = _readRegister(INA226_SHUNT_VOLTAGE);
if (val & 0x8000)
{
val = val & 0x7FFF;
val = val ^ 0x7FFF;
val++;
return val * -2.5e-6;
}
return val * 2.5e-6; // fixed 2.50 uV
}
float INA226::getBusVoltage()
{
uint16_t val = _readRegister(INA226_BUS_VOLTAGE);
return val * 1.25e-3; // fixed 1.25 mV
}
float INA226::getPower()
{
uint16_t val = _readRegister(INA226_POWER);
return val * 25 * _current_LSB;
}
float INA226::getCurrent()
{
uint16_t val = _readRegister(INA226_CURRENT);
if (val & 0x8000)
{
val = val & 0x7FFF;
val = val ^ 0x7FFF;
val++;
return val * -_current_LSB;
}
return val * _current_LSB;
}
////////////////////////////////////////////////////////
//
// Configuration
//
void INA226::reset()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask |= 0x800;
_writeRegister(INA226_CONFIGURATION, mask);
// reset calibration?
}
bool INA226::setAverage(uint8_t avg)
{
if (avg > 7) return false;
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask &= 0xF1FF;
mask |= (avg << 9);
_writeRegister(INA226_CONFIGURATION, mask);
return true;
}
uint8_t INA226::getAverage()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask >>= 9;
mask &= 7;
return mask;
}
bool INA226::setBusVoltageConversionTime(uint8_t bvct)
{
if (bvct > 7) return false;
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask &= 0xFE3F;
mask |= (bvct << 6);
_writeRegister(INA226_CONFIGURATION, mask);
return true;
}
uint8_t INA226::getBusVoltageConversionTime()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask >>= 6;
mask &= 7;
return mask;
}
bool INA226::setShuntVoltageConversionTime(uint8_t svct)
{
if (svct > 7) return false;
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask &= 0xFFC7;
mask |= (svct << 3);
_writeRegister(INA226_CONFIGURATION, mask);
return true;
}
uint8_t INA226::getShuntVoltageConversionTime()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
mask >>= 3;
mask &= 7;
return mask;
}
////////////////////////////////////////////////////////
//
// Calibration
//
bool INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
{
if (maxCurrent > 20 || maxCurrent < 0.001) return false;
if (shunt < 0.001) return false;
_current_LSB = maxCurrent * 3.0517578125e-5; // maxCurrent / 32768;
// normalize the LSB to a round number
// LSB will increase
if (normalize)
{
// Serial.print("current_LSB:\t");
// Serial.println(_current_LSB, 10);
uint32_t factor = 1;
while (_current_LSB < 1)
{
_current_LSB *= 10;
factor *= 10;
}
_current_LSB = 10.0 / factor;
// Serial.print("current_LSB:\t");
// Serial.println(_current_LSB, 10);
}
// auto-scale
uint32_t calib = round(0.00512 / (_current_LSB * shunt));
while (calib > 65535)
{
_current_LSB *= 10;
calib /= 10;
}
_writeRegister(INA226_CALIBRATION, calib);
// Serial.print("Calibration:\t");
// Serial.println(calib);
_maxCurrent = _current_LSB * 32768.0;
_shunt = shunt;
return true;
}
////////////////////////////////////////////////////////
//
// operating mode
//
bool INA226::setMode(uint8_t mode)
{
if (mode > 7) return false;
uint16_t config = _readRegister(INA226_CONFIGURATION);
config &= 0xFFF8;
config |= mode;
_writeRegister(INA226_CONFIGURATION, config);
return true;
}
uint8_t INA226::getMode()
{
return _readRegister(INA226_CONFIGURATION) & 0x0007;
}
////////////////////////////////////////////////////////
//
// alert
//
void INA226::setAlertRegister(uint16_t mask)
{
_writeRegister(INA226_MASK_ENABLE, (mask & 0xFC00));
}
uint16_t INA226::getAlertFlag()
{
return _readRegister(INA226_MASK_ENABLE) & 0x001F;
}
void INA226::setAlertLimit(uint16_t limit)
{
_writeRegister(INA226_ALERT_LIMIT, limit);
}
uint16_t INA226::getAlertLimit()
{
return _readRegister(INA226_ALERT_LIMIT);
}
////////////////////////////////////////////////////////
//
// meta information
//
uint16_t INA226::getManufacturerID()
{
return _readRegister(INA226_MANUFACTURER);
}
uint16_t INA226::getDieID()
{
return _readRegister(INA226_DIE_ID);
}
////////////////////////////////////////////////////////
//
// PRIVATE
//
uint16_t INA226::_readRegister(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->endTransmission();
_wire->requestFrom(_address, (uint8_t)2);
uint16_t value = _wire->read();
value <<= 8;
value |= _wire->read();
return value;
}
uint16_t INA226::_writeRegister(uint8_t reg, uint16_t value)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->write(value >> 8);
_wire->write(value & 0xFF);
return _wire->endTransmission();
}
// -- END OF FILE --