INA3221 3 Channel Voltage Current Sensor Firmware Ported to Photon - Completed

Hey guys I’m needing some help porting the Arduino library for this INA3221 3 channel I2C voltage and current sensor. It’s basically 3 x INA219 sensors in one package.

The Arduino Library is here: https://github.com/switchdoclabs/SDL_Arduino_INA3221

Product page is here: http://www.switchdoc.com/ina3221-breakout-board/

I tried deleting the obvious wire.h and other includes but still get compile errors.

Any help is appreciated greatly :smile:

@RWB, we meet again Mr. Bond :smirk:

In the code, you will see #if ARDUINO >= 100 sections. You wan to keep the code in those sections, delete the #if and the #else and associated code. The only exception is at the top of the file where you will remove the code and replace with `#include “Particle.h”.

In the example, you can remove besides removing Wire.h, change the < > characters in the other #include to double quotes. After that, give compiling a go! :wink:

2 Likes

@peekay123 Yea buddy! Another Arduino to Particle port completed :tada:

It took me a min and some playing around to decode your instructions but I figured it out and learned a few things in the process which is good.

The code is working and I have tested it so this is good news.

I’ll post the code for this INA3221 3 channel voltage + current sensor incase anybody else ever needs to use it:

Here is the .ino file:

//
//   SDL_Arduino_INA3221 Library Test Code
//   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
//   Version 1.1
//   SwitchDoc Labs   January 31, 2015
//
//
// This was designed for SunAirPlus - Solar Power Controller - www.switchdoc.com
//


#include "Particle.h"

#include "SDL_Arduino_INA3221.h"

SDL_Arduino_INA3221 ina3221;

// the three channels of the INA3221 named for SunAirPlus Solar Power Controller channels (www.switchdoc.com)
#define LIPO_BATTERY_CHANNEL 1
#define SOLAR_CELL_CHANNEL 2
#define OUTPUT_CHANNEL 3

void setup(void) 
{
    
  Serial.begin(57600);
  Serial.println("SDA_Arduino_INA3221_Test");
  
  Serial.println("Measuring voltage and current with ina3221 ...");
  ina3221.begin();
}

void loop(void) 
{
  
  Serial.println("------------------------------");
  float shuntvoltage1 = 0;
  float busvoltage1 = 0;
  float current_mA1 = 0;
  float loadvoltage1 = 0;


  busvoltage1 = ina3221.getBusVoltage_V(LIPO_BATTERY_CHANNEL);
  shuntvoltage1 = ina3221.getShuntVoltage_mV(LIPO_BATTERY_CHANNEL);
  current_mA1 = -ina3221.getCurrent_mA(LIPO_BATTERY_CHANNEL);  // minus is to get the "sense" right.   - means the battery is charging, + that it is discharging
  loadvoltage1 = busvoltage1 + (shuntvoltage1 / 1000);
  
  Serial.print("LIPO_Battery Bus Voltage:   "); Serial.print(busvoltage1); Serial.println(" V");
  Serial.print("LIPO_Battery Shunt Voltage: "); Serial.print(shuntvoltage1); Serial.println(" mV");
  Serial.print("LIPO_Battery Load Voltage:  "); Serial.print(loadvoltage1); Serial.println(" V");
  Serial.print("LIPO_Battery Current 1:       "); Serial.print(current_mA1); Serial.println(" mA");
  Serial.println("");

  float shuntvoltage2 = 0;
  float busvoltage2 = 0;
  float current_mA2 = 0;
  float loadvoltage2 = 0;

  busvoltage2 = ina3221.getBusVoltage_V(SOLAR_CELL_CHANNEL);
  shuntvoltage2 = ina3221.getShuntVoltage_mV(SOLAR_CELL_CHANNEL);
  current_mA2 = -ina3221.getCurrent_mA(SOLAR_CELL_CHANNEL);
  loadvoltage2 = busvoltage2 + (shuntvoltage2 / 1000);
  
  Serial.print("Solar Cell Bus Voltage 2:   "); Serial.print(busvoltage2); Serial.println(" V");
  Serial.print("Solar Cell Shunt Voltage 2: "); Serial.print(shuntvoltage2); Serial.println(" mV");
  Serial.print("Solar Cell Load Voltage 2:  "); Serial.print(loadvoltage2); Serial.println(" V");
  Serial.print("Solar Cell Current 2:       "); Serial.print(current_mA2); Serial.println(" mA");
  Serial.println("");

  float shuntvoltage3 = 0;
  float busvoltage3 = 0;
  float current_mA3 = 0;
  float loadvoltage3 = 0;

  busvoltage3 = ina3221.getBusVoltage_V(OUTPUT_CHANNEL);
  shuntvoltage3 = ina3221.getShuntVoltage_mV(OUTPUT_CHANNEL);
  current_mA3 = ina3221.getCurrent_mA(OUTPUT_CHANNEL);
  loadvoltage3 = busvoltage3 + (shuntvoltage3 / 1000);
  
  Serial.print("Output Bus Voltage 3:   "); Serial.print(busvoltage3); Serial.println(" V");
  Serial.print("Output Shunt Voltage 3: "); Serial.print(shuntvoltage3); Serial.println(" mV");
  Serial.print("Output Load Voltage 3:  "); Serial.print(loadvoltage3); Serial.println(" V");
  Serial.print("Output Current 3:       "); Serial.print(current_mA3); Serial.println(" mA");
  Serial.println("");

  delay(1000);
}

