expand xsns_100_ina3221 to optionaly calculate the charge and / or Energy per chanel (#20915)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Update en_GB.h

* Update xsns_100_ina3221.ino

* Add files via upload

* Add files via upload

I hope I have all details now changed ;-))

* Add files via upload

I still found a little detail to beutify ;-)
This commit is contained in:
fb-pilot 2024-03-12 08:12:22 +01:00 committed by GitHub
parent 8b7cd2de44
commit f7ae60a9e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 196 additions and 45 deletions

View File

@ -499,6 +499,10 @@
#define D_JSON_ENERGYMONITOR "EnergyMonitor" #define D_JSON_ENERGYMONITOR "EnergyMonitor"
#define D_JSON_MAXENERGYREACHED "MaxEnergyReached" #define D_JSON_MAXENERGYREACHED "MaxEnergyReached"
// xsns_100_ina3221.ino
#define D_JSON_CHARGE "Charge"
// Commands xdrv_04_light.ino // Commands xdrv_04_light.ino
#define D_SO_CHANNELREMAP "ChannelRemap" // SO37 #define D_SO_CHANNELREMAP "ChannelRemap" // SO37
#define D_SO_MULTIPWM "MultiPWM" // SO68 #define D_SO_MULTIPWM "MultiPWM" // SO68

View File

@ -536,6 +536,11 @@
#define D_ENERGY_YESTERDAY "Energie gestern" #define D_ENERGY_YESTERDAY "Energie gestern"
#define D_ENERGY_TOTAL "Energie gesamt" #define D_ENERGY_TOTAL "Energie gesamt"
// xsns_100_ina3221.ino
#define D_CHARGE "Ladung"
#define D_ENERGY "Energie"
#define D_UNIT_CHARGE "Ah"
// xdrv_27_shutter.ino // xdrv_27_shutter.ino
#define D_OPEN "Öffnen" #define D_OPEN "Öffnen"
#define D_CLOSE "Schliessen" #define D_CLOSE "Schliessen"

View File

@ -535,6 +535,11 @@
#define D_ENERGY_TODAY "Energy Today" #define D_ENERGY_TODAY "Energy Today"
#define D_ENERGY_YESTERDAY "Energy Yesterday" #define D_ENERGY_YESTERDAY "Energy Yesterday"
#define D_ENERGY_TOTAL "Energy Total" #define D_ENERGY_TOTAL "Energy Total"
// xsns_100_ina3221.ino
#define D_UNIT_CHARGE "Ah"
#define D_CHARGE "Charge"
#define D_ENERGY "Energy"
// xdrv_27_shutter.ino // xdrv_27_shutter.ino
#define D_OPEN "Open" #define D_OPEN "Open"

View File

@ -734,6 +734,8 @@ https://rya.nc/tasmota-fingerprint.html"
// #define INA3221_ADDRESS1 // allow to change the 1st address to search for INA3221 to 0x41..0x43 // #define INA3221_ADDRESS1 // allow to change the 1st address to search for INA3221 to 0x41..0x43
// #define INA3221_MAX_COUNT // change the number of devices to search for (default 4). // #define INA3221_MAX_COUNT // change the number of devices to search for (default 4).
// // Both settings together allow to limit searching for INA3221 to only a subset of addresses // // Both settings together allow to limit searching for INA3221 to only a subset of addresses
// #define INA3221_CALC_CHARGE_AH // calculate charge in Ah
// #define INA3221_CALC_ENERGY_WH // calculate energy in Wh
// #define USE_PMSA003I // [I2cDriver78] Enable PMSA003I Air Quality Sensor (I2C address 0x12) (+1k8 code) // #define USE_PMSA003I // [I2cDriver78] Enable PMSA003I Air Quality Sensor (I2C address 0x12) (+1k8 code)
// #define USE_GDK101 // [I2cDriver79] Enable GDK101 sensor (I2C addresses 0x18 - 0x1B) (+1k2 code) // #define USE_GDK101 // [I2cDriver79] Enable GDK101 sensor (I2C addresses 0x18 - 0x1B) (+1k2 code)
// #define GDK101_SHOW_FW_VERSION // #define GDK101_SHOW_FW_VERSION

