GY-63_MS5611/libraries/INA228/INA228.cpp
2024-05-14 12:06:33 +02:00

405 lines
8.1 KiB
C++

// FILE: INA228.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2024-05-09
// PURPOSE: Arduino library for INA228 power sensor
// URL: https://github.com/RobTillaart/INA228
//
// Read the datasheet for the details
#include "INA228.h"
////////////////////////////////////////////////////////
//
// CONSTRUCTOR
//
INA228::INA228(const uint8_t address, TwoWire *wire)
{
_address = address;
_wire = wire;
// no calibrated values by default.
_shunt = 0.015;
_maxCurrent = 10.0;
_current_LSB = _maxCurrent * pow(2, -19);
}
bool INA228::begin()
{
if (! isConnected()) return false;
return true;
}
bool INA228::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
uint8_t INA228::getAddress()
{
return _address;
}
////////////////////////////////////////////////////////
//
// CORE FUNCTIONS
//
// PAGE 25
float INA228::getBusVoltage()
{
uint32_t value = _readRegister(INA228_BUS_VOLTAGE, 3);
value >>= 4;
return value * 195.3125e-6;
}
// PAGE 25
float INA228::getShuntVoltage()
{
uint32_t value = _readRegister(INA228_SHUNT_VOLTAGE, 3);
value >>= 4;
// depends on ADCRANGE in INA228_CONFIG register.
uint16_t config = _readRegister(INA228_CONFIG, 2);
if (config & 0x0008) return value * 78.125e-9;
return value * 312.5e-9;
}
// PAGE 25 + 8.1.2
float INA228::getCurrent()
{
uint32_t value = _readRegister(INA228_CURRENT, 3);
// PAGE 31 (8.1.2)
float shunt_cal = 13107.2e6 * _current_LSB * _shunt;
// depends on ADCRANGE in INA228_CONFIG register.
uint16_t config = _readRegister(INA228_CONFIG, 2);
if (config & 0x0008) shunt_cal *= 4;
return value * shunt_cal;
}
// PAGE 26 + 8.1.2
float INA228::getPower()
{
uint32_t value = _readRegister(INA228_POWER, 3);
// PAGE 31 (8.1.2)
return value * 3.2 * _current_LSB;
}
// PAGE25
float INA228::getTemperature()
{
uint32_t value = _readRegister(INA228_TEMPERATURE, 2);
return value * 7.8125e-6;
}
// PAGE 26 + 8.1.2
float INA228::getEnergy()
{
float value = _readRegisterF(INA228_ENERGY, 5);
// PAGE 31 (8.1.2)
return value * 16 * 3.2 * _current_LSB;
}
float INA228::getCharge()
{
float value = _readRegisterF(INA228_CHARGE, 5);
// PAGE 32 (8.1.2)
return value * _current_LSB;
}
////////////////////////////////////////////////////////
//
// CONFIG REGISTER 0
//
void INA228::reset()
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
value |= 0x8000;
_writeRegister(INA228_CONFIG, value);
}
bool INA228::setAccumulation(uint8_t val)
{
if (val > 1) return false;
uint16_t value = _readRegister(INA228_CONFIG, 2);
value &= ~0x4000;
if (val == 1) value |= 0x4000;
_writeRegister(INA228_CONFIG, value);
return true;
}
bool INA228::getAccumulation()
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
return (value & 0x4000) > 0;
}
void INA228::setConversionDelay(uint8_t steps)
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
value &= ~0x3FC0;
value |= (steps << 6);
_writeRegister(INA228_CONFIG, value);
}
uint8_t INA228::getConversionDelay()
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
return (value >> 6) & 0xFF;
}
void INA228::setTemperatureCompensation(bool on)
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
value &= ~0x0020;
if (on) value |= 0x0020;
_writeRegister(INA228_CONFIG, value);
}
bool INA228::getTemperatureCompensation()
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
return value & 0x0020;
}
void INA228::setADCRange(bool flag)
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
value &= ~0x0010;
if (flag) value |= 0x0010;
_writeRegister(INA228_CONFIG, value);
}
bool INA228::getADCRange()
{
uint16_t value = _readRegister(INA228_CONFIG, 2);
return value & 0x0010;
}
////////////////////////////////////////////////////////
//
// CONFIG ADC REGISTER 1
//
bool INA228::setMode(uint8_t mode)
{
if (mode > 0x0F) return false;
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
value &= 0x0FFF; // ~(0x0F << 12);
value |= (mode << 12);
_writeRegister(INA228_ADC_CONFIG, value);
return true;
}
uint8_t INA228::getMode()
{
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
return (value >> 12) & 0x0F;
}
bool INA228::setBusVoltageConversionTime(uint8_t bvct)
{
if (bvct > 7) return false;
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
value &= 0xF1FF; // ~(0x07 << 9);
value |= (bvct << 9);
_writeRegister(INA228_ADC_CONFIG, value);
return true;
}
uint8_t INA228::getBusVoltageConversionTime()
{
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
return (value >> 9) & 0x07;
}
bool INA228::setShuntVoltageConversionTime(uint8_t svct)
{
if (svct > 7) return false;
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
value &= 0xFE3F; // ~(0x07 << 6);
value |= (svct << 6);
_writeRegister(INA228_ADC_CONFIG, value);
return true;
}
uint8_t INA228::getShuntVoltageConversionTime()
{
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
return (value >> 6) & 0x07;
}
bool INA228::setTemperatureConversionTime(uint8_t tct)
{
if (tct > 7) return false;
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
value &= 0xFFC7; // ~(0x07 << 3);
value |= (tct << 3);
_writeRegister(INA228_ADC_CONFIG, value);
return true;
}
uint8_t INA228::getTemperatureConversionTime()
{
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
return (value >> 3) & 0x07;
}
bool INA228::setAverage(uint8_t avg)
{
if (avg > 7) return false;
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
value &= 0xF1FF;
value |= avg;
_writeRegister(INA228_ADC_CONFIG, value);
return true;
}
uint8_t INA228::getAverage()
{
uint16_t value = _readRegister(INA228_ADC_CONFIG, 2);
return value & 0x0010;
}
////////////////////////////////////////////////////////
//
// SHUNT CALIBRATION REGISTER 2
//
int INA228::setMaxCurrentShunt(float maxCurrent, float shunt)
{
if (maxCurrent > 10) return -1;
if (shunt < 0.005) return -2;
_maxCurrent = maxCurrent;
_shunt = shunt;
_current_LSB = _maxCurrent * 1.9073486328125e-6; // pow(2, -19);
return 0;
}
float INA228::getMaxCurrent()
{
return _maxCurrent;
}
float INA228::getShunt()
{
return _shunt;
}
////////////////////////////////////////////////////////
//
// SHUNT TEMPERATURE COEFFICIENT REGISTER 3
//
bool INA228::setShuntTemperatureCoefficent(uint16_t ppm)
{
if (ppm > 16383) return false;
_writeRegister(INA228_SHUNT_TEMP_CO, ppm);
return true;
}
uint16_t INA228::getShuntTemperatureCoefficent()
{
uint16_t value = _readRegister(INA228_SHUNT_TEMP_CO, 2);
return value;
}
////////////////////////////////////////////////////////
//
// DIAGNOSE ALERT REGISTER 11
//
////////////////////////////////////////////////////////
//
// THRESHOLD AND LIMIT REGISTERS 12-17
//
////////////////////////////////////////////////////////
//
// MANUFACTURER and ID REGISTER 3E/3F
//
bool INA228::getManufacturer()
{
uint16_t value = _readRegister(INA228_MANUFACTURER, 2);
return value;
}
uint16_t INA228::getDieID()
{
uint16_t value = _readRegister(INA228_DEVICE_ID, 2);
return (value >> 4) & 0xFFF0;
}
uint16_t INA228::getRevision()
{
uint16_t value = _readRegister(INA228_DEVICE_ID, 2);
return value & 0x0F;
}
////////////////////////////////////////////////////////
//
// SHOULD BE PRIVATE
//
uint32_t INA228::_readRegister(uint8_t reg, uint8_t bytes)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->endTransmission();
_wire->requestFrom(_address, (uint8_t)bytes);
uint32_t value = 0;
for ( int i = 0; i < bytes; i++)
{
value <<= 8;
value |= _wire->read();
}
return value;
}
float INA228::_readRegisterF(uint8_t reg, uint8_t bytes)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->endTransmission();
_wire->requestFrom(_address, (uint8_t)bytes);
float value = 0;
for ( int i = 0; i < bytes; i++)
{
value *= 256.0;
value += _wire->read();
}
return value;
}
uint16_t INA228::_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 --