Here is the .cpp file:

//
//   SDL_Arduino_INA3221 Library
//   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
//   Version 1.1
//   SwitchDoc Labs   January 31, 2015
//
//



/*
    Initial code from INA219 code (Basically just a core structure left)
    @author   K.Townsend (Adafruit Industries)
	@license  BSD (see BSDlicense.txt)
*/
#include "Particle.h"



#include "SDL_Arduino_INA3221.h"

/**************************************************************************/
/*! 
    @brief  Sends a single command byte over I2C
*/
/**************************************************************************/
void SDL_Arduino_INA3221::wireWriteRegister (uint8_t reg, uint16_t value)
{
  Wire.beginTransmission(INA3221_i2caddr);
  
    Wire.write(reg);                       // Register
    Wire.write((value >> 8) & 0xFF);       // Upper 8-bits
    Wire.write(value & 0xFF);              // Lower 8-bits
 
  Wire.endTransmission();
}

/**************************************************************************/
/*! 
    @brief  Reads a 16 bit values over I2C
*/
/**************************************************************************/
void SDL_Arduino_INA3221::wireReadRegister(uint8_t reg, uint16_t *value)
{

  Wire.beginTransmission(INA3221_i2caddr);
 
    Wire.write(reg);                       // Register
    Wire.endTransmission();
  
  delay(1); // Max 12-bit conversion time is 586us per sample

  Wire.requestFrom(INA3221_i2caddr, (uint8_t)2);  
  
    *value = ((Wire.read() << 8) | Wire.read());
 
}

//
void SDL_Arduino_INA3221::INA3221SetConfig(void)
{
 
 
  // Set Config register to take into account the settings above
  uint16_t config = INA3221_CONFIG_ENABLE_CHAN1 |
                    INA3221_CONFIG_ENABLE_CHAN2 |
                    INA3221_CONFIG_ENABLE_CHAN3 |
                    INA3221_CONFIG_AVG1 |
                    INA3221_CONFIG_VBUS_CT2 |
                    INA3221_CONFIG_VSH_CT2 |
                    INA3221_CONFIG_MODE_2 |
                    INA3221_CONFIG_MODE_1 |
                    INA3221_CONFIG_MODE_0;
  wireWriteRegister(INA3221_REG_CONFIG, config);
}

