Need help where to do changes in Adafruit INA219 library

I was using INA219 current sensor module for current measurement but in market module it is measuring upto 10A but i have modified the shunt resistance R100 to R005 that is 0.1 ohm to 5 miliohm so where to change in Adafruit library for measuring current upto 10A

That is a very bad idea, now whenever the library changes you have to also change your special copy. In any case you need to speak to Adafruit as they are the keepers of the library. Perhaps they can tell you a way to accomplish what you want without changing the library.

Hi, @shubham260202

If you want to minimise the shunt resistance, why not use a hall effect current sensor?

Google;

hall effect current sensor arduino 10A

Tom.. :smiley: :+1: :coffee: :australia:

Multiple the returned value by 20? (R100/R005)

Adafruit posted instructions on their web site on how to change the sense resistor and modify the library accordingly.

1 Like

Honestly I don't use the Adafruit library, I created my own library for my stm32 development board in C code. A good library will allow you to specify at least, the shunt resistance and the desired maxCurrent. But taking a look at the Adrafruit library I can tell you the following:

I assume you are using the next library:
Adafruit_INA219

In each INA219 code with arduino, you tipically use the next fragment of code to initialize the device:

  // Initialize the INA219.
  if (! ina219.begin())
  {
    Serial.println("Failed to find INA219 chip");
    while (1) 
    {
      delay(10);
    }
  }

If you see the .cpp file you will notice the begin() method (line 53 of the file) calls the init() method

bool Adafruit_INA219::begin(TwoWire *theWire) {
  if (!i2c_dev) {
    i2c_dev = new Adafruit_I2CDevice(ina219_i2caddr, theWire);
  }

  if (!i2c_dev->begin()) {
    return false;
  }
  init();
  return true;
}

In turn, the init() method (line 68) calls the setCalibration_32V_2A() method (line 192).

void Adafruit_INA219::init() {
  // Set chip to large range config values to start
  setCalibration_32V_2A();
}

And this last one is the method you must modify:

void Adafruit_INA219::setCalibration_32V_2A() {
  // 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.1               (Resistor value in ohms)

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

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

  // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
  // MinimumLSB = MaxExpected_I/32767
  // MinimumLSB = 0.000061              (61uA per bit)
  // MaximumLSB = MaxExpected_I/4096
  // MaximumLSB = 0,000488              (488uA per bit)

  // 4. Choose an LSB between the min and max values
  //    (Preferrably a roundish number close to MinLSB)
  // CurrentLSB = 0.0001 (100uA per bit)

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

  ina219_calValue = 4096;

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

  // 7. Compute the maximum current and shunt voltage values before overflow
  //
  // Max_Current = Current_LSB * 32767
  // Max_Current = 3.2767A before overflow
  //
  // If Max_Current > Max_Possible_I then
  //    Max_Current_Before_Overflow = MaxPossible_I
  // Else
  //    Max_Current_Before_Overflow = Max_Current
  // End If
  //
  // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
  // Max_ShuntVoltage = 0.32V
  //
  // 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 = 3.2 * 32V
  // MaximumPower = 102.4W

  // Set multipliers to convert raw current/power values
  ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10)
  ina219_powerMultiplier_mW = 2; // Power LSB = 1mW per bit (2/1)

  // 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);
}

According to INA219 Datasheet (on page 12), you need to calculate the Current_LSB value (equation 2):

Current_LSB = Maximum Expected Current/2^15 = 10A / 2^15 = 305.175 uA

Now, we use the equation 1
Cal = trunc(0.04096/(Current_LSB * Rshunt)) = trunc(0.04096/(305.175uA * 5mOhm)) = 26843

This is the value you need to change on line 225 of the Adafruit_INA219.cpp file, i.e.:

ina219_calValue = 26843;

However, the INA219 datasheet mentions the following:

The highest resolution for the Current Register (04h) can be obtained by using the smallest allowable Current_LSB based on the maximum expected current as shown in equation 2. While this value yields the highest resolution, it is common to select a value for the Current_LSB to the nearest round number above this value to simplify the conversion of the current register (04h)...

So, we obtained a value for the Current_LSB = 305.175 uA. We can rounded this number to 350uA for example. With this value, the calValue would be calValue = 23405. (I'd use the first value for Current_LSB, however, it depends on each person's consideration.)

Honestly I don't know how they obtain the "multipliers to convert raw current/power values" (I don't know why they use 1000 in the numerator) (line 257):

  // Set multipliers to convert raw current/power values
  ina219_currentDivider_mA = 10; // Current LSB = 100uA per bit (1000/100 = 10)
  ina219_powerMultiplier_mW = 2; // Power LSB = 1mW per bit (2/1)

this value is used to get the current in mA (line 168)

float Adafruit_INA219::getCurrent_mA() {
  float valueDec = getCurrent_raw();  //It's ok
  valueDec /= ina219_currentDivider_mA; // ?
  return valueDec;
}

The datasheet mention that the current value in amperes is obtained multiplying the current register by the programmed Current_LSB, only that. However, they divide the value of the current register by ina219_currentDivider_mA.

if you ask me, I would implement the getCurrent_mA() method as:

float Adafruit_INA219::getCurrent_mA() {
  float rawCurrent= getCurrent_raw();
  current = rawCurrent * Current_LSB; // where Current_LSB = max_expected_current/pow(2,15)
// if you want the current in mA then
current = current * 1000.0;
  return current;
}

Following that logic, the new value for ina219_currentDivider_mA would be (using Current_LSB = 350 uA):

ina219_currentDivider_mA = 1000/350 = 2.857

ina219_currentDivider_mA = 1000/350 = 2.857 // line 257

BUT there is a problem here, this variable was declared as an integer value, not as a float value (see INA219.h) file, line 188.
You could try changing the data type of the ina219_currentDivider_mA from uint32_t to float into the .h file (try it you don't lose anything.)

A couple more things before finish.
You can set the number of samples used when averaging results for the shunt and bus voltages (up to 128 samples!). This would allow more stable values for the shunt and bus voltage as well as the current value without the need to implement some filter in code, you only need to modify the line 265:

  // 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);
}

to

  // 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_128S_69MS |
                    INA219_CONFIG_SADCRES_12BIT_128S_69MS |
                    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);
}

And finally, if you use a 5mOhm resistor, then the maximum drop voltage would be:
V_Rshunt(max) = Rshunt * Imax = 5mOhm * 10A = 50 mV.
You could change the the gain resolution using a range of 80mV (page 19 in the datasheet)


Then, the config value would be:
  // Set Config register to take into account the settings above
  uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
                    INA219_CONFIG_GAIN_2_80MV | INA219_CONFIG_BADCRES_12BIT_128S_69MS |
                    INA219_CONFIG_SADCRES_12BIT_128S_69MS |
                    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);

If you look in the library manager there are other INA219 libraries. Some provide additional functions to what is in the Adafruit library.

(I ended up writing my own because the existing ones didn't have the options I wanted.)