This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

INA228: INA228 problem with reading data from the VBUS register

Part Number: INA228

Good day! I plan to use the INA228 in my project. I have a problem with reading data from the VBUS register, the value does not correlate with the real voltage at the VBUS pin. Several ic were used to eliminate the hardware error, but to no avail. All other parameters are calculated and read correctly.

Parameters:

shunt resistance - 0.001 Ohm;
max current - no more than 163.84 A;
number of averaging - 16;
conversion time - 4120 uS (same for all channels);
mode - continuous for all channels (hF);
ADC range - 163.84 mV;
I2C frequency - 400 kHz;
DEVICE_ID - 0x2281.

Used code for VBUS:

#define INA228_VBUS_LSB                      (0.0001953125f)
#define INA228_x_ADDRESS_x_VBUS    (0x05)

uint32_t INA228_x_VBUS;

void INA228::ReadBlock(uint8_t regAddress, uint8_t* receiverPtr, uint8_t length)
{
    Wire.requestFrom(addressI2C, length, regAddress, (uint8_t)1, (uint8_t)true);
    for (uint8_t i = 0; i < length; i++)
    {
        receiverPtr[i] = Wire.read();
    }
}

uint32_t INA228::GetBusVoltage_raw(void)
{
    uint8_t data[3] = { 0 };
    ReadBlock(INA228_x_ADDRESS_x_VBUS, data, 3);
    INA228_x_VBUS = 0x000FFFFF & ( ( (data[0] << 16) | (data[1] << 8) | (data[2]) ) >> 4 );
    return INA228_x_VBUS;
}

float INA228::GetBusVoltage_V(void)
{
    uint32_t raw = GetBusVoltage_raw();
    return (float)(raw * INA228_VBUS_LSB);
}

Used code for VSHUNT (works correctly, for example):

#define INA228_x_ADDRESS_x_VSHUNT    (0x04)
#define INA228_VSH_LSB_WIDE                  (0.0000003125f)
#define INA228_VSH_LSB_NARROW           (0.000000078125f)

typedef enum
{
    INA228_ADC_RANGE_WIDE = 0,
    INA228_ADC_RANGE_NARROW = 1,
} INA228_ADC_RANGE_t;

uint8_t adcRange = INA228_ADC_RANGE_WIDE;
uint32_t INA228_x_VSHUNT;

uint32_t INA228::GetShuntVoltage_raw(void)
{
    uint8_t data[3] = { 0 };
    ReadBlock(INA228_x_ADDRESS_x_VSHUNT, data, 3);
    INA228_x_VSHUNT = 0x000FFFFF & ( ( (data[0] << 16) | (data[1] << 8) | (data[2]) ) >> 4 );
    return INA228_x_VSHUNT;
}

float INA228::GetShuntVoltage_V(void)
{
    float sign = 1.0;
    uint32_t raw = GetShuntVoltage_raw();
    if (raw >> 19)
    {
        raw = ((~raw) & 0x000FFFFF) + 1;
        sign = -1.0;
    }
    if (adcRange == INA228_ADC_RANGE_WIDE)
        return (float)(sign * raw * INA228_VSH_LSB_WIDE);
    else
        return (float)(sign * raw * INA228_VSH_LSB_NARROW);
}

VBUS pin voltage approximately 24.4 V

09:57:10.557 -> --------------------------------------------------
09:57:10.557 -> Measured Values:                                       16bit_16bit_... [binary]
09:57:10.557 ->
09:57:10.557 -> Shunt Voltage:  [Us] = 0.00017438 V          RAW [h/l]: 0_1000111011
09:57:10.557 ->
09:57:10.557 -> Bus Voltage:     ![Ub] = 204.44746398 V     RAW [h/l]: 1111_1111100011111100
09:57:10.557 -> Power/Current: ![Ub] = 24.44157791 V
09:57:10.557 ->
09:57:10.557 -> Temperature:       [T] = 33.95312500 C        RAW [h/l]: 0_1000011111011
09:57:10.557 -> Current:                [I] = 0.17437500 A           RAW [h/l]: 0_1000111100
09:57:10.557 -> Power:                 [P] = 4.26200008 W         RAW [h/l]: 0_1000001111001
09:57:10.557 -> Energy:                [E] = 4.25600004 J          RAW [h/l]: 0_0_0_100010100
09:57:10.557 -> Charge:                [C] = 0.17531249 C         RAW [h/l]: 0_0_0_1001001001

VBUS pin voltage approximately 20.2 V (same load)

10:00:35.521 -> --------------------------------------------------
10:00:35.521 -> Measured Values:                                          16bit_16bit_... [binary]
10:00:35.521 ->
10:00:35.521 -> Shunt Voltage:   [Us] = 0.00007281 V           RAW [h/l]: 0_11101100
10:00:35.521 ->
10:00:35.521 -> Bus Voltage:     ![Ub] = 0.22519531 V           RAW [h/l]: 0_10010011001
10:00:35.521 -> Power/Current: ![Ub] = 20.21631050 V
10:00:35.521 ->
10:00:35.521 -> Temperature:       [T] = 33.85156250 C         RAW [h/l]: 0_1000011101110
10:00:35.521 -> Current:                [I] = 0.07281250 A            RAW [h/l]: 0_11100110
10:00:35.521 -> Power:                 [P] = 1.47200012 W          RAW [h/l]: 0_10110101101
10:00:35.521 -> Energy:                [E] = 1.42400002 J           RAW [h/l]: 0_0_0_1011100
10:00:35.521 -> Charge:               [C] = 0.07156250 C           RAW [h/l]: 0_0_0_11101110

  • Hello,

    To rule out potential software/read errors, can you send a scope shot (ideally with I2C decoding) of the read command and response from the INA228?  Also, it would be good to use a voltmeter to confirm voltage and get a more precise measurement to compare against at the time of conversion. 

    Another way to rule out software/read errors would be to connect your setup to the EVM and read with the GUI to see if the value is correct.  You could even try only using the MCU/firmware that comes with the EVM, and jumper wiring the communication to your setup to see if things work correctly in the GUI.

  • Hi, Mitch! Problem solved! The error consisted in the need for additional casting of the uint8_t type to uint32_t in the GetBusVoltage_raw function to implement the correct shift (data[0], data[1] etc). Reading via I2C was without problems, but an error occurred at the stage of forming a 20-bit register value. Interestingly, all other parameters were read correctly, although the code for receiving the raw data is identical. Sorry to bothered you about a trifling issue)) Thanks and have a nice day))

  • Glad you were able to figure it out!