/**************************************************************************/
/*! 
    @brief  Instantiates a new SDL_Arduino_INA3221 class
*/
/**************************************************************************/
SDL_Arduino_INA3221::SDL_Arduino_INA3221(uint8_t addr, float shuntresistor) {
    
    INA3221_i2caddr = addr;
    INA3221_shuntresistor = shuntresistor;
 
}

/**************************************************************************/
/*! 
    @brief  Setups the HW (defaults to 32V and 2A for calibration values)
*/
/**************************************************************************/
void SDL_Arduino_INA3221::begin() {
  Wire.begin();    
  // Set chip to known config values to start
  INA3221SetConfig();
    
    Serial.print("shut resistor="); Serial.println(INA3221_shuntresistor);
        Serial.print("address="); Serial.println(INA3221_i2caddr);
    
}

/**************************************************************************/
/*! 
    @brief  Gets the raw bus voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t SDL_Arduino_INA3221::getBusVoltage_raw(int channel) {
  uint16_t value;
  wireReadRegister(INA3221_REG_BUSVOLTAGE_1+(channel -1) *2, &value);
//    Serial.print("BusVoltage_raw=");
//    Serial.println(value,HEX);

  // Shift to the right 3 to drop CNVR and OVF and multiply by LSB
  return (int16_t)(value );
}

/**************************************************************************/
/*! 
    @brief  Gets the raw shunt voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t SDL_Arduino_INA3221::getShuntVoltage_raw(int channel) {
  uint16_t value;
  wireReadRegister(INA3221_REG_SHUNTVOLTAGE_1+(channel -1) *2, &value);
   // Serial.print("ShuntVoltage_raw=");
   // Serial.println(value,HEX);
  return (int16_t)value;
}


 
/**************************************************************************/
/*! 
    @brief  Gets the shunt voltage in mV (so +-168.3mV)
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getShuntVoltage_mV(int channel) {
  int16_t value;
  value = getShuntVoltage_raw(channel);
  return value * 0.005;
}

/**************************************************************************/
/*! 
    @brief  Gets the shunt voltage in volts
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getBusVoltage_V(int channel) {
  int16_t value = getBusVoltage_raw(channel);
  return value * 0.001;
}

/**************************************************************************/
/*! 
    @brief  Gets the current value in mA, taking into account the
            config settings and current LSB
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getCurrent_mA(int channel) {
    float valueDec = getShuntVoltage_mV(channel)/INA3221_shuntresistor;
  
  return valueDec;
}

Here is the .H file:

//
//   SDL_Arduino_INA3221 Library
//   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
//   Version 1.1
//   SwitchDoc Labs   January 31, 2015
//
//

/**************************************************************************/
/*! 
    Initial code from INA219 code (Basically just a core structure left)
    @author   K. Townsend (Adafruit Industries)
	@license  BSD (see BSDlicense.txt)
	
	*/
/**************************************************************************/


#include "Particle.h"


/*=========================================================================
    I2C ADDRESS/BITS
    -----------------------------------------------------------------------*/
    #define INA3221_ADDRESS                         (0x40)    // 1000000 (A0+A1=GND)
    #define INA3221_READ                            (0x01)
/*=========================================================================*/

