Error Updating INA219 from 0.1ohm to 0.01 Ohm

Hi,

I'm getting odd results trying to update the Adafruit INA219 software for their breakboard board in the Adafruit_INA219 library to measure 10A for a 0.01ohm resistor. This is using an Arduino Uno Rev2 Wifi.

V_expected = 16.8V
V_max = 32V
current_expected = 10A
current_max = 32A

I am trying to update the calibration function setCalibration_32V_1A() to allow 10A instead of 1A.

I build a resistive load to test the original, unaltered sensor. I wanted around 100mA draw to test, so I built a resistive divider with four 680 OHM 1/2W resistors in parallel, which gave an expected current flow of 96mA with the battery pack voltage at 16.3V.

The original sensor with 0.1 Ohm worked well within the margins I wanted. The results are below.

Bus : 16.19V
Shunt : 10.88mV
Load : 16.2V
Current: 108.6mA
Power : 1760mW

I then unsoldered and resolderwd with this 0.01OHM 1W resistor
https://www.digikey.com/en/products/det ... 1L/2178323

I then build a new function and updated the code in the manner shown below, following the process outlined in the library step-by-step:

void Adafruit_INA219::setCalibration_32V_10A() {
  // By default we use a pretty huge range for the input voltage,
  // which probably isn't the most appropriate choice for system
  // that don't use a lot of power.  But all of the calculations
  // are shown below if you want to change the settings.  You will
  // also need to change any relevant register settings, such as
  // setting the VBUS_MAX to 16V instead of 32V, etc.

  // VBUS_MAX = 32V		(Assumes 32V, can also be set to 16V)
  // VSHUNT_MAX = 0.32	(Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
  // RSHUNT = 0.01			(Resistor value in ohms)

  // 1. Determine max possible current
  // MaxPossible_I = VSHUNT_MAX / RSHUNT
  // MaxPossible_I = 32A

  // 2. Determine max expected current
  // MaxExpected_I = 10.0A

  // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
  // MinimumLSB = MaxExpected_I/32767
  // MinimumLSB = 0.000305             (305uA per bit)
  // MaximumLSB = MaxExpected_I/4096
  // MaximumLSB = 0.00244              (2.44 mA per bit)

  // 4. Choose an LSB between the min and max values
  // CurrentLSB = 0.000400 (400uA per bit)

  // 5. Compute the calibration register
  // Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
  // Cal = 10240 (0x2800)

  ina219_calValue = 10240;

  // 6. Calculate the power LSB
  // PowerLSB = 20 * CurrentLSB
  // PowerLSB = 0.008 (8mW per bit)

  // 7. Compute the maximum current and shunt voltage values before overflow
  //
  // Max_Current = Current_LSB * 32767
  // Max_Current = 13.1068A before overflow
  //
  // If Max_Current > Max_Possible_I then
  //    Max_Current_Before_Overflow = MaxPossible_I
  // Else
  //    Max_Current_Before_Overflow = Max_Current
  // End If
  //
  // ... In this case, we're good though since Max_Current is less than
  // MaxPossible_I
  //
  // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
  // Max_ShuntVoltage = 0.131068V
  //
  // If Max_ShuntVoltage >= VSHUNT_MAX
  //    Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
  // Else
  //    Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
  // End If

  // 8. Compute the Maximum Power
  // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
  // MaximumPower = 13.1068 * 32V
  // MaximumPower = 419.4176W

  // Set multipliers to convert raw current/power values
  ina219_currentDivider_mA = 2.5;    // Current LSB = 400uA per bit (1000/400 = 2.5)
  ina219_powerMultiplier_mW = 8.0f; // Power LSB = 8mW per bit

  // Set Calibration register to 'Cal' calculated above
  Adafruit_BusIO_Register calibration_reg =
      Adafruit_BusIO_Register(i2c_dev, INA219_REG_CALIBRATION, 2, MSBFIRST);
  calibration_reg.write(ina219_calValue, 2);

  // Set Config register to take into account the settings above
  uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
                    INA219_CONFIG_GAIN_8_320MV | INA219_CONFIG_BADCRES_12BIT |
                    INA219_CONFIG_SADCRES_12BIT_1S_532US |
                    INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
  Adafruit_BusIO_Register config_reg =
      Adafruit_BusIO_Register(i2c_dev, INA219_REG_CONFIG, 2, MSBFIRST);
  _success = config_reg.write(config, 2);
}

