Add fieldpair "F" replacing "M"

This commit is contained in:
Theo Arends 2022-12-23 11:39:13 +01:00
parent 768820061b
commit 0dc3b8d7e1

View File

@ -36,7 +36,7 @@
* Voltage - Voltage register entered as decimal or hexadecimal for one phase (0x0000) or up to three phases ([0x0000,0x0002,0x0004]) or
* Additional defined parameters
* Value pair description:
* {"R":0,"T":0,"M":1}
* {"R":0,"T":0,"F":0}
* R - Modbus register entered as decimal or hexadecimal for one phase (0x0160) or up to three phases ([0x0160,0x0162,0x0164])
* T - Datatype - optional. default is 0 - float:
* 0 - float
@ -48,7 +48,17 @@
* 6 = 4-byte signed with swapped words
* 7 = not used
* 8 = 4-byte unsigned with swapped words
* M - Multiply, if negative, or divide, if positive, the read register by 1 to 10000 - optional. default = 1
* F - Register factor positive for multiplication or negative for division - optional. default is 0 - no action
* -4 - divide by 10000
* -3 - divide by 1000
* -2 - divide by 100
* -1 - divide by 10
* 0 - no action
* 1 - multiply by 10
* 2 - multiply by 100
* 3 - multiply by 1000
* 4 - multiply by 10000
* M - [LEGACY - replaced by "F"] Divide register by 1 to 10000 - optional. default = 0 (no action)
* Current - Current register entered as decimal or hexadecimal for one phase (0x0006) or up to three phases ([0x0006,0x0008,0x000A]) or
* See additional defines like voltage.
* Power - Active power register entered as decimal or hexadecimal for one phase (0x000C) or up to three phases ([0x000C,0x000E,0x0010]) or
@ -68,7 +78,7 @@
* Optional user defined registers:
* User - Additional user defined registers
* Value pair description:
* "User":{"R":0x0024,"T":0,"M":1,"J":"PhaseAngle","G":"Phase Angle","U":"Deg","D":2}
* "User":{"R":0x0024,"T":0,"F":0,"J":"PhaseAngle","G":"Phase Angle","U":"Deg","D":2}
* R - Modbus register entered as decimal or hexadecimal for one phase (0x0160) or up to three phases ([0x0160,0x0162,0x0164])
* T - Datatype - optional. default is 0 - float:
* 0 - float
@ -80,7 +90,17 @@
* 6 = 4-byte signed with swapped words
* 7 = not used
* 8 = 4-byte unsigned with swapped words
* M - Multiply, if negative, or divide, if positive, the read register by 1 to 10000 - optional. default = 1
* F - Register factor positive for multiplication or negative for division - optional. default is 0 - no action
* -4 - divide by 10000
* -3 - divide by 1000
* -2 - divide by 100
* -1 - divide by 10
* 0 - no action
* 1 - multiply by 10
* 2 - multiply by 100
* 3 - multiply by 1000
* 4 - multiply by 10000
* M - [LEGACY - replaced by "F"] Divide register by 1 to 10000 - optional. default = 0 (no action)
* J - JSON register name (preferrably without spaces like "PhaseAngle")
* G - GUI register name
* U - GUI unit name
@ -105,7 +125,7 @@
* rule3 on file#modbus do {"Name":"SDM120","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":0,"Current":6,"Power":12,"ApparentPower":18,"ReactivePower":24,"Factor":30,"Frequency":70,"Total":342,"ExportActive":0x004A,"User":[{"R":0x0048,"J":"ImportActive","G":"Import Active","U":"kWh","D":24},{"R":0x004E,"J":"ExportReactive","G":"Export Reactive","U":"kVArh","D":24},{"R":0x004C,"J":"ImportReactive","G":"Import Reactive","U":"kVArh","D":24},{"R":0x0024,"J":"PhaseAngle","G":"Phase Angle","U":"Deg","D":2}]} endon
* rule3 on file#modbus do {"Name":"SDM230 with two user registers","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":0,"Current":6,"Power":12,"ApparentPower":18,"ReactivePower":24,"Factor":30,"Frequency":70,"Total":342,"ExportActive":0x004A,"User":[{"R":0x004E,"J":"ExportReactive","G":"Export Reactive","U":"kVArh","D":3},{"R":0x0024,"J":"PhaseAngle","G":"Phase Angle","U":"Deg","D":2}]} endon
* rule3 on file#modbus do {"Name":"SDM630","Baud":9600,"Config":8N1","Address":1,"Function":4,"Voltage":[0,2,4],"Current":[6,8,10],"Power":[12,14,16],"ApparentPower":[18,20,22],"ReactivePower":[24,26,28],"Factor":[30,32,34],"Frequency":70,"Total":342,"ExportActive":[352,354,356],"User":{"R":[346,348,350],"J":"ImportActive","G":"Import Active","U":"kWh","D":24}} endon
* rule3 on file#modbus do {"Name":"X3MIC","Baud":9600,"Config":8N1","Address":1,"Function":4,"Voltage":{"R":0x0404,"T":3,"M":10},"Power":{"R":0x040e,"T":3,"M":1},"Total":{"R":0x0423,"T":8,"M":1000}} endon
* rule3 on file#modbus do {"Name":"X3MIC","Baud":9600,"Config":8N1","Address":1,"Function":4,"Voltage":{"R":0x0404,"T":3,"F":-1},"Power":{"R":0x040e,"T":3,"F":0},"Total":{"R":0x0423,"T":8,"F":-3}} endon
*
* Note:
* - To enter long rules using the serial console and solve error "Serial buffer overrun" you might need to enlarge the serial input buffer with command serialbuffer 800
@ -128,7 +148,7 @@
* rule3 on file#modbus do {"Name":"SDM120 test1","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":0,"Current":6,"Power":12,"ApparentPower":18,"ReactivePower":24,"Factor":30,"Frequency":70,"Total":342,"ExportActive":0x004A,"User":[{"R":0x0048,"J":"ImportActive","G":"Import Active","U":"kWh","D":24},{"R":0x004E,"J":"ExportReactive","G":"Export Reactive","U":"kVArh","D":24},{"R":0x004C,"J":"ImportReactive","G":"Import Reactive","U":"kVArh","D":24},{"R":0x0024,"J":"PhaseAngle","G":"Phase Angle","U":"Deg","D":2}]} endon
*
* rule3 on file#modbus do {"Name":"SDM230 test6","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":{"R":0,"T":0,"M":1},"Current":{"R":6,"T":0,"M":1},"Power":{"R":12,"T":0,"M":1},"Frequency":70,"Total":342} endon
* rule3 on file#modbus do {"Name":"SDM230 test6","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":{"R":0,"T":0,"M":1},"Current":{"R":6,"T":0,"M":1},"Power":{"R":12,"T":0,"M":1},"Frequency":70,"Total":342,"User":{"R":0x0048,"T":0,"M":10,"J":"ImportActive","G":"Import Active","U":"kWh","D":24}} endon
* rule3 on file#modbus do {"Name":"SDM230 test6","Baud":2400,"Config":8N1","Address":1,"Function":4,"Voltage":{"R":0,"T":0,"F":0},"Current":{"R":6,"T":0,"F":0},"Power":{"R":12,"T":0,"F":0},"Frequency":70,"Total":342,"User":{"R":0x0048,"T":0,"F":-1,"J":"ImportActive","G":"Import Active","U":"kWh","D":24}} endon
\*********************************************************************************************/
#define XNRG_29 29
@ -139,8 +159,6 @@
#define ENERGY_MODBUS_FUNC 0x04 // Default Modbus function code
#define ENERGY_MODBUS_DATATYPE 0 // Default Modbus datatype is 4-byte float
#define ENERGY_MODBUS_DIVIDER 1 // Default Modbus data divider
#define ENERGY_MODBUS_DECIMALS 0 // Default user decimal resolution
#define ENERGY_MODBUS_TICKER // Enable for ESP8266 when using softwareserial solving most modbus serial retries
@ -216,7 +234,7 @@ struct NRGMBSPARAM {
typedef struct NRGMBSREGISTER {
uint16_t address[ENERGY_MAX_PHASES];
int16_t divider;
int16_t factor;
uint32_t datatype;
} NrgMbsRegister_t;
NrgMbsRegister_t *NrgMbsReg = nullptr;
@ -342,10 +360,17 @@ void EnergyModbusLoop(void) {
break;
}
}
if (NrgMbsReg[NrgMbsParam.state].divider < 1) {
value *= (NrgMbsReg[NrgMbsParam.state].divider * -1);
uint32_t factor = 1;
// 1 = 10, 2 = 100, 3 = 1000, 4 = 10000
uint32_t scaler = abs(NrgMbsReg[NrgMbsParam.state].factor);
while (scaler) {
factor *= 10;
scaler--;
}
if (NrgMbsReg[NrgMbsParam.state].factor < 0) {
value /= factor;
} else {
value /= NrgMbsReg[NrgMbsParam.state].divider;
value *= factor;
}
switch (NrgMbsParam.state) {
@ -417,7 +442,7 @@ void EnergyModbusLoop(void) {
#ifdef USE_RULES
bool EnergyModbusReadUserRegisters(JsonParserObject user_add_value, uint32_t add_index) {
// {"R":0x004E,"T":0,"M":1,"J":"ExportReactive","G":"Export Reactive","U":"kVArh","D":3}
// {"R":0x004E,"T":0,"F":0,"J":"ExportReactive","G":"Export Reactive","U":"kVArh","D":3}
uint32_t reg_index = NRG_MBS_MAX_REGS + add_index;
JsonParserToken val;
val = user_add_value[PSTR("R")]; // Register address
@ -443,10 +468,21 @@ bool EnergyModbusReadUserRegisters(JsonParserObject user_add_value, uint32_t add
// "T":0
NrgMbsReg[reg_index].datatype = val.getUInt();
}
val = user_add_value[PSTR("M")]; // Register divider
val = user_add_value[PSTR("F")]; // Register factor
if (val) {
// "M":1 or "M":-10
NrgMbsReg[reg_index].divider = val.getInt();
// "F":1 or "F":-2
NrgMbsReg[reg_index].factor = val.getInt();
}
val = user_add_value[PSTR("M")]; // [LEGACY] Register divider
if (val) {
// "M":1
int32_t divider = val.getUInt();
int factor = 0;
while (divider > 1) {
divider /= 10;
factor--;
}
NrgMbsReg[reg_index].factor = factor;
}
val = user_add_value[PSTR("J")]; // JSON value name
if (val) {
@ -472,13 +508,13 @@ bool EnergyModbusReadUserRegisters(JsonParserObject user_add_value, uint32_t add
}
#ifdef ENERGY_MODBUS_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Idx %d, R [%04X,%04X,%04X], T %d, M %d, J '%s', G '%s', U '%s', D %d"),
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Idx %d, R [%04X,%04X,%04X], T %d, F %d, J '%s', G '%s', U '%s', D %d"),
add_index,
NrgMbsReg[reg_index].address[0],
NrgMbsReg[reg_index].address[1],
NrgMbsReg[reg_index].address[2],
NrgMbsReg[reg_index].datatype,
NrgMbsReg[reg_index].divider,
NrgMbsReg[reg_index].factor,
NrgMbsUser[add_index].json_name,
NrgMbsUser[add_index].gui_name,
NrgMbsUser[add_index].gui_unit,
@ -529,7 +565,6 @@ bool EnergyModbusReadRegisters(void) {
// Init defaults
for (uint32_t i = 0; i < NrgMbsParam.total_regs; i++) {
NrgMbsReg[i].datatype = ENERGY_MODBUS_DATATYPE;
NrgMbsReg[i].divider = ENERGY_MODBUS_DIVIDER;
for (uint32_t j = 0; j < ENERGY_MAX_PHASES; j++) {
NrgMbsReg[i].address[j] = nrg_mbs_reg_not_used;
}
@ -576,12 +611,12 @@ bool EnergyModbusReadRegisters(void) {
if (val) {
// "Voltage":0
// "Voltage":[0,0,0]
// "Voltage":{"R":0,"T":0,"M":1}
// "Voltage":{"R":[0,0,0],"T":0,"M":1}
// "Voltage":{"R":0,"T":0,"F":0}
// "Voltage":{"R":[0,0,0],"T":0,"F":0}
uint32_t phase = 0;
if (val.isObject()) {
// "Voltage":{"R":0,"T":0,"M":1}
// "Voltage":{"R":[0,0,0],"T":0,"M":1}
// "Voltage":{"R":0,"T":0,"F":0}
// "Voltage":{"R":[0,0,0],"T":0,"F":0}
JsonParserObject register_add_values = val.getObject();
val = register_add_values[PSTR("R")]; // Register address
if (val.isArray()) {
@ -602,10 +637,21 @@ bool EnergyModbusReadRegisters(void) {
// "T":0
NrgMbsReg[names].datatype = val.getUInt();
}
val = register_add_values[PSTR("M")]; // Register divider
val = register_add_values[PSTR("F")]; // Register factor
if (val) {
// "M":1 or "M":-10
NrgMbsReg[names].divider = val.getInt();
// "F":1 or "F":-2
NrgMbsReg[names].factor = val.getInt();
}
val = register_add_values[PSTR("M")]; // [LEGACY] Register divider
if (val) {
// "M":1
int32_t divider = val.getUInt();
int factor = 0;
while (divider > 1) {
divider /= 10;
factor--;
}
NrgMbsReg[names].factor = factor;
}
} else if (val.isArray()) {
// "Voltage":[0,0,0]
@ -644,13 +690,13 @@ bool EnergyModbusReadRegisters(void) {
}
#ifdef ENERGY_MODBUS_DEBUG
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Idx %d, R [%04X,%04X,%04X], T %d, M %d"),
AddLog(LOG_LEVEL_DEBUG, PSTR("NRG: Idx %d, R [%04X,%04X,%04X], T %d, F %d"),
names,
NrgMbsReg[names].address[0],
NrgMbsReg[names].address[1],
NrgMbsReg[names].address[2],
NrgMbsReg[names].datatype,
NrgMbsReg[names].divider);
NrgMbsReg[names].factor);
#endif
}
@ -687,9 +733,6 @@ bool EnergyModbusReadRegisters(void) {
if (NrgMbsReg[i].datatype >= NRG_DT_MAX) {
NrgMbsReg[i].datatype = ENERGY_MODBUS_DATATYPE;
}
if (0 == NrgMbsReg[i].divider) {
NrgMbsReg[i].divider = ENERGY_MODBUS_DIVIDER;
}
}
#ifdef ENERGY_MODBUS_DEBUG