/*=========================================================================
    CONFIG REGISTER (R/W)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_CONFIG                      (0x00)
    /*---------------------------------------------------------------------*/
    #define INA3221_CONFIG_RESET                    (0x8000)  // Reset Bit
	
    #define INA3221_CONFIG_ENABLE_CHAN1             (0x4000)  // Enable Channel 1
    #define INA3221_CONFIG_ENABLE_CHAN2             (0x2000)  // Enable Channel 2
    #define INA3221_CONFIG_ENABLE_CHAN3             (0x1000)  // Enable Channel 3
	
    #define INA3221_CONFIG_AVG2                     (0x0800)  // AVG Samples Bit 2 - See table 3 spec
    #define INA3221_CONFIG_AVG1                     (0x0400)  // AVG Samples Bit 1 - See table 3 spec
    #define INA3221_CONFIG_AVG0                     (0x0200)  // AVG Samples Bit 0 - See table 3 spec

    #define INA3221_CONFIG_VBUS_CT2                 (0x0100)  // VBUS bit 2 Conversion time - See table 4 spec
    #define INA3221_CONFIG_VBUS_CT1                 (0x0080)  // VBUS bit 1 Conversion time - See table 4 spec
    #define INA3221_CONFIG_VBUS_CT0                 (0x0040)  // VBUS bit 0 Conversion time - See table 4 spec

    #define INA3221_CONFIG_VSH_CT2                  (0x0020)  // Vshunt bit 2 Conversion time - See table 5 spec
    #define INA3221_CONFIG_VSH_CT1                  (0x0010)  // Vshunt bit 1 Conversion time - See table 5 spec
    #define INA3221_CONFIG_VSH_CT0                  (0x0008)  // Vshunt bit 0 Conversion time - See table 5 spec

    #define INA3221_CONFIG_MODE_2                   (0x0004)  // Operating Mode bit 2 - See table 6 spec
    #define INA3221_CONFIG_MODE_1                   (0x0002)  // Operating Mode bit 1 - See table 6 spec
    #define INA3221_CONFIG_MODE_0                   (0x0001)  // Operating Mode bit 0 - See table 6 spec

/*=========================================================================*/

/*=========================================================================
    SHUNT VOLTAGE REGISTER (R)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_SHUNTVOLTAGE_1                (0x01)
/*=========================================================================*/

/*=========================================================================
    BUS VOLTAGE REGISTER (R)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_BUSVOLTAGE_1                  (0x02)
/*=========================================================================*/

#define SHUNT_RESISTOR_VALUE  (0.1)   // default shunt resistor value of 0.1 Ohm

class SDL_Arduino_INA3221{
 public:
  SDL_Arduino_INA3221(uint8_t addr = INA3221_ADDRESS, float shuntresistor = SHUNT_RESISTOR_VALUE);
  void begin(void);
  float getBusVoltage_V(int channel);
  float getShuntVoltage_mV(int channel);
  float getCurrent_mA(int channel);

 private:
  uint8_t INA3221_i2caddr;
  float INA3221_shuntresistor;

  
  void wireWriteRegister(uint8_t reg, uint16_t value);
  void wireReadRegister(uint8_t reg, uint16_t *value);
  void INA3221SetConfig(void);
  int16_t getBusVoltage_raw(int channel);
  int16_t getShuntVoltage_raw(int channel);

};
4 Likes

@RWB, did you ever get an INA3221 working?

@brianr Yes I did and here is the code:

