From ad294e6b018b89e6b4bf464355bb58b6991cca38 Mon Sep 17 00:00:00 2001 From: Jon Little Date: Mon, 8 Jul 2019 20:55:48 -0500 Subject: [PATCH] Added support for multiple INA219 devices on single I2C buss. --- sonoff/xsns_13_ina219.ino | 111 +++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index 57e4a03a7..662db2209 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -84,20 +84,19 @@ #define INA219_REG_CURRENT (0x04) #define INA219_REG_CALIBRATION (0x05) -uint8_t ina219_type = 0; -uint8_t ina219_address; +uint8_t ina219_type[4] = {0,0,0,0}; uint8_t ina219_addresses[] = { INA219_ADDRESS1, INA219_ADDRESS2, INA219_ADDRESS3, INA219_ADDRESS4 }; uint32_t ina219_cal_value = 0; // The following multiplier is used to convert raw current values to mA, taking into account the current config settings uint32_t ina219_current_divider_ma = 0; -uint8_t ina219_valid = 0; -float ina219_voltage = 0; -float ina219_current = 0; +uint8_t ina219_valid[4] = {0,0,0,0}; +float ina219_voltage[4] = {0,0,0,0}; +float ina219_current[4] = {0,0,0,0}; char ina219_types[] = "INA219"; -bool Ina219SetCalibration(uint8_t mode) +bool Ina219SetCalibration(uint8_t mode, uint16_t addr) { uint16_t config = 0; @@ -120,40 +119,40 @@ bool Ina219SetCalibration(uint8_t mode) break; } // Set Calibration register to 'Cal' calculated above - bool success = I2cWrite16(ina219_address, INA219_REG_CALIBRATION, ina219_cal_value); + bool success = I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); if (success) { // Set Config register to take into account the settings above - I2cWrite16(ina219_address, INA219_REG_CONFIG, config); + I2cWrite16(addr, INA219_REG_CONFIG, config); } return success; } -float Ina219GetShuntVoltage_mV(void) +float Ina219GetShuntVoltage_mV(uint16_t addr) { // raw shunt voltage (16-bit signed integer, so +-32767) - int16_t value = I2cReadS16(ina219_address, INA219_REG_SHUNTVOLTAGE); + int16_t value = I2cReadS16(addr, INA219_REG_SHUNTVOLTAGE); // shunt voltage in mV (so +-327mV) return value * 0.01; } -float Ina219GetBusVoltage_V(void) +float Ina219GetBusVoltage_V(uint16_t addr) { // Shift to the right 3 to drop CNVR and OVF and multiply by LSB // raw bus voltage (16-bit signed integer, so +-32767) - int16_t value = (int16_t)(((uint16_t)I2cReadS16(ina219_address, INA219_REG_BUSVOLTAGE) >> 3) * 4); + int16_t value = (int16_t)(((uint16_t)I2cReadS16(addr, INA219_REG_BUSVOLTAGE) >> 3) * 4); // bus voltage in volts return value * 0.001; } -float Ina219GetCurrent_mA(void) +float Ina219GetCurrent_mA(uint16_t addr) { // Sometimes a sharp load will reset the INA219, which will reset the cal register, // meaning CURRENT and POWER will not be available ... avoid this by always setting // a cal value even if it's an unfortunate extra step - I2cWrite16(ina219_address, INA219_REG_CALIBRATION, ina219_cal_value); + I2cWrite16(addr, INA219_REG_CALIBRATION, ina219_cal_value); // Now we can safely read the CURRENT register! // raw current value (16-bit signed integer, so +-32767) - float value = I2cReadS16(ina219_address, INA219_REG_CURRENT); + float value = I2cReadS16(addr, INA219_REG_CURRENT); value /= ina219_current_divider_ma; // current value in mA, taking into account the config settings and current LSB return value; @@ -161,9 +160,15 @@ float Ina219GetCurrent_mA(void) bool Ina219Read(void) { - ina219_voltage = Ina219GetBusVoltage_V() + (Ina219GetShuntVoltage_mV() / 1000); - ina219_current = Ina219GetCurrent_mA() / 1000; - ina219_valid = SENSOR_MAX_MISS; + for (int i=0; i1) + snprintf_P(name, sizeof(name), PSTR("%s%c%d"), ina219_types, IndexSeparator(), sensor_num); + else + snprintf_P(name, sizeof(name), PSTR("%s"), ina219_types); + if (json) { - ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - ina219_types, voltage, current, power); + ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + name, ina219_addresses[i], voltage, current, power); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); @@ -250,7 +263,7 @@ void Ina219Show(bool json) #endif // USE_DOMOTICZ #ifdef USE_WEBSERVER } else { - WSContentSend_PD(HTTP_SNS_INA219_DATA, voltage, current, power); + WSContentSend_PD(HTTP_SNS_INA219_DATA, name, voltage, name, current, name, power); #endif // USE_WEBSERVER } }