View File

@ -1,7 +1,7 @@
/* /*
xsns_100_ina3221.ino - INA3221 3-channels Current Sensor support for Tasmota xsns_100_ina3221.ino - INA3221 3-channels Current Sensor support for Tasmota
Copyright (C) 2021 Barbudor and Theo Arends Copyright (C) 2021 Barbudor and Theo Arends + fb-pilot 2024-3-7
Based on Barbudor's CircuitPython_INA3221 Based on Barbudor's CircuitPython_INA3221
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
@ -30,16 +30,32 @@
* IMPORTANT INFORMATION * IMPORTANT INFORMATION
* By default the driver is enabled to support up to 4 INA3221 from hte above addresse * By default the driver is enabled to support up to 4 INA3221 from hte above addresse
* If you want to enable less addresses in order to use other I2C chip on those addresses you * If you want to enable less addresses in order to use other I2C chip on those addresses you
* can define in your user_config_override.h the following: * can define in your user_config_override.h the following:
* #define INA3221_MAX_COUNT the max number of INA3221 to support * #define INA3221_MAX_COUNT the max number of INA3221 to support
* #define INA3221_ADDRESS1 the I2C address of the 1st INA3221 * #define INA3221_ADDRESS1 the I2C address of the 1st INA3221
* For example to support only 2 INA3221 at addresses 0x41 and 0x42 you can use: * For example to support only 2 INA3221 at addresses 0x41 and 0x42 you can use:
* #define INA3221_MAX_COUNT 2 * #define INA3221_MAX_COUNT 2
* #define INA3221_ADDRESS1 0x41 * #define INA3221_ADDRESS1 0x41
* That would leave 0x40 and 0x42 for other devices * That would leave 0x40 and 0x43 for other devices
* By defining INA3221_CALC_CHARGE_AH INA3221_CALC_ENERGY_WH the driver adds a estimation of
* energies in Ah and Wh to the output, To reset the energie calculation disable tge
* according INA3221 chanel by setting the shunt to 0.0 and enable it again
* For example :
* sensor100 1,0.0,0.1,0.2 and sensor100 1,0.1,0.1,0.2 will reset channel 1
* Nevertheless, hte driver tries to identifiy if the chip as an address is a IN3221 * Nevertheless, hte driver tries to identifiy if the chip as an address is a IN3221
\*********************************************************************************************/ \*********************************************************************************************/
// setup of INA3221 config
#ifndef INA3221_CONFIG_INIT
#define INA3221_CONFIG_INIT INA3221_AVERAGING_16_SAMPLES |\
INA3221_VBUS_CONV_TIME_1MS |\
INA3221_SHUNT_CONV_TIME_1MS
// that results in a complete conversions sequence in 6,6 ms and a slope time of 105,6 ms
#endif
// end of setup of INA3221 config
#define XSNS_100 100 #define XSNS_100 100
#define XI2C_72 72 // See I2CDEVICES.md #define XI2C_72 72 // See I2CDEVICES.md
@ -61,6 +77,8 @@
#error "**** INA3221 bad combination for ADDRESS1 and MAX_COUNT ****" #error "**** INA3221 bad combination for ADDRESS1 and MAX_COUNT ****"
#endif #endif
#define INA3221_NB_CHAN (3) #define INA3221_NB_CHAN (3)
// Config register - ch : 0..2 // Config register - ch : 0..2
@ -71,13 +89,13 @@
#define INA3221_ENABLE_CH(ch) (0x4000>>(ch)) // default: set #define INA3221_ENABLE_CH(ch) (0x4000>>(ch)) // default: set
#define INA3221_AVERAGING_MASK (0x0E00) #define INA3221_AVERAGING_MASK (0x0E00)
#define INA3221_AVERAGING_NONE (0x0000) // 1 sample, default #define INA3221_AVERAGING_NONE (0x0000)
#define INA3221_AVERAGING_4_SAMPLES (0x0200) #define INA3221_AVERAGING_4_SAMPLES (0x0200)
#define INA3221_AVERAGING_16_SAMPLES (0x0400) #define INA3221_AVERAGING_16_SAMPLES (0x0400)
#define INA3221_AVERAGING_64_SAMPLES (0x0600) #define INA3221_AVERAGING_64_SAMPLES (0x0600)
#define INA3221_AVERAGING_128_SAMPLES (0x0800) #define INA3221_AVERAGING_128_SAMPLES (0x0800)
#define INA3221_AVERAGING_256_SAMPLES (0x0A00) #define INA3221_AVERAGING_256_SAMPLES (0x0A00)
#define INA3221_AVERAGING_512_SAMPLES (0x0C00) #define INA3221_AVERAGING_512_SAMPLES (0x0C00) // 1 sample
#define INA3221_AVERAGING_1024_SAMPLES (0x0E00) #define INA3221_AVERAGING_1024_SAMPLES (0x0E00)
#define INA3221_VBUS_CONV_TIME_MASK (0x01C0) #define INA3221_VBUS_CONV_TIME_MASK (0x01C0)
@ -85,7 +103,7 @@
#define INA3221_VBUS_CONV_TIME_204US (0x0040) #define INA3221_VBUS_CONV_TIME_204US (0x0040)
#define INA3221_VBUS_CONV_TIME_332US (0x0080) #define INA3221_VBUS_CONV_TIME_332US (0x0080)
#define INA3221_VBUS_CONV_TIME_588US (0x00C0) #define INA3221_VBUS_CONV_TIME_588US (0x00C0)
#define INA3221_VBUS_CONV_TIME_1MS (0x0100) // 1.1ms, default #define INA3221_VBUS_CONV_TIME_1MS (0x0100) // 1.1ms
#define INA3221_VBUS_CONV_TIME_2MS (0x0140) // 2.116ms #define INA3221_VBUS_CONV_TIME_2MS (0x0140) // 2.116ms
#define INA3221_VBUS_CONV_TIME_4MS (0x0180) // 4.156ms #define INA3221_VBUS_CONV_TIME_4MS (0x0180) // 4.156ms
#define INA3221_VBUS_CONV_TIME_8MS (0x01C0) // 8.244ms #define INA3221_VBUS_CONV_TIME_8MS (0x01C0) // 8.244ms
@ -95,7 +113,7 @@
#define INA3221_SHUNT_CONV_TIME_204US (0x0008) #define INA3221_SHUNT_CONV_TIME_204US (0x0008)
#define INA3221_SHUNT_CONV_TIME_332US (0x0010) #define INA3221_SHUNT_CONV_TIME_332US (0x0010)
#define INA3221_SHUNT_CONV_TIME_588US (0x0018) #define INA3221_SHUNT_CONV_TIME_588US (0x0018)
#define INA3221_SHUNT_CONV_TIME_1MS (0x0020) // 1.1ms, default #define INA3221_SHUNT_CONV_TIME_1MS (0x0020) // 1.1ms
#define INA3221_SHUNT_CONV_TIME_2MS (0x0028) // 2.116ms #define INA3221_SHUNT_CONV_TIME_2MS (0x0028) // 2.116ms
#define INA3221_SHUNT_CONV_TIME_4MS (0x0030) // 4.156ms #define INA3221_SHUNT_CONV_TIME_4MS (0x0030) // 4.156ms
#define INA3221_SHUNT_CONV_TIME_8MS (0x0038) // 8.244ms #define INA3221_SHUNT_CONV_TIME_8MS (0x0038) // 8.244ms
@ -108,7 +126,7 @@
#define INA3221_MODE_POWER_DOWN2 (0x0004) #define INA3221_MODE_POWER_DOWN2 (0x0004)
#define INA3221_MODE_SHUNT_VOLTAGE_CONTINUOUS (0x0005) #define INA3221_MODE_SHUNT_VOLTAGE_CONTINUOUS (0x0005)
#define INA3221_MODE_BUS_VOLTAGE_CONTINUOUS (0x0006) #define INA3221_MODE_BUS_VOLTAGE_CONTINUOUS (0x0006)
#define INA3221_MODE_SHUNT_AND_BUS_CONTINOUS (0x0007) #define INA3221_MODE_SHUNT_AND_BUS_CONTINOUS (0x0007) // default
// Other registers - ch = 0..2 // Other registers - ch = 0..2
#define INA3221_REG_SHUNT_VOLTAGE_CH(ch) (0x01+((ch)<<1)) #define INA3221_REG_SHUNT_VOLTAGE_CH(ch) (0x01+((ch)<<1))
@ -145,6 +163,8 @@
#define INA3221C_SHUNT_ADC_LSB (0.00004) // VShunt ADC LSB is 40µV #define INA3221C_SHUNT_ADC_LSB (0.00004) // VShunt ADC LSB is 40µV
#define INA3221_DEFAULT_SHUNT_RESISTOR (0.1) #define INA3221_DEFAULT_SHUNT_RESISTOR (0.1)
#define INA3221_ENERGY_FACTOR (1.0/(3600.0*1000.0)) // reading values all xx ms
#ifdef DEBUG_TASMOTA_SENSOR #ifdef DEBUG_TASMOTA_SENSOR
// temporary strings for floating point in debug messages // temporary strings for floating point in debug messages
char _ina3221_dbg1[FLOATSZ]; char _ina3221_dbg1[FLOATSZ];
@ -154,10 +174,21 @@ char _ina3221_dbg2[FLOATSZ];
const char INA3221_SENSORCMND_START[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":{\"idx\":%d,\"addr\":\"0x%02X\",\"rshunt\":["; const char INA3221_SENSORCMND_START[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":{\"idx\":%d,\"addr\":\"0x%02X\",\"rshunt\":[";
const char INA3221_SENSORCMND_END[] PROGMEM = "]}}"; const char INA3221_SENSORCMND_END[] PROGMEM = "]}}";
#if defined(INA3221_CALC_CHARGE_AH) || defined(INA3221_CALC_ENERGY_WH)
uint32_t INA3221_last_millis;
uint32_t INA3221_delta_ms;
#endif
struct INA3221_Channel_Data { struct INA3221_Channel_Data {
float voltage; float voltage;
float current; float current;
float shunt; float shunt;
#ifdef INA3221_CALC_CHARGE_AH
float charge_ah;
#endif
#ifdef INA3221_CALC_ENERGY_WH
float energy_wh;
#endif
}; };
struct INA3221_Data { struct INA3221_Data {
@ -188,10 +219,8 @@ bool Ina3221SetConfig(uint8_t addr)
// write default configuration // write default configuration
uint16_t config = INA3221_ENABLE_MASK | uint16_t config = INA3221_ENABLE_MASK |
INA3221_AVERAGING_16_SAMPLES | INA3221_CONFIG_INIT |
INA3221_VBUS_CONV_TIME_1MS | INA3221_MODE_BUS_VOLTAGE_CONTINUOUS;
INA3221_SHUNT_CONV_TIME_1MS |
INA3221_MODE_SHUNT_AND_BUS_CONTINOUS;
DEBUG_SENSOR_LOG(PSTR(D_INA3221 ":SetConfig: addr:0x%02X, config=0x%04X"), addr, config); DEBUG_SENSOR_LOG(PSTR(D_INA3221 ":SetConfig: addr:0x%02X, config=0x%04X"), addr, config);
// Set Config register // Set Config register
if (!I2cWrite16(addr, INA3221_REG_CONFIG, config)) if (!I2cWrite16(addr, INA3221_REG_CONFIG, config))
@ -218,10 +247,17 @@ bool Ina3221PowerDown(uint8_t device)
void Ina3221SetShunt(uint8_t device, uint8_t channel, float shunt) void Ina3221SetShunt(uint8_t device, uint8_t channel, float shunt)
{ {
Ina3221Data[device].chan[channel].shunt = shunt; Ina3221Data[device].chan[channel].shunt = shunt;
if (shunt > 0.0) if (shunt > 0.0){
Ina3221Data[device].enabled_chan |= (1<<channel); Ina3221Data[device].enabled_chan |= (1<<channel);
else }else{
Ina3221Data[device].enabled_chan &= ~(1<<channel); Ina3221Data[device].enabled_chan &= ~(1<<channel);
#ifdef INA3221_CALC_CHARGE_AH
Ina3221Data[device].chan[channel].charge_ah =0.0;
#endif
#ifdef INA3221_CALC_ENERGY_WH
Ina3221Data[device].chan[channel].energy_wh =0.0;
#endif
}
} }
bool Ina3221Read(uint8_t device, uint8_t channel) bool Ina3221Read(uint8_t device, uint8_t channel)
@ -240,8 +276,20 @@ bool Ina3221Read(uint8_t device, uint8_t channel)
DEBUG_SENSOR_LOG(D_INA3221 ":GetShuntVoltage: RegSh[%d:%d](0x%02X) = 0x%04X = %d", device, channel, INA3221_REG_SHUNT_VOLTAGE_CH(channel), shunt_voltage, shunt_voltage); DEBUG_SENSOR_LOG(D_INA3221 ":GetShuntVoltage: RegSh[%d:%d](0x%02X) = 0x%04X = %d", device, channel, INA3221_REG_SHUNT_VOLTAGE_CH(channel), shunt_voltage, shunt_voltage);
// convert to shunt voltage in V // convert to shunt voltage in V
pChannel->current = INA3221C_SHUNT_ADC_LSB * (float)(shunt_voltage >> 3) / pChannel->shunt; pChannel->current = INA3221C_SHUNT_ADC_LSB * (float)(shunt_voltage >> 3) / pChannel->shunt;
#ifdef INA3221_CALC_CHARGE_AH
pChannel->charge_ah += (pChannel->current * (float)INA3221_delta_ms * INA3221_ENERGY_FACTOR);
#endif
#ifdef INA3221_CALC_ENERGY_WH
pChannel->energy_wh += (pChannel->current * pChannel->voltage * (float)INA3221_delta_ms * INA3221_ENERGY_FACTOR);
#endif
} else { } else {
pChannel->current = INFINITY; pChannel->current = INFINITY;
#ifdef INA3221_CALC_CHARGE_AH
pChannel->charge_ah = INFINITY;
#endif
#ifdef INA3221_CALC_ENERGY_WH
pChannel->energy_wh = INFINITY;
#endif
} }
#ifdef DEBUG_TASMOTA_SENSOR #ifdef DEBUG_TASMOTA_SENSOR
@ -318,6 +366,9 @@ void Ina3221Detect(void)
free(Ina3221Data); free(Ina3221Data);
Ina3221Data = nullptr; Ina3221Data = nullptr;
} }
#if defined(INA3221_CALC_CHARGE_AH) || defined(INA3221_CALC_ENERGY_WH)
INA3221_last_millis = millis();
#endif
} }
void Ina3221Every250ms(void) void Ina3221Every250ms(void)
@ -327,18 +378,41 @@ void Ina3221Every250ms(void)
for (int chan = 0 ; enabled_chan ; chan++, enabled_chan>>=1) { for (int chan = 0 ; enabled_chan ; chan++, enabled_chan>>=1) {
if (0x01 & enabled_chan) if (0x01 & enabled_chan)
Ina3221Read(_ina3221_current_device, chan); Ina3221Read(_ina3221_current_device, chan);
} }
if (++_ina3221_current_device >= INA3221_MAX_COUNT) if (++_ina3221_current_device >= INA3221_MAX_COUNT){
_ina3221_current_device = 0; _ina3221_current_device = 0;
#if defined(INA3221_CALC_CHARGE_AH) || defined(INA3221_CALC_ENERGY_WH)
INA3221_delta_ms = millis()-INA3221_last_millis;
INA3221_last_millis = millis();
#endif
}
} }
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
// {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#define INA3221_AL "<td style='text-align:right'>"
const char HTTP_SNS_INA3221_HEADER[] PROGMEM = const char HTTP_SNS_INA3221_HEADER[] PROGMEM =
"{s}" D_INA3221 "&nbsp;&nbsp;&nbsp;&nbsp;</th><td>&nbsp;</td><td style='text-align:right'>" D_VOLTAGE " </td><td>&nbsp;</td><td style='text-align:right'>" D_CURRENT " </td><td>&nbsp;</td><td style='text-align:right'>" D_POWERUSAGE " {e}"; // "{s}" D_INA3221 "&nbsp;&nbsp;&nbsp;&nbsp;</th><td>&nbsp;</td><td style='text-align:right'>" D_VOLTAGE " </td><td>&nbsp;</td><td style='text-align:right'>" D_CURRENT " </td><td>&nbsp;</td><td style='text-align:right'>" D_POWERUSAGE
"{s}" D_INA3221 "&nbsp;&nbsp;&nbsp;&nbsp;</th>" INA3221_AL D_VOLTAGE " </td><td>&nbsp;</td>" INA3221_AL D_CURRENT " </td><td>&nbsp;</td>" INA3221_AL D_POWERUSAGE
#ifdef INA3221_CALC_CHARGE_AH
"</td><td>&nbsp;</td>" INA3221_AL D_CHARGE
#endif
#ifdef INA3221_CALC_ENERGY_WH
"</td><td>&nbsp;</td>" INA3221_AL D_ENERGY
#endif
"{e}";
const char HTTP_SNS_INA3221_DATA[] PROGMEM = const char HTTP_SNS_INA3221_DATA[] PROGMEM =
"{s}%s </th></th><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_VOLT " </td><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_AMPERE " </td><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_WATT " {e}"; // "{s}%s </th></th><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_VOLT " </td><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_AMPERE " </td><td>&nbsp;</td><td style='text-align:right'>%s " D_UNIT_WATT
"{s}%s </th></th>" INA3221_AL " %s " D_UNIT_VOLT " </td><td>&nbsp;</td>" INA3221_AL " %s " D_UNIT_AMPERE " </td><td>&nbsp;</td>" INA3221_AL " %s " D_UNIT_WATT
#ifdef INA3221_CALC_CHARGE_AH
"</td><td>&nbsp;</td>" INA3221_AL " %s " D_UNIT_CHARGE
#endif
#ifdef INA3221_CALC_ENERGY_WH
"</td><td>&nbsp;</td>" INA3221_AL " %s " D_UNIT_WATTHOUR
#endif
"{e}";
#endif // USE_WEBSERVER #endif // USE_WEBSERVER
void Ina3221Show(bool json) void Ina3221Show(bool json)
@ -348,6 +422,12 @@ void Ina3221Show(bool json)
char voltage[3*FLOATSZ+3]; char voltage[3*FLOATSZ+3];
char current[3*FLOATSZ+3]; char current[3*FLOATSZ+3];
char power[3*FLOATSZ+3]; char power[3*FLOATSZ+3];
#ifdef INA3221_CALC_CHARGE_AH
char charge_ah[3*FLOATSZ+3];
#endif
#ifdef INA3221_CALC_ENERGY_WH
char energy_wh[3*FLOATSZ+3];
#endif
if (json) { if (json) {
// data // data
@ -355,34 +435,75 @@ void Ina3221Show(bool json)
uint8_t enabled_chan = Ina3221Data[device].enabled_chan; uint8_t enabled_chan = Ina3221Data[device].enabled_chan;
if (!enabled_chan) continue; if (!enabled_chan) continue;
if (Ina3221count > 1) if (Ina3221count > 1){
snprintf_P(name, sizeof(name), PSTR("%s%c%d"), INA3221_TYPE, IndexSeparator(), device +1); snprintf_P(name, sizeof(name), PSTR("%s%c%d"), INA3221_TYPE, IndexSeparator(), device +1);
else }
else{
snprintf_P(name, sizeof(name), PSTR("%s"), INA3221_TYPE); snprintf_P(name, sizeof(name), PSTR("%s"), INA3221_TYPE);
voltage[0] = current[0] = power[0] = '\0'; voltage[0] = current[0] = power[0] =
#ifdef INA3221_CALC_CHARGE_AH
charge_ah[0] =
#endif
#ifdef INA3221_CALC_ENERGY_WH
energy_wh[0] =
#endif
'\0';
}
for (int chan=0 ; enabled_chan ; chan++, enabled_chan>>=1) { for (int chan=0 ; enabled_chan ; chan++, enabled_chan>>=1) {
if (0x01 & enabled_chan) { if (0x01 & enabled_chan) {
dtostrfd(Ina3221Data[device].chan[chan].voltage, Settings->flag2.voltage_resolution, temp); dtostrfd(Ina3221Data[device].chan[chan].voltage, Settings->flag2.voltage_resolution, temp);
strncat(voltage, temp, sizeof(voltage)); strncat(voltage, temp, sizeof(voltage));
dtostrfd(Ina3221Data[device].chan[chan].current, Settings->flag2.current_resolution, temp); dtostrfd(Ina3221Data[device].chan[chan].current, Settings->flag2.current_resolution, temp);
strncat(current, temp, sizeof(voltage)); strncat(current, temp, sizeof(current));
dtostrfd(Ina3221Data[device].chan[chan].voltage * Ina3221Data[device].chan[chan].current, Settings->flag2.wattage_resolution, temp); dtostrfd(Ina3221Data[device].chan[chan].voltage * Ina3221Data[device].chan[chan].current, Settings->flag2.wattage_resolution, temp);
strncat(power, temp, sizeof(voltage)); strncat(power, temp, sizeof(power));
} //if enabled #ifdef INA3221_CALC_CHARGE_AH
else { dtostrfd(Ina3221Data[device].chan[chan].charge_ah, Settings->flag2.energy_resolution, temp);
strncat(charge_ah, temp, sizeof(charge_ah));
#endif
#ifdef INA3221_CALC_ENERGY_WH
dtostrfd(Ina3221Data[device].chan[chan].energy_wh, Settings->flag2.energy_resolution, temp);
strncat(energy_wh, temp, sizeof(energy_wh));
#endif
} //if enabled
else {
strncat(voltage, "null", sizeof(voltage)); strncat(voltage, "null", sizeof(voltage));
strncat(current, "null", sizeof(voltage)); strncat(current, "null", sizeof(current));
strncat(power, "null", sizeof(voltage)); strncat(power, "null", sizeof(power));
#ifdef INA3221_CALC_CHARGE_AH
strncat(charge_ah, "null", sizeof(charge_ah));
#endif
#ifdef INA3221_CALC_ENERGY_WH
strncat(energy_wh, "null", sizeof(energy_wh));
#endif
} }
if (0xFE & enabled_chan) { if (0xFE & enabled_chan) {
strncat(voltage, ",", sizeof(voltage)); strncat(voltage, ",", sizeof(voltage));
strncat(current, ",", sizeof(voltage)); strncat(current, ",", sizeof(current));
strncat(power, ",", sizeof(voltage)); strncat(power, ",", sizeof(power));
#ifdef INA3221_CALC_CHARGE_AH
strncat(charge_ah, ",", sizeof(charge_ah));
#endif
#ifdef INA3221_CALC_ENERGY_WH
strncat(energy_wh, ",", sizeof(energy_wh));
#endif
} }
} // for channel } // for channel
ResponseAppend_P(PSTR(",\"%s\":{\"Id\":\"0x%02x\",\"" D_JSON_VOLTAGE "\":[%s],\"" D_JSON_CURRENT "\":[%s],\"" D_JSON_POWERUSAGE "\":[%s]}"), ResponseAppend_P(PSTR(",\"%s\":{\"Id\":\"0x%02x\",\"" D_JSON_VOLTAGE "\":[%s],\"" D_JSON_CURRENT "\":[%s],\"" D_JSON_POWERUSAGE "\":[%s]"
name, Ina3221Data[device].i2caddr, voltage, current, power); #ifdef INA3221_CALC_CHARGE_AH
",\"" D_JSON_CHARGE "\":[%s]"
#endif
#ifdef INA3221_CALC_ENERGY_WH
",\"" D_JSON_ENERGY "\":[%s]"
#endif
"}"),name, Ina3221Data[device].i2caddr, voltage, current, power
#ifdef INA3221_CALC_CHARGE_AH
, charge_ah
#endif
#ifdef INA3221_CALC_ENERGY_WH
, energy_wh
#endif
);
#ifdef USE_DOMOTICZ #ifdef USE_DOMOTICZ
if (0 == TasmotaGlobal.tele_period) { if (0 == TasmotaGlobal.tele_period) {
DomoticzSensor(DZ_VOLTAGE, voltage); DomoticzSensor(DZ_VOLTAGE, voltage);
@ -390,7 +511,7 @@ void Ina3221Show(bool json)
} }
#endif // USE_DOMOTICZ #endif // USE_DOMOTICZ
} // for device } // for device
} // if json } // if json
#ifdef USE_WEBSERVER #ifdef USE_WEBSERVER
else { else {
// header // header
@ -400,14 +521,28 @@ void Ina3221Show(bool json)
uint8_t enabled_chan = Ina3221Data[device].enabled_chan; uint8_t enabled_chan = Ina3221Data[device].enabled_chan;
for (int chan=0 ; enabled_chan ; chan++, enabled_chan>>=1) { for (int chan=0 ; enabled_chan ; chan++, enabled_chan>>=1) {
if (0x01 & enabled_chan) { if (0x01 & enabled_chan) {
if (Ina3221count > 1) if (Ina3221count > 1){
snprintf_P(name, sizeof(name), PSTR("%s%c%d:%d"), INA3221_TYPE, IndexSeparator(), device +1, chan); snprintf_P(name, sizeof(name), PSTR("%s%c%d:%d"), INA3221_TYPE, IndexSeparator(), device +1, chan);
else }else{
snprintf_P(name, sizeof(name), PSTR("%s:%d"), INA3221_TYPE, chan); snprintf_P(name, sizeof(name), PSTR("%s:%d"), INA3221_TYPE, chan);
dtostrfd(Ina3221Data[device].chan[chan].voltage, Settings->flag2.voltage_resolution, voltage); dtostrfd(Ina3221Data[device].chan[chan].voltage, Settings->flag2.voltage_resolution, voltage);
dtostrfd(Ina3221Data[device].chan[chan].current, Settings->flag2.current_resolution, current); dtostrfd(Ina3221Data[device].chan[chan].current, Settings->flag2.current_resolution, current);
dtostrfd(Ina3221Data[device].chan[chan].voltage * Ina3221Data[device].chan[chan].current, Settings->flag2.wattage_resolution, power); dtostrfd(Ina3221Data[device].chan[chan].voltage * Ina3221Data[device].chan[chan].current, Settings->flag2.wattage_resolution, power);
WSContentSend_PD(HTTP_SNS_INA3221_DATA, name, voltage, current, power); #ifdef INA3221_CALC_CHARGE_AH
dtostrfd(Ina3221Data[device].chan[chan].charge_ah, Settings->flag2.energy_resolution, charge_ah);
#endif
#ifdef INA3221_CALC_ENERGY_WH
dtostrfd(Ina3221Data[device].chan[chan].energy_wh, Settings->flag2.energy_resolution, energy_wh);
#endif
WSContentSend_PD(HTTP_SNS_INA3221_DATA, name, voltage, current, power
#ifdef INA3221_CALC_CHARGE_AH
, charge_ah
#endif
#ifdef INA3221_CALC_ENERGY_WH
, energy_wh
#endif
);
}
} // if active } // if active
} // for channel } // for channel
} // for device } // for device