.ino code:

    //
    //   SDL_Arduino_INA3221 Library Test Code
    //   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
    //   Version 1.1
    //   SwitchDoc Labs   January 31, 2015
    //
    //
    // This was designed for SunAirPlus - Solar Power Controller - www.switchdoc.com
    //
    
    
    #include "Particle.h"
    
    #include "SDL_Arduino_INA3221.h"
    
    SDL_Arduino_INA3221 ina3221;
    
    // the three channels of the INA3221 named for SunAirPlus Solar Power Controller channels (www.switchdoc.com)
    #define LIPO_BATTERY_CHANNEL 1
    #define SOLAR_CELL_CHANNEL 2
    #define OUTPUT_CHANNEL 3
    
    void setup(void) 
    {
        
      Serial.begin(57600);
      Serial.println("SDA_Arduino_INA3221_Test");
      
      Serial.println("Measuring voltage and current with ina3221 ...");
      ina3221.begin();
    }
    
    void loop(void) 
    {
      
      Serial.println("------------------------------");
      float shuntvoltage1 = 0;
      float busvoltage1 = 0;
      float current_mA1 = 0;
      float loadvoltage1 = 0;
    
    
      busvoltage1 = ina3221.getBusVoltage_V(LIPO_BATTERY_CHANNEL);
      shuntvoltage1 = ina3221.getShuntVoltage_mV(LIPO_BATTERY_CHANNEL);
      current_mA1 = -ina3221.getCurrent_mA(LIPO_BATTERY_CHANNEL);  // minus is to get the "sense" right.   - means the battery is charging, + that it is discharging
      loadvoltage1 = busvoltage1 + (shuntvoltage1 / 1000);
      
      Serial.print("LIPO_Battery Bus Voltage:   "); Serial.print(busvoltage1); Serial.println(" V");
      Serial.print("LIPO_Battery Shunt Voltage: "); Serial.print(shuntvoltage1); Serial.println(" mV");
      Serial.print("LIPO_Battery Load Voltage:  "); Serial.print(loadvoltage1); Serial.println(" V");
      Serial.print("LIPO_Battery Current 1:       "); Serial.print(current_mA1); Serial.println(" mA");
      Serial.println("");
    
      float shuntvoltage2 = 0;
      float busvoltage2 = 0;
      float current_mA2 = 0;
      float loadvoltage2 = 0;
    
      busvoltage2 = ina3221.getBusVoltage_V(SOLAR_CELL_CHANNEL);
      shuntvoltage2 = ina3221.getShuntVoltage_mV(SOLAR_CELL_CHANNEL);
      current_mA2 = -ina3221.getCurrent_mA(SOLAR_CELL_CHANNEL);
      loadvoltage2 = busvoltage2 + (shuntvoltage2 / 1000);
      
      Serial.print("Solar Cell Bus Voltage 2:   "); Serial.print(busvoltage2); Serial.println(" V");
      Serial.print("Solar Cell Shunt Voltage 2: "); Serial.print(shuntvoltage2); Serial.println(" mV");
      Serial.print("Solar Cell Load Voltage 2:  "); Serial.print(loadvoltage2); Serial.println(" V");
      Serial.print("Solar Cell Current 2:       "); Serial.print(current_mA2); Serial.println(" mA");
      Serial.println("");
    
      float shuntvoltage3 = 0;
      float busvoltage3 = 0;
      float current_mA3 = 0;
      float loadvoltage3 = 0;
    
      busvoltage3 = ina3221.getBusVoltage_V(OUTPUT_CHANNEL);
      shuntvoltage3 = ina3221.getShuntVoltage_mV(OUTPUT_CHANNEL);
      current_mA3 = ina3221.getCurrent_mA(OUTPUT_CHANNEL);
      loadvoltage3 = busvoltage3 + (shuntvoltage3 / 1000);
      
      Serial.print("Output Bus Voltage 3:   "); Serial.print(busvoltage3); Serial.println(" V");
      Serial.print("Output Shunt Voltage 3: "); Serial.print(shuntvoltage3); Serial.println(" mV");
      Serial.print("Output Load Voltage 3:  "); Serial.print(loadvoltage3); Serial.println(" V");
      Serial.print("Output Current 3:       "); Serial.print(current_mA3); Serial.println(" mA");
      Serial.println("");
    
      delay(1000);
    }

Here is the .CPP file:

//
//   SDL_Arduino_INA3221 Library
//   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
//   Version 1.1
//   SwitchDoc Labs   January 31, 2015
//
//



/*
    Initial code from INA219 code (Basically just a core structure left)
    @author   K.Townsend (Adafruit Industries)
    @license  BSD (see BSDlicense.txt)
*/
#include "Particle.h"



#include "SDL_Arduino_INA3221.h"

/**************************************************************************/
/*! 
    @brief  Sends a single command byte over I2C
*/
/**************************************************************************/
void SDL_Arduino_INA3221::wireWriteRegister (uint8_t reg, uint16_t value)
{
  Wire.beginTransmission(INA3221_i2caddr);
  
    Wire.write(reg);                       // Register
    Wire.write((value >> 8) & 0xFF);       // Upper 8-bits
    Wire.write(value & 0xFF);              // Lower 8-bits
 
  Wire.endTransmission();
}