I placed this sensor in the test rig in exactly the same spot using exactly the same wiring, and received these results.

Bus : 16.22V
Shunt : 2.10mV
Load : 16.22V
Current : 262.50mA
Power : 3426mW

The current values and power values seem to be almost double what they need to be, with an expected shunt drop of 1mV for the 0.01ohm resistor. I had hoped I could simply divide by 2 and call it a day, however this same exact circuit was then tested on a battery analyzer, and the current for a 3000mA draw was measured at 3992mA.

Something in the software setup seems to be incorrect. Can anyone point me in the correct direction?

Update: to rule out the resistor used itself as an issue, I soldered a 0.01OHM 5W radial resistor onto the same spot.
The resistor https://www.digikey.com/en/products/detail/riedon/MSR5-0R01F1/1641093

I got the exact same outputs as I had for the 0.01 1W smd component, within a small margin. This tells me the issue is definitely in the code itself and not the hardware.

I am going crazy trying to figure out why this isn't working, and would appreciate any input.

The tracks on the PCB and the soldered joints add extra resistance in series with your shunt resistor.

When your shunt resistor was 0.1Ω the extra resistance is negligible.

When you change to 0.01Ω the additional resistance becomes more significant.

That calls for a 0.03 ohm shunt.
You should have left the original shunt on the board, and add an external resistor/shunt where most of that 10A current flows through. The traces and screw terminal of the INA are not designed for 10A.
Leo..

This may be a silly question, but is there a simple way to account for this increased resistance? My equipment is unable to measure precisely enough for this value of resistor.

The system design itself is meant to support up to 30A ; a max current of 10A with values from 6A-8A is what I expect to pull from the first test I am doing.

I did not consider the rating of the traces and screw terminal, although that is a very good point. I will likely need to add this external shunt. Can you point to a good resource for this?

I have two more of the INA modules, so can jury rig something together. How would I calculate the Calibration values if there is 0.1ohm on the board and a parallel external shunt (lets say the 0.01 Ohm 5W radial resistor, as I have a handful of these).

I am a bit confused by the current flow through the on-board shunt in this case vs the eternal, and how to set up the software to correctly calculate the resulting current.

Get a 10Amp shunt from ebay (or a 30A shunt). They are all 75mV (at the rated current).
Remove the shunt resistor from the INA board (no resistor), and connect the screw terminal to the small screws of the shunt (Kelvin connection). Set the INA to PGA2 (80mV).

Main current now only flows through the shunt,
with the wires connected to the larger screws of the shunt.

VSHUNT_MAX = 0.08 // 80mV
// RSHUNT = 0.0075 // calculated for 10A (0.075 / 10A)
// RSHUNT = 0.0025 // calculated for 30A (0.075 / 30A)

Leo..

Sadly time is sensitive, and I won't be able to order a large shunt before an initial test result is required. I only have a large 5A and 100A shunt in the lab of the type you're describing.

If I were to place the 0.01OHM 5W in series with the load (with 14G wires), and Kelvin connection to the INA, would that not be similar and potentially work?

Yes, that would also work, as long as you use Kelvin connections.
A shunt is nothing more than a resistor.
Leo..

Software-wise, would the prior implementation work as-is?

I am mostly concerned about these code values

ina219_calValue = 10240;
ina219_currentDivider_mA = 2.5; // Current LSB = 400uA per bit (1000/400 = 2.5)
ina219_powerMultiplier_mW = 8.0f; // Power LSB = 8mW per bit

as I do not know if they are correct for the 0.01 shunt resistor. Do they seem appropriate for using with the kelvin-connected shunt?

Adafruit uses a complicated way of setting PGA and calibration, but values seem ok.
There are always unknown tolerances, so calibration will still be needed.
Leo..

I've already asked a lot of questions, and I sincerely appreciate your responses. How would you recommend calibrating the code values above once I assemble? Run at 1A, 3A, 5A and see the response? Would updating the code for a different R_shunt based on this resulting line be the move?

There is no linearity adjustment, so I think you should calibrate at max expected current (10A?).
Leo..

I think I'm just confused on exactly what "calibrate" means for the INA and the adafruit library I'm using. So I would pull 10A, see the resulting value, then which portion of the setCalibration function would I update based on the results?

Try "new value = actual current /measured current * oldvalue" (10240).
Leo..