INA226 Current/Power Monitor with Electron - Library and Wiring Help

Hi,
I’m trying to configure the INA226 current/power monitor for use with a Particle Electron. I have a CJMCU Breakout board and have it wired to my Electron.

I’m trying to use an Arduino Library I found on GitHub to interface with this board, but I don’t know enough about the conversion from Arduino to Particle.

I’ve incorporated the INA226.h and INA226.cpp into my project, but I can’t get it to work. Thanks in advance for any help.

My wiring schematic looks like this:
Electron%20with%20INA226%20schematic

Here’s my code:

/*  Particle Electron current and voltage measurement using the INA226 CJMCU Breakout Board */

// ************************** Libraries Needed To Compile The Script  **************************
        #include <INA226.h> //library for the current and voltage sensor
        #include <Ubidots.h>
        #define TOKEN "mytoken"  // Your unique Ubidots TOKEN. 
        Ubidots ubidots(TOKEN);

// ************ INA226 Current and Voltage Monitor Definitions *****************************************
    INA226 ina;
    const int CurrentSensorPowerPin=B0; //current and voltage sensor power pin 
    const int CurrentSensorGndPin =B1;  //current and voltage sensor GROUND pin 
    const int CurrentSensorSDAPin =B2;  //I2C communication pin 
    const int CurrentSensorSCLPin =B3;  //I2C communication pin  
    const int LightPin =D7;  //on board light

    float shuntcurrentA=0; //i7nitalize variables for INA226
    float shuntvoltageV=0;
    float busvoltageV=0;
    float buspowerW=0;

    int Reading_Delay_milliseconds=15000;  // delay between readings in milliseconds.  