/**************************************************************************/
/*! 
    @brief  Reads a 16 bit values over I2C
*/
/**************************************************************************/
void SDL_Arduino_INA3221::wireReadRegister(uint8_t reg, uint16_t *value)
{

  Wire.beginTransmission(INA3221_i2caddr);
 
    Wire.write(reg);                       // Register
    Wire.endTransmission();
  
  delay(1); // Max 12-bit conversion time is 586us per sample

  Wire.requestFrom(INA3221_i2caddr, (uint8_t)2);  
  
    *value = ((Wire.read() << 8) | Wire.read());
 
}

//
void SDL_Arduino_INA3221::INA3221SetConfig(void)
{
 
 
  // Set Config register to take into account the settings above
  uint16_t config = INA3221_CONFIG_ENABLE_CHAN1 |
                    INA3221_CONFIG_ENABLE_CHAN2 |
                    INA3221_CONFIG_ENABLE_CHAN3 |
                    INA3221_CONFIG_AVG1 |
                    INA3221_CONFIG_VBUS_CT2 |
                    INA3221_CONFIG_VSH_CT2 |
                    INA3221_CONFIG_MODE_2 |
                    INA3221_CONFIG_MODE_1 |
                    INA3221_CONFIG_MODE_0;
  wireWriteRegister(INA3221_REG_CONFIG, config);
}

/**************************************************************************/
/*! 
    @brief  Instantiates a new SDL_Arduino_INA3221 class
*/
/**************************************************************************/
SDL_Arduino_INA3221::SDL_Arduino_INA3221(uint8_t addr, float shuntresistor) {
    
    INA3221_i2caddr = addr;
    INA3221_shuntresistor = shuntresistor;
 
}

/**************************************************************************/
/*! 
    @brief  Setups the HW (defaults to 32V and 2A for calibration values)
*/
/**************************************************************************/
void SDL_Arduino_INA3221::begin() {
  Wire.begin();    
  // Set chip to known config values to start
  INA3221SetConfig();
    
    Serial.print("shut resistor="); Serial.println(INA3221_shuntresistor);
        Serial.print("address="); Serial.println(INA3221_i2caddr);
    
}

/**************************************************************************/
/*! 
    @brief  Gets the raw bus voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t SDL_Arduino_INA3221::getBusVoltage_raw(int channel) {
  uint16_t value;
  wireReadRegister(INA3221_REG_BUSVOLTAGE_1+(channel -1) *2, &value);
//    Serial.print("BusVoltage_raw=");
//    Serial.println(value,HEX);

  // Shift to the right 3 to drop CNVR and OVF and multiply by LSB
  return (int16_t)(value );
}

/**************************************************************************/
/*! 
    @brief  Gets the raw shunt voltage (16-bit signed integer, so +-32767)
*/
/**************************************************************************/
int16_t SDL_Arduino_INA3221::getShuntVoltage_raw(int channel) {
  uint16_t value;
  wireReadRegister(INA3221_REG_SHUNTVOLTAGE_1+(channel -1) *2, &value);
   // Serial.print("ShuntVoltage_raw=");
   // Serial.println(value,HEX);
  return (int16_t)value;
}


 
/**************************************************************************/
/*! 
    @brief  Gets the shunt voltage in mV (so +-168.3mV)
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getShuntVoltage_mV(int channel) {
  int16_t value;
  value = getShuntVoltage_raw(channel);
  return value * 0.005;
}

/**************************************************************************/
/*! 
    @brief  Gets the shunt voltage in volts
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getBusVoltage_V(int channel) {
  int16_t value = getBusVoltage_raw(channel);
  return value * 0.001;
}

/**************************************************************************/
/*! 
    @brief  Gets the current value in mA, taking into account the
            config settings and current LSB
*/
/**************************************************************************/
float SDL_Arduino_INA3221::getCurrent_mA(int channel) {
    float valueDec = getShuntVoltage_mV(channel)/INA3221_shuntresistor;
  
  return valueDec;
}

Here is the .H file:

