GY-63_MS5611/libraries/INA226/INA226.cpp

372 lines
7.6 KiB
C++
Raw Normal View History

2022-07-02 04:42:38 -04:00
// FILE: INA226.cpp
2021-05-30 08:22:31 -04:00
// AUTHOR: Rob Tillaart
2022-11-14 12:55:30 -05:00
// VERSION: 0.4.1
2021-05-30 08:22:31 -04:00
// DATE: 2021-05-18
2022-02-08 11:18:33 -05:00
// PURPOSE: Arduino library for INA226 power sensor
2021-05-30 08:22:31 -04:00
// URL: https://github.com/RobTillaart/INA226
//
2022-11-14 12:55:30 -05:00
// HISTORY: see changelog.md
2021-11-05 14:39:16 -04:00
2021-05-30 08:22:31 -04:00
#include "INA226.h"
2022-08-28 01:32:00 -04:00
// REGISTERS
2021-05-30 08:22:31 -04:00
#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
2022-07-02 04:42:38 -04:00
// CONFIGURATION MASKS
#define INA226_CONF_RESET_MASK 0x8000
#define INA226_CONF_AVERAGE_MASK 0x0E00
#define INA226_CONF_BUSVC_MASK 0x01C0
#define INA226_CONF_SHUNTVC_MASK 0x0038
#define INA226_CONF_MODE_MASK 0x0007
2021-05-30 08:22:31 -04:00
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// Constructor
2021-05-30 08:22:31 -04:00
//
2021-11-05 14:39:16 -04:00
INA226::INA226(const uint8_t address, TwoWire *wire)
2021-05-30 08:22:31 -04:00
{
_address = address;
_wire = wire;
2022-08-28 01:32:00 -04:00
// not calibrated values by default.
2021-05-30 08:22:31 -04:00
_current_LSB = 0;
2021-06-22 09:22:35 -04:00
_maxCurrent = 0;
_shunt = 0;
2021-05-30 08:22:31 -04:00
}
#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);
}
2022-07-02 04:42:38 -04:00
uint8_t INA226::getAddress()
{
return _address;
};
2021-05-30 08:22:31 -04:00
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// Core functions
2021-05-30 08:22:31 -04:00
//
float INA226::getShuntVoltage()
{
2022-02-08 11:18:33 -05:00
int16_t val = _readRegister(INA226_SHUNT_VOLTAGE);
2022-08-28 01:32:00 -04:00
return val * 2.5e-6; // fixed 2.50 uV
2021-05-30 08:22:31 -04:00
}
float INA226::getBusVoltage()
{
uint16_t val = _readRegister(INA226_BUS_VOLTAGE);
2022-08-28 01:32:00 -04:00
return val * 1.25e-3; // fixed 1.25 mV
2021-05-30 08:22:31 -04:00
}
float INA226::getPower()
{
uint16_t val = _readRegister(INA226_POWER);
2022-08-28 01:32:00 -04:00
return val * 25 * _current_LSB; // fixed 25 Watt
2021-05-30 08:22:31 -04:00
}
float INA226::getCurrent()
{
2022-02-08 11:18:33 -05:00
int16_t val = _readRegister(INA226_CURRENT);
2021-05-30 08:22:31 -04:00
return val * _current_LSB;
}
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// Configuration
2021-05-30 08:22:31 -04:00
//
void INA226::reset()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask |= INA226_CONF_RESET_MASK;
2021-05-30 08:22:31 -04:00
_writeRegister(INA226_CONFIGURATION, mask);
2022-08-28 01:32:00 -04:00
// reset calibration
2022-02-08 11:18:33 -05:00
_current_LSB = 0;
_maxCurrent = 0;
_shunt = 0;
2021-05-30 08:22:31 -04:00
}
2021-06-22 09:22:35 -04:00
bool INA226::setAverage(uint8_t avg)
2021-05-30 08:22:31 -04:00
{
2021-06-22 09:22:35 -04:00
if (avg > 7) return false;
2021-05-30 08:22:31 -04:00
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= ~INA226_CONF_AVERAGE_MASK;
2021-05-30 08:22:31 -04:00
mask |= (avg << 9);
_writeRegister(INA226_CONFIGURATION, mask);
2021-06-22 09:22:35 -04:00
return true;
2021-05-30 08:22:31 -04:00
}
uint8_t INA226::getAverage()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= INA226_CONF_AVERAGE_MASK;
2021-05-30 08:22:31 -04:00
mask >>= 9;
return mask;
}
2021-06-22 09:22:35 -04:00
bool INA226::setBusVoltageConversionTime(uint8_t bvct)
2021-05-30 08:22:31 -04:00
{
2021-06-22 09:22:35 -04:00
if (bvct > 7) return false;
2021-05-30 08:22:31 -04:00
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= ~INA226_CONF_BUSVC_MASK;
2021-05-30 08:22:31 -04:00
mask |= (bvct << 6);
_writeRegister(INA226_CONFIGURATION, mask);
2021-06-22 09:22:35 -04:00
return true;
2021-05-30 08:22:31 -04:00
}
uint8_t INA226::getBusVoltageConversionTime()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= INA226_CONF_BUSVC_MASK;
2021-05-30 08:22:31 -04:00
mask >>= 6;
return mask;
}
2021-06-22 09:22:35 -04:00
bool INA226::setShuntVoltageConversionTime(uint8_t svct)
2021-05-30 08:22:31 -04:00
{
2021-06-22 09:22:35 -04:00
if (svct > 7) return false;
2021-05-30 08:22:31 -04:00
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= ~INA226_CONF_SHUNTVC_MASK;
2021-05-30 08:22:31 -04:00
mask |= (svct << 3);
_writeRegister(INA226_CONFIGURATION, mask);
2021-06-22 09:22:35 -04:00
return true;
2021-05-30 08:22:31 -04:00
}
uint8_t INA226::getShuntVoltageConversionTime()
{
uint16_t mask = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
mask &= INA226_CONF_SHUNTVC_MASK;
2021-05-30 08:22:31 -04:00
mask >>= 3;
return mask;
}
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// Calibration
2021-05-30 08:22:31 -04:00
//
2022-08-28 01:32:00 -04:00
int INA226::setMaxCurrentShunt(float maxCurrent, float shunt, bool normalize)
2021-05-30 08:22:31 -04:00
{
2022-08-28 01:32:00 -04:00
// #define printdebug true
2022-02-08 11:18:33 -05:00
2022-08-28 01:32:00 -04:00
// fix #16 - datasheet 6.5 Electrical Characteristics
// rounded value to 80 mV
float shuntVoltage = abs(maxCurrent * shunt);
if (shuntVoltage > 0.080) return INA226_ERR_SHUNTVOLTAGE_HIGH;
if (maxCurrent < 0.001) return INA226_ERR_MAXCURRENT_LOW;
if (shunt < 0.001) return INA226_ERR_SHUNT_LOW;
2021-06-22 09:22:35 -04:00
2021-06-22 14:38:00 -04:00
_current_LSB = maxCurrent * 3.0517578125e-5; // maxCurrent / 32768;
2021-06-22 09:22:35 -04:00
2022-02-08 11:18:33 -05:00
#ifdef printdebug
Serial.println();
Serial.print("normalize:\t");
Serial.println(normalize ? " true":" false");
Serial.print("initial current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.println(" uA / bit");
#endif
2022-08-28 01:32:00 -04:00
uint32_t calib = 0;
uint32_t factor = 1;
// normalize the LSB to a round number
// LSB will increase
2021-06-22 09:22:35 -04:00
if (normalize)
2021-05-30 08:22:31 -04:00
{
2022-02-08 11:18:33 -05:00
calib = round(0.00512 / (_current_LSB * shunt));
_current_LSB = 0.00512 / (calib * shunt);
#ifdef printdebug
Serial.print("Prescale current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.println(" uA / bit");
#endif
2022-08-28 01:32:00 -04:00
// auto scale current_LSB
2022-02-08 11:18:33 -05:00
factor = 1;
2021-06-22 09:22:35 -04:00
while (_current_LSB < 1)
{
2021-06-22 14:38:00 -04:00
_current_LSB *= 10;
2021-06-22 09:22:35 -04:00
factor *= 10;
}
2022-02-08 11:18:33 -05:00
_current_LSB = 1.0 / factor;
2021-05-30 08:22:31 -04:00
}
2021-06-22 09:22:35 -04:00
2022-08-28 01:32:00 -04:00
// auto scale calibration
2022-02-08 11:18:33 -05:00
calib = round(0.00512 / (_current_LSB * shunt));
2021-06-22 14:38:00 -04:00
while (calib > 65535)
{
_current_LSB *= 10;
calib /= 10;
}
2021-05-30 08:22:31 -04:00
_writeRegister(INA226_CALIBRATION, calib);
2021-06-22 09:22:35 -04:00
2022-08-28 01:32:00 -04:00
_maxCurrent = _current_LSB * 32768;
2021-06-22 14:38:00 -04:00
_shunt = shunt;
2022-02-08 11:18:33 -05:00
#ifdef printdebug
Serial.print("factor:\t");
Serial.println(factor);
Serial.print("Final current_LSB:\t");
Serial.print(_current_LSB, 8);
Serial.println(" uA / bit");
Serial.print("Calibration:\t");
Serial.println(calib);
Serial.print("Max current:\t");
Serial.print(_maxCurrent);
Serial.println(" A");
Serial.print("Shunt:\t");
Serial.print(_shunt, 8);
Serial.println(" ohm");
2022-08-28 01:32:00 -04:00
Serial.print("ShuntV:\t");
Serial.print(shuntVoltage, 4);
Serial.println(" Volt");
2022-02-08 11:18:33 -05:00
#endif
2022-08-28 01:32:00 -04:00
return INA226_ERR_NONE;
2021-05-30 08:22:31 -04:00
}
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// operating mode
2021-05-30 08:22:31 -04:00
//
2021-06-22 09:22:35 -04:00
bool INA226::setMode(uint8_t mode)
2021-05-30 08:22:31 -04:00
{
2021-06-22 09:22:35 -04:00
if (mode > 7) return false;
uint16_t config = _readRegister(INA226_CONFIGURATION);
2022-07-02 04:42:38 -04:00
config &= ~INA226_CONF_MODE_MASK;
2021-06-22 09:22:35 -04:00
config |= mode;
_writeRegister(INA226_CONFIGURATION, config);
return true;
2021-05-30 08:22:31 -04:00
}
uint8_t INA226::getMode()
{
2022-07-02 04:42:38 -04:00
uint16_t mode = _readRegister(INA226_CONFIGURATION);
mode &= INA226_CONF_MODE_MASK;
return mode;
2021-05-30 08:22:31 -04:00
}
////////////////////////////////////////////////////////
//
// 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);
}
////////////////////////////////////////////////////////
//
2022-08-28 01:32:00 -04:00
// PRIVATE
2021-05-30 08:22:31 -04:00
//
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 --