diff --git a/Adafruit_INA219.cpp b/Adafruit_INA219.cpp index d2b6e6d..3f172a9 100644 --- a/Adafruit_INA219.cpp +++ b/Adafruit_INA219.cpp @@ -89,10 +89,13 @@ void Adafruit_INA219::wireReadRegister(uint8_t reg, uint16_t *value) each unit of power corresponds to 2mW. Counter overflow occurs at 3.2A. + @param triggered : a boolean to configure INA219 in triggered (true) + or continuous (false) mode. Optional with default value false + @note These calculations assume a 0.1 ohm resistor is present */ /**************************************************************************/ -void Adafruit_INA219::setCalibration_32V_2A(void) +void Adafruit_INA219::setCalibration_32V_2A(bool triggered) { // By default we use a pretty huge range for the input voltage, // which probably isn't the most appropriate choice for system @@ -165,11 +168,22 @@ void Adafruit_INA219::setCalibration_32V_2A(void) wireWriteRegister(INA219_REG_CALIBRATION, ina219_calValue); // 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; + uint16_t config; + + if (triggered) { + config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_128S_69MS | + INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED; + } else { + 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; + } + wireWriteRegister(INA219_REG_CONFIG, config); } @@ -180,10 +194,13 @@ void Adafruit_INA219::setCalibration_32V_2A(void) unit of power corresponds to 800�W. Counter overflow occurs at 1.3A. + @param triggered : a boolean to configure INA219 in triggered (true) + or continuous (false) mode. Optional with default value false + @note These calculations assume a 0.1 ohm resistor is present */ /**************************************************************************/ -void Adafruit_INA219::setCalibration_32V_1A(void) +void Adafruit_INA219::setCalibration_32V_1A(bool triggered) { // By default we use a pretty huge range for the input voltage, // which probably isn't the most appropriate choice for system @@ -258,22 +275,38 @@ void Adafruit_INA219::setCalibration_32V_1A(void) wireWriteRegister(INA219_REG_CALIBRATION, ina219_calValue); // 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; + uint16_t config; + + if (triggered) { + config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_8_320MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_128S_69MS | + INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED; + } else { + 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; + } + wireWriteRegister(INA219_REG_CONFIG, config); } /**************************************************************************/ /*! - @brief set device to alibration which uses the highest precision for - current measurement (0.1mA), at the expense of + @brief set device to calibration which uses the highest precision for + current measurement (0.05mA), at the expense of only supporting 16V at 400mA max. + + @param triggered : a boolean to configure INA219 in triggered (true) + or continuous (false) mode. Optional with default value false + + @note These calculations assume a 0.1 ohm resistor is present */ /**************************************************************************/ -void Adafruit_INA219::setCalibration_16V_400mA(void) { +void Adafruit_INA219::setCalibration_16V_400mA(bool triggered) { // Calibration which uses the highest precision for // current measurement (0.1mA), at the expense of @@ -349,11 +382,125 @@ void Adafruit_INA219::setCalibration_16V_400mA(void) { wireWriteRegister(INA219_REG_CALIBRATION, ina219_calValue); // Set Config register to take into account the settings above - uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V | - INA219_CONFIG_GAIN_1_40MV | - INA219_CONFIG_BADCRES_12BIT | - INA219_CONFIG_SADCRES_12BIT_1S_532US | - INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + uint16_t config; + + if (triggered) { + config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_128S_69MS | + INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED; + } else { + config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + } + wireWriteRegister(INA219_REG_CONFIG, config); +} + +/**************************************************************************/ +/*! + @brief set device to calibration which uses the highest precision for + current measurement (0.1mA), Gain 1 and 32V max bus voltage + + @param triggered : a boolean to configure INA219 in triggered (true) + or continuous (false) mode. Optional with default value false + + @note These calculations assume a 0.1 ohm resistor is present +*/ +/**************************************************************************/ +void Adafruit_INA219::setCalibration_32V_400mA(bool triggered) { + + // Calibration which uses the highest precision for + // current measurement (0.1mA) + + // VBUS_MAX = 32V + // VSHUNT_MAX = 0.04 (Assumes Gain 1, 40mV) + // RSHUNT = 0.1 (Resistor value in ohms) + + // 1. Determine max possible current + // MaxPossible_I = VSHUNT_MAX / RSHUNT + // MaxPossible_I = 0.4A + + // 2. Determine max expected current + // MaxExpected_I = 0.4A + + // 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit) + // MinimumLSB = MaxExpected_I/32767 + // MinimumLSB = 0.0000122 (12uA per bit) + // MaximumLSB = MaxExpected_I/4096 + // MaximumLSB = 0.0000977 (98uA per bit) + + // 4. Choose an LSB between the min and max values + // (Preferrably a roundish number close to MinLSB) + // CurrentLSB = 0.00005 (50uA per bit) + + // 5. Compute the calibration register + // Cal = trunc (0.04096 / (Current_LSB * RSHUNT)) + // Cal = 8192 (0x2000) + + ina219_calValue = 8192; + + // 6. Calculate the power LSB + // PowerLSB = 20 * CurrentLSB + // PowerLSB = 0.001 (1mW per bit) + + // 7. Compute the maximum current and shunt voltage values before overflow + // + // Max_Current = Current_LSB * 32767 + // Max_Current = 1.63835A 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_Current_Before_Overflow = MaxPossible_I + // Max_Current_Before_Overflow = 0.4 + // + // Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT + // Max_ShuntVoltage = 0.04V + // + // If Max_ShuntVoltage >= VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Else + // Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage + // End If + // + // Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX + // Max_ShuntVoltage_Before_Overflow = 0.04V + + // 8. Compute the Maximum Power + // MaximumPower = Max_Current_Before_Overflow * VBUS_MAX + // MaximumPower = 0.4 * 32V + // MaximumPower = 12.8W + + // Set multipliers to convert raw current/power values + ina219_currentDivider_mA = 20; // Current LSB = 50uA per bit (1000/50 = 20) + ina219_powerMultiplier_mW = 1.0f; // Power LSB = 1mW per bit + + // Set Calibration register to 'Cal' calculated above + wireWriteRegister(INA219_REG_CALIBRATION, ina219_calValue); + + // Set Config register to take into account the settings above + uint16_t config; + + if (triggered) { + config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_128S_69MS | + INA219_CONFIG_MODE_SANDBVOLT_TRIGGERED; + } else { + config = INA219_CONFIG_BVOLTAGERANGE_32V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS; + } wireWriteRegister(INA219_REG_CONFIG, config); } @@ -517,3 +664,23 @@ float Adafruit_INA219::getPower_mW() { valueDec *= ina219_powerMultiplier_mW; return valueDec; } + +/**************************************************************************/ +/*! + @brief Enter the Power Down mode + using 1 uA instead of 1 mA current in continous mode. + Just call your calibration routine to turn it on again + @return void + +*/ +void Adafruit_INA219::enterPowerSave() { + + uint16_t config = INA219_CONFIG_BVOLTAGERANGE_16V | + INA219_CONFIG_GAIN_1_40MV | + INA219_CONFIG_BADCRES_12BIT | + INA219_CONFIG_SADCRES_12BIT_1S_532US | + INA219_CONFIG_MODE_POWERDOWN; + + wireWriteRegister(INA219_REG_CONFIG, config); + +} \ No newline at end of file diff --git a/Adafruit_INA219.h b/Adafruit_INA219.h index be8cb35..1112c2f 100644 --- a/Adafruit_INA219.h +++ b/Adafruit_INA219.h @@ -213,13 +213,15 @@ class Adafruit_INA219{ Adafruit_INA219(uint8_t addr = INA219_ADDRESS); void begin(void); void begin(TwoWire *theWire); - void setCalibration_32V_2A(void); - void setCalibration_32V_1A(void); - void setCalibration_16V_400mA(void); + void setCalibration_32V_2A(bool triggered = false); + void setCalibration_32V_1A(bool triggered = false); + void setCalibration_16V_400mA(bool triggered = false); + void setCalibration_32V_400mA(bool triggered = false); float getBusVoltage_V(void); float getShuntVoltage_mV(void); float getCurrent_mA(void); float getPower_mW(void); + void enterPowerSave(void); private: TwoWire *_i2c; diff --git a/examples/getcurrent_asynchronous/getcurrent_asynchronous.ino b/examples/getcurrent_asynchronous/getcurrent_asynchronous.ino new file mode 100644 index 0000000..e4f6e4d --- /dev/null +++ b/examples/getcurrent_asynchronous/getcurrent_asynchronous.ino @@ -0,0 +1,66 @@ +/* The difference with getcurrent example is that + * INA219 will not be constantly measuring values but only when triggered by calling the configuration function + * hence it will be measuring for 69 ms every 2 seconds (delay(200) + delay(1800) in this example) + * During the 1800 ms timelap the INA219 is put to power dowm using enterPowerSave() + * It would be particularly helpfull if you put the MCU in sleep mode during this period so both MCU and INA219 would consumme close to 0. + */ + +#include +#include + +Adafruit_INA219 ina219; + + +void setup(void) +{ + Serial.begin(115200); + while (!Serial) { + // will pause Zero, Leonardo, etc until serial console opens + delay(1); + } + + uint32_t currentFrequency; + + Serial.println("Hello!"); + + // Initialize the INA219. + // By default the initialization will use the largest range (32V, 2A). However + // you can call a setCalibration function to change this range (see comments). + ina219.begin(); + + Serial.println("Measuring voltage and current with INA219 ..."); +} + +void loop(void) +{ + float shuntvoltage = 0; + float busvoltage = 0; + float current_mA = 0; + float loadvoltage = 0; + float power_mW = 0; + + // Configuring the INA (in trigger mode) will trigger measurement. Use the appropriate calibration function + ina219.setCalibration_32V_2A(true); + //ina219.setCalibration_32V_1A(true); + //ina219.setCalibration_16V_400mA(true); + + // Some time to do the measurement (more than 69 ms) + delay(200); + + shuntvoltage = ina219.getShuntVoltage_mV(); + busvoltage = ina219.getBusVoltage_V(); + current_mA = ina219.getCurrent_mA(); + power_mW = ina219.getPower_mW(); + loadvoltage = busvoltage + (shuntvoltage / 1000); + + Serial.print("Bus Voltage: "); Serial.print(busvoltage); Serial.println(" V"); + Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV"); + Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V"); + Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA"); + Serial.print("Power: "); Serial.print(power_mW); Serial.println(" mW"); + Serial.println(""); + + // Now INA219 is sleeping, using a couple of uA instead of 1mA + ina219.enterPowerSave(); + delay(1800); +}