//
//   SDL_Arduino_INA3221 Library
//   SDL_Arduino_INA3221.cpp Arduino code - runs in continuous mode
//   Version 1.1
//   SwitchDoc Labs   January 31, 2015
//
//

/**************************************************************************/
/*! 
    Initial code from INA219 code (Basically just a core structure left)
    @author   K. Townsend (Adafruit Industries)
    @license  BSD (see BSDlicense.txt)
    
    */
/**************************************************************************/


#include "Particle.h"


/*=========================================================================
    I2C ADDRESS/BITS
    -----------------------------------------------------------------------*/
    #define INA3221_ADDRESS                         (0x40)    // 1000000 (A0+A1=GND)
    #define INA3221_READ                            (0x01)
/*=========================================================================*/

/*=========================================================================
    CONFIG REGISTER (R/W)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_CONFIG                      (0x00)
    /*---------------------------------------------------------------------*/
    #define INA3221_CONFIG_RESET                    (0x8000)  // Reset Bit
    
    #define INA3221_CONFIG_ENABLE_CHAN1             (0x4000)  // Enable Channel 1
    #define INA3221_CONFIG_ENABLE_CHAN2             (0x2000)  // Enable Channel 2
    #define INA3221_CONFIG_ENABLE_CHAN3             (0x1000)  // Enable Channel 3
    
    #define INA3221_CONFIG_AVG2                     (0x0800)  // AVG Samples Bit 2 - See table 3 spec
    #define INA3221_CONFIG_AVG1                     (0x0400)  // AVG Samples Bit 1 - See table 3 spec
    #define INA3221_CONFIG_AVG0                     (0x0200)  // AVG Samples Bit 0 - See table 3 spec

    #define INA3221_CONFIG_VBUS_CT2                 (0x0100)  // VBUS bit 2 Conversion time - See table 4 spec
    #define INA3221_CONFIG_VBUS_CT1                 (0x0080)  // VBUS bit 1 Conversion time - See table 4 spec
    #define INA3221_CONFIG_VBUS_CT0                 (0x0040)  // VBUS bit 0 Conversion time - See table 4 spec

    #define INA3221_CONFIG_VSH_CT2                  (0x0020)  // Vshunt bit 2 Conversion time - See table 5 spec
    #define INA3221_CONFIG_VSH_CT1                  (0x0010)  // Vshunt bit 1 Conversion time - See table 5 spec
    #define INA3221_CONFIG_VSH_CT0                  (0x0008)  // Vshunt bit 0 Conversion time - See table 5 spec

    #define INA3221_CONFIG_MODE_2                   (0x0004)  // Operating Mode bit 2 - See table 6 spec
    #define INA3221_CONFIG_MODE_1                   (0x0002)  // Operating Mode bit 1 - See table 6 spec
    #define INA3221_CONFIG_MODE_0                   (0x0001)  // Operating Mode bit 0 - See table 6 spec

/*=========================================================================*/

/*=========================================================================
    SHUNT VOLTAGE REGISTER (R)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_SHUNTVOLTAGE_1                (0x01)
/*=========================================================================*/

/*=========================================================================
    BUS VOLTAGE REGISTER (R)
    -----------------------------------------------------------------------*/
    #define INA3221_REG_BUSVOLTAGE_1                  (0x02)
/*=========================================================================*/

#define SHUNT_RESISTOR_VALUE  (0.1)   // default shunt resistor value of 0.1 Ohm

class SDL_Arduino_INA3221{
 public:
  SDL_Arduino_INA3221(uint8_t addr = INA3221_ADDRESS, float shuntresistor = SHUNT_RESISTOR_VALUE);
  void begin(void);
  float getBusVoltage_V(int channel);
  float getShuntVoltage_mV(int channel);
  float getCurrent_mA(int channel);

 private:
  uint8_t INA3221_i2caddr;
  float INA3221_shuntresistor;

  
  void wireWriteRegister(uint8_t reg, uint16_t value);
  void wireReadRegister(uint8_t reg, uint16_t *value);
  void INA3221SetConfig(void);
  int16_t getBusVoltage_raw(int channel);
  int16_t getShuntVoltage_raw(int channel);

};