// **************************Setup - runs Once and sets pins etc ****************************************
void setup()
{
  //SET UP PINS FOR SENSORS:
  //Serial.begin(9600); // only used for wired connection serial communication 
 
  pinMode(CurrentSensorPowerPin , OUTPUT); // set the powerpin as an output
    digitalWrite(CurrentSensorPowerPin , HIGH); //Turn it on for now
  pinMode(CurrentSensorGndPin , OUTPUT);//setting pin for ground for the EC sensor as an ouput
    digitalWrite(CurrentSensorGndPin,LOW);//We can leave the ground connected permanantly
  pinMode(CurrentSensorSDAPin,INPUT); // set the current sensor I2C communication pins as inputs
  pinMode(CurrentSensorSCLPin,INPUT); // set the current sensor I2C communication pins as inputs  
  pinMode(LightPin , OUTPUT); // set the lightpin as an output (for troubleshooting)


  // Initialize INA226 Current & Voltage Sensor.  Default INA226 address is 0x40
  delay(500);// gives sensor time to settle
  ina.begin();
  // Configure INA226:
  ina.configure(INA226_AVERAGES_1, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
  // Calibrate INA226. (Rshunt = 0.01 ohm, Max excepted current = 4A) (Rshunt = .008, Max current=11A):
  ina.calibrate(0.008, 11);
 };  // ******************************************* End of Setup ********************************************************
  
// *******************************************************************************************************************
// ************************************* Main Loop - Runs Forever ************************************************
// *******************************************************************************************************************
    // The main loop is run repeatedly.  It calls functions for taking sensor readings, printing results, etc.
void loop()
    {
    digitalWrite(LightPin , HIGH); //Turn on light
    GetCurrent();       //Calls code to get current and voltage
    PrintReadings();    // Calls Print routine [below main loop]
    digitalWrite(LightPin , LOW); //Turn off light
    delay(Reading_Delay_milliseconds); //delay between readings in milliseconds. 
    
    };
// *******************************************************************************************************************
// ************************************** End Of Main Loop ***********************************************************
// *******************************************************************************************************************

// ************  GetCurrent Function (This Loop Is called From Main Loop)*************************************
void GetCurrent(){
// reads current and voltage from the INA219 or INA229 sensor
 
  shuntcurrentA=ina.readShuntCurrent();
  shuntvoltageV=ina.readShuntVoltage();
  busvoltageV=ina.readBusVoltage();
  buspowerW=ina.readBusPower();
  delay(500);
};

// ****** Send Readings Function (This is where useful data is sent to the desired location) ******
void PrintReadings(){
    ubidots.add("Current_A", shuntcurrentA);
    ubidots.sendAll();      //send the variables to Ubidots
    
};  // *********************** END OF PROGRAM ************************

Here is some more information…

I am planning to use this to monitor a system with a Max current of 10Amps, and a Max voltage of 36VDC. I have removed the .010 ohm resistor from the INA226 breakout board and replaced it with a .008 ohm shunt resistor.

Here is a photo of the setup so far…

BTW, There was some discussion about this in another thread, but that got off track, so I decided to create a new thread on the subject.

In your schema you have your I2C pins (SDA/SCL) connected to B2/B3 but the docs do tell that on the Electon the I2C interface can be found on D0/D1 (Wire) or C4/C5 (Wire1).

2 Likes

Thanks for the help. I’ll make that change tonight. I’ll attempt to alter the library accordingly as well.

@undergrounder996, you should not be doing anything with the SCA and SCL pins in your code. Wire.begin() will correctly set the pin modes for I2C operation. :wink:

4 Likes

Great help! I’ve got it working with the correct wiring (I2C connected to D0/D1 and using the Wire.begin() code)

I’ve also made some modifications to the libraries, removing some Arduino-specific code and replacing with Particle code. So far so good.

I’m getting readings for Shunt Current and Voltage, but no readings for Bus Voltage and Power.

Here’s the wiring…

I’ve set up a simple load circuit with a 9V Battery, a 2K ohm Resistor, and an LED. I’m getting a shunt current of 4.4mA, and a shunt voltage of .035mV, which is just about perfect. No readings for Bus Voltage or Bus Power though. Am I missing something in the wiring?

1 Like

For reference, here is the code and libraries I am using, in case it helps with troubleshooting, or in case someone else in the future wants to use them…

current_monitor.ino


/*  Particle Electron current and voltage measurement using the INA226 CJMCU Breakout Board */

// ************************** Libraries Needed To Compile The Script  **************************
        #include <INA226.h> //library for the current and voltage sensor
        #include <Ubidots.h>
        #define TOKEN "mytoken"  // Your unique Ubidots TOKEN.   Do not share this token publicly.
        Ubidots ubidots(TOKEN);

// ************ INA226 Current and Voltage Monitor Definitions *****************************************
    INA226 ina;
    const int CurrentSensorPowerPin=B0; //current and voltage sensor power pin 
    const int CurrentSensorGndPin =B1;  //current and voltage sensor GROUND pin 
    //const int CurrentSensorSDAPin =D0;  //I2C communication pin 
    //const int CurrentSensorSCLPin =D1;  //I2C communication pin  
    const int LightPin =D7;  // light for debugging  

    float shuntcurrentA=0; //i7nitalize variables for INA226
    float shuntvoltageV=0;
    float busvoltageV=0;
    float buspowerW=0;

    int Reading_Delay_milliseconds=15000;  // delay between readings in milliseconds.  

// *********************************Setup - runs Once and sets pins etc ******************************************************
void setup()
{
  //SET UP PINS FOR SENSORS:
  //Serial.begin(9600); // only used for wired connection serial communication 
 
  pinMode(CurrentSensorPowerPin , OUTPUT); // set the powerpin as an output
    digitalWrite(CurrentSensorPowerPin , HIGH); //Turn it on for now
  pinMode(CurrentSensorGndPin , OUTPUT);//setting pin for ground for the EC sensor as an ouput
    digitalWrite(CurrentSensorGndPin,LOW);//We can leave the ground connected permanantly
  pinMode(LightPin , OUTPUT); // set the lightpin as an output (for troubleshooting)


  // Initialize INA226 Current & Voltage Sensor.  Default INA226 address is 0x40
  delay(500);// gives sensor time to settle
  ina.begin();
  // Configure INA226:
  ina.configure(INA226_AVERAGES_1, INA226_BUS_CONV_TIME_1100US, INA226_SHUNT_CONV_TIME_1100US, INA226_MODE_SHUNT_BUS_CONT);
  // Calibrate INA226. (Rshunt = 0.01 ohm, Max excepted current = 4A) (Rshunt = .008 ohm, Max current=11A):
  ina.calibrate(0.008, 11);
 };  // ******************************************* End of Setup **********************************************************************
 
 
 
// *******************************************************************************************************************
// ************************************* Main Loop - Runs Forever ****************************************************
// *******************************************************************************************************************
    // The main loop is run repeatedly.  It calls functions for taking sensor readings, printing results, etc.
void loop()
    {
    digitalWrite(LightPin , HIGH); //Turn on light
    GetCurrent();       //Calls code to get current and voltage
    PrintReadings();    // Calls Print routine [below main loop]
    digitalWrite(LightPin , LOW); //Turn off light
    delay(Reading_Delay_milliseconds); //delay between readings in milliseconds. 
    
    };
// *******************************************************************************************************************
// ************************************** End Of Main Loop ***********************************************************
// *******************************************************************************************************************


// ************  GetCurrent Function (This Loop Is called From Main Loop)********************************************************
void GetCurrent(){
// reads current and voltage from the INA219 or INA229 sensor
 
  shuntcurrentA=ina.readShuntCurrent();
  shuntvoltageV=ina.readShuntVoltage();
  busvoltageV=ina.readBusVoltage();
  buspowerW=ina.readBusPower();
  delay(500);
};


// ****** Send Readings Function (This is where useful data is sent to the desired location) ******
void PrintReadings(){
    ubidots.add("Current_A", shuntcurrentA);
    ubidots.add("Shunt_Voltage_V", shuntvoltageV);
    ubidots.add("Bus_Voltage_V", busvoltageV);
    ubidots.add("buspowerW", buspowerW);    
    ubidots.sendAll();      //send the variables to Ubidots
    
};  // *********************** END OF PROGRAM ************************

INA226.h

/*
INA226.h - Header file for the 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/>.
*/

#ifndef INA226_h
#define INA226_h


    //#if ARDUINO >= 100
    //#include "Arduino.h"
    //#else
    //#include "WProgram.h"
    //#endif

#include "Particle.h" 


#define INA226_ADDRESS              (0x40)

#define INA226_REG_CONFIG           (0x00)
#define INA226_REG_SHUNTVOLTAGE     (0x01)
#define INA226_REG_BUSVOLTAGE       (0x02)
#define INA226_REG_POWER            (0x03)
#define INA226_REG_CURRENT          (0x04)
#define INA226_REG_CALIBRATION      (0x05)
#define INA226_REG_MASKENABLE       (0x06)
#define INA226_REG_ALERTLIMIT       (0x07)

#define INA226_BIT_SOL              (0x8000)
#define INA226_BIT_SUL              (0x4000)
#define INA226_BIT_BOL              (0x2000)
#define INA226_BIT_BUL              (0x1000)
#define INA226_BIT_POL              (0x0800)
#define INA226_BIT_CNVR             (0x0400)
#define INA226_BIT_AFF              (0x0010)
#define INA226_BIT_CVRF             (0x0008)
#define INA226_BIT_OVF              (0x0004)
#define INA226_BIT_APOL             (0x0002)
#define INA226_BIT_LEN              (0x0001)

typedef enum
{
    INA226_AVERAGES_1             = 0b000,
    INA226_AVERAGES_4             = 0b001,
    INA226_AVERAGES_16            = 0b010,
    INA226_AVERAGES_64            = 0b011,
    INA226_AVERAGES_128           = 0b100,
    INA226_AVERAGES_256           = 0b101,
    INA226_AVERAGES_512           = 0b110,
    INA226_AVERAGES_1024          = 0b111
} ina226_averages_t;

typedef enum
{
    INA226_BUS_CONV_TIME_140US    = 0b000,
    INA226_BUS_CONV_TIME_204US    = 0b001,
    INA226_BUS_CONV_TIME_332US    = 0b010,
    INA226_BUS_CONV_TIME_588US    = 0b011,
    INA226_BUS_CONV_TIME_1100US   = 0b100,
    INA226_BUS_CONV_TIME_2116US   = 0b101,
    INA226_BUS_CONV_TIME_4156US   = 0b110,
    INA226_BUS_CONV_TIME_8244US   = 0b111
} ina226_busConvTime_t;

typedef enum
{
    INA226_SHUNT_CONV_TIME_140US   = 0b000,
    INA226_SHUNT_CONV_TIME_204US   = 0b001,
    INA226_SHUNT_CONV_TIME_332US   = 0b010,
    INA226_SHUNT_CONV_TIME_588US   = 0b011,
    INA226_SHUNT_CONV_TIME_1100US  = 0b100,
    INA226_SHUNT_CONV_TIME_2116US  = 0b101,
    INA226_SHUNT_CONV_TIME_4156US  = 0b110,
    INA226_SHUNT_CONV_TIME_8244US  = 0b111
} ina226_shuntConvTime_t;

typedef enum
{
    INA226_MODE_POWER_DOWN      = 0b000,
    INA226_MODE_SHUNT_TRIG      = 0b001,
    INA226_MODE_BUS_TRIG        = 0b010,
    INA226_MODE_SHUNT_BUS_TRIG  = 0b011,
    INA226_MODE_ADC_OFF         = 0b100,
    INA226_MODE_SHUNT_CONT      = 0b101,
    INA226_MODE_BUS_CONT        = 0b110,
    INA226_MODE_SHUNT_BUS_CONT  = 0b111,
} ina226_mode_t;

class INA226
{
    public:

	bool begin(uint8_t address = INA226_ADDRESS);
	bool configure(ina226_averages_t avg = INA226_AVERAGES_1, ina226_busConvTime_t busConvTime = INA226_BUS_CONV_TIME_1100US, ina226_shuntConvTime_t shuntConvTime = INA226_SHUNT_CONV_TIME_1100US, ina226_mode_t mode = INA226_MODE_SHUNT_BUS_CONT);
	bool calibrate(float rShuntValue = 0.1, float iMaxExcepted = 2);

	ina226_averages_t getAverages(void);
	ina226_busConvTime_t getBusConversionTime(void);
	ina226_shuntConvTime_t getShuntConversionTime(void);
	ina226_mode_t getMode(void);

	void enableShuntOverLimitAlert(void);
	void enableShuntUnderLimitAlert(void);
	void enableBusOvertLimitAlert(void);
	void enableBusUnderLimitAlert(void);
	void enableOverPowerLimitAlert(void);
	void enableConversionReadyAlert(void);

	void setBusVoltageLimit(float voltage);
	void setShuntVoltageLimit(float voltage);
	void setPowerLimit(float watts);

	void setAlertInvertedPolarity(bool inverted);
	void setAlertLatch(bool latch);

	bool isMathOverflow(void);
	bool isAlert(void);

	float readShuntCurrent(void);
	float readShuntVoltage(void);
	float readBusPower(void);
	float readBusVoltage(void);

	float getMaxPossibleCurrent(void);
	float getMaxCurrent(void);
	float getMaxShuntVoltage(void);
	float getMaxPower(void);

    private:

	int8_t inaAddress;
	float currentLSB, powerLSB;
	float vShuntMax, vBusMax, rShunt;

	void setMaskEnable(uint16_t mask);
	uint16_t getMaskEnable(void);

	void writeRegister16(uint8_t reg, uint16_t val);
	int16_t readRegister16(uint8_t reg);
};

#endif

INA226.cpp

/*
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 "Particle.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();
}

UPDATE: excess #include statements removed from libraries above per ScruffR’s comment.

If you have #include Particle.h you won’t need application.h nor Wire.h.

You can add some Serial.print() statements to print out the factors of your calculations and see which one causes the 0.0 to be returned
e.g.

float INA226::readBusPower(void)
{
    int regPower = readRegister16(INA226_REG_POWER);
    Serial.printlnf("readBusPower: %d * %d = %d", regPower, powerLSB, regPower * powerLSB);
    return regPower * powerLSB;
    //return (readRegister16(INA226_REG_POWER) * powerLSB);
}

And then investigate the reason.
I guess powerLSB isn’t set correctly.

Okay. I removed the excess #include statements and added math.h where needed.

The line:

int regPower = readRegister16(INA226_REG_POWER);
Serial.printlnf("readBusPower: %d * %d = %d", regPower, powerLSB, regPower * powerLSB);

yields the following output:
readBusPower: 0 * 1073741824 = 1065646817

So it looks like readRegister16(INA226_REG_POWER) is yielding zero. Still not clear if this is a wiring issue or a coding issue.

Open to suggestions. (and thanks very much for the help!)

I think you need to connect the V+ and V- to the power supply you’re measuring the current flow of before you can read the supply voltage.

I had a closer look at the library and it turns out powerLSB is a float, so the statement should actually be

 Serial.printlnf("readBusPower: %d * %f = %f", regPower, powerLSB, regPower * powerLSB);

But the interesting part is already in the previous output

The first 0 is your culprit. whatever powerLSB is won't matter since it'll be multiplied by zero rendering the result zero too.

Hmm...

Serial.printlnf("readBusPower: %d * %d = %d", regPower, powerLSB, regPower * powerLSB);

works fine, but

Serial.printlnf(“readBusPower: %d * %f = %f”, regPower, powerLSB, regPower * powerLSB);

gives me a bunch of compile errors.
Still trying to figure out how this library works...

I think you need to connect the V+ and V- to the power supply you’re measuring the current flow of before you can read the supply voltage.

I thought that too, but then I was unsure. It looks like the similar INA219 from Adafruit (which has a lower voltage range) is wired up without using the in+ and in- pins.

Acutally no, that doesn't work fine othwise how could 0 * x not equal 0?
The problem is the misinterpretation of a float variable as an integer (%d).

Would be good to know what comile errors, tho'

But I guess the errors come from the typographic double quotes ( & ) vs. the actual ASCII double quotes (").

1 Like

But I guess the errors come from the typographic double quotes (“ & ”) vs. the actual ASCII double quotes (").

Doh! That fixed the compile errors. Thanks. I noticed something else in the code... The "pow" in powerLSB is a different color. That must mean something...

Nope, that doesn't really mean anything. It's just a glitch in the automatic code highlighting which knows about a math.h function pow() and confuses your variable name for that.
That can safely be ignored :wink:

1 Like

They are different chips. The vin+ and Vin- has an input voltage range of up to 30+ volts which is different than the shunt voltage range.

Thanks RWB. So my modified wiring diagram would look like this:

(incorrect sketch removed to avoid future confusion)

When I switch this over to a 36VDC circuit, I’m surprise the tiny inputs could handle it. The specs say “Senses Bus Voltages From 0 V to 36 V”

I would run that IN- to connect before the first 2K resistor for the most accurate readings.

@RWB, for current, the voltage is measured across the shunt. For voltage, it is measured across the supply. In this case, if you measure before the 2K ohm resistor (on the other side of the shunt), the voltage will include be affected by the voltage drop across the LED.