This is my first ever project using i2c so please forgive me if this is a stupid question, but would I need to make any changes to this code to make it work with the Electron (vs the photon which you originally wrote it for?). I have it hooked up and running, but doesn’t seem to be successfully communicating with the INA3221.

This is what I see when the INA3221 is powered on and they should be communicating (I plug and unplug peripherals from all of the inputs that I think the INA3221 should be monitoring, but absolutely nothing changes):

5/15/2019 12:40:25.05 [RX] - ------------------------------<CR><LF>
LIPO_Battery Bus Voltage:   -0.00 V<CR><LF>
LIPO_Battery Shunt Voltage: -0.00 mV<CR><LF>
LIPO_Battery Load Voltage:  -0.00 V<CR><LF>
LIPO_Battery Current 1:       0.05 mA<CR><LF>
<CR><LF>
Solar Cell Bus Voltage 2:   -0.00 V<CR><LF>
Solar Cell Shunt Voltage 2: -0.00 mV<CR><LF>
Solar Cell Load Voltage 2:  -0.00 V<CR><LF>
Solar Cell Current 2:       0.05 mA<CR><LF>
<CR><LF>
Output Bus Voltage 3:   -0.00 V<CR><LF>
Output Shunt Voltage 3: -0.00 mV<CR><LF>
Output Load Voltage 3:  -0.00 V<CR><LF>
Output Current 3:       -0.05 mA<CR><LF>
<CR><LF>

I only mention that because I noticed that if I power off the board that the INA3221 is on, it changes and reports like this:

 5/15/2019 12:40:30.13 [RX] - ------------------------------<CR><LF>
LIPO_Battery Bus Voltage:   0.00 V<CR><LF>
LIPO_Battery Shunt Voltage: 0.00 mV<CR><LF>
LIPO_Battery Load Voltage:  0.00 V<CR><LF>
LIPO_Battery Current 1:       0.00 mA<CR><LF>
<CR><LF>
Solar Cell Bus Voltage 2:   0.00 V<CR><LF>
Solar Cell Shunt Voltage 2: 0.00 mV<CR><LF>
Solar Cell Load Voltage 2:  0.00 V<CR><LF>
Solar Cell Current 2:       0.00 mA<CR><LF>
<CR><LF>
Output Bus Voltage 3:   0.00 V<CR><LF>
Output Shunt Voltage 3: 0.00 mV<CR><LF>
Output Load Voltage 3:  0.00 V<CR><LF>
Output Current 3:       0.00 mA<CR><LF>
<CR><LF>

I would test this on a photon if I had one but unfortunately I do not!

1 Like

Update after further investigation:
I un-commented out the BusVoltage_raw, and ShuntVoltage_raw and now I see when the INA3221 is powered on, they return FFFF always, and when it is powered off they return 0 always. Hoping this sparks an idea for someone who might know what is going on here!

And your using my code from this post?

Yes, besides adding some cell connect logic at the beginning. At this point i’m pretty sure that the hardware supplied is either faulty or was set up incorrectly, I was just trying to rule out me missing some simple firmware bit that may be different between this running on photon vs electron! I am going to go test this on the scope now and figure out what is going on haha!

Do you have pull ups on the I2C lines?

@ColinVT, a picture of your setup would be good. How you connect and power things can make or break your setup.

Yes, 10ks on each!

@peekay123 I would have done that right off the bat but unfortunately this is all on in-house boards (retrofitting an older product with the controller board that we use in the newer products haha!) i will come back and update later or tomorrow once I figure out the issue!
EDIT: I still intend on updating this, however a urgent issue came up elsewhere so this has been sidelined for the moment!

Update:
It was faulty hardware! Built and set up the testing hardware myself and it works perfectly, so I’m going to finish this project up and send it back. If they update me with what the issue was with the previous hardware, I will come back and update here!

2 Likes