I am building a MySensors serial <->RS485 node, which also has to read out a modbus enable energy monitoring device (Schneider PM9C).
The modbus part is working great, so now i am trying to send the measured values as MySensors data so i can pick them up with Domoticz.
My code at the moment :
#define MY_GATEWAY_SERIAL // Enable serial gateway mode
#define MY_RS485 // Enable RS485 transport layer
#define MY_RS485_HWSERIAL Serial2 // Set serial interface to use for RS-485
#define MY_RS485_BAUD_RATE 9600 // Set RS485 baud rate to use
#define MY_RS485_DE_PIN 2 // Define this to enables DE-pin management on defined pin
#include <MySensors.h>
#include <ModbusMaster.h>
#define CHILD_ID_Phase1_Current 11
#define CHILD_ID_Phase2_Current 12
#define CHILD_ID_Phase3_Current 13
#define CHILD_ID_Neutral_Current 14
#define CHILD_ID_Phase12_Voltage 21
#define CHILD_ID_Phase23_Voltage 22
#define CHILD_ID_Phase31_Voltage 23
#define CHILD_ID_Phase1_Voltage 24
#define CHILD_ID_Phase2_Voltage 25
#define CHILD_ID_Phase3_Voltage 26
#define CHILD_ID_Frequency 30
#define CHILD_ID_Total_Active_Power 41
#define CHILD_ID_Total_Reactive_Power 42
#define CHILD_ID_Total_Apparant_Power 43
#define CHILD_ID_Total_Power_Factor 44
#define CHILD_ID_Power_Factor_Sector 45
#define CHILD_ID_Power_Demand 50
#define CHILD_ID_Max_Power_Demand 51
#define CHILD_ID_Phase1_Active_Power 60
#define CHILD_ID_Phase1_Reactive_Power 61
#define CHILD_ID_Phase2_Active_Power 62
#define CHILD_ID_Phase2_Reactive_Power 63
#define CHILD_ID_Phase3_Active_Power 64
#define CHILD_ID_Phase3_Reactive_Power 65
ModbusMaster node; // Initiate ModbusMaster object
MyMessage Phase1_Current (CHILD_ID_Phase1_Current,V_CURRENT);
MyMessage Phase2_Current (CHILD_ID_Phase2_Current, V_CURRENT);
MyMessage Phase3_Current (CHILD_ID_Phase3_Current, V_CURRENT);
MyMessage Neutral_Current (CHILD_ID_Neutral_Current, V_CURRENT);
MyMessage Phase12_Voltage (CHILD_ID_Phase12_Voltage, V_VOLTAGE);
MyMessage Phase23_Voltage (CHILD_ID_Phase23_Voltage, V_VOLTAGE);
MyMessage Phase31_Voltage (CHILD_ID_Phase31_Voltage, V_VOLTAGE);
MyMessage Phase1_Voltage (CHILD_ID_Phase1_Voltage, V_VOLTAGE);
MyMessage Phase2_Voltage (CHILD_ID_Phase2_Voltage, V_VOLTAGE);
MyMessage Phase3_Voltage (CHILD_ID_Phase3_Voltage, V_VOLTAGE);
MyMessage Total_Active_Power (CHILD_ID_Total_Active_Power, V_WATT);
MyMessage Total_Reactive_Power (CHILD_ID_Total_Reactive_Power, V_VAR);
MyMessage Total_Apparant_Power (CHILD_ID_Total_Apparant_Power, V_VA);
MyMessage Total_Power_Factor (CHILD_ID_Total_Power_Factor, V_POWER_FACTOR);
MyMessage Phase1_Active_Power (CHILD_ID_Phase1_Reactive_Power, V_WATT);
MyMessage Phase1_Reactive_Power (CHILD_ID_Phase1_Reactive_Power, V_VAR);
MyMessage Phase2_Active_Power (CHILD_ID_Phase1_Reactive_Power, V_WATT);
MyMessage Phase2_Reactive_Power (CHILD_ID_Phase1_Reactive_Power, V_VAR);
MyMessage Phase3_Active_Power (CHILD_ID_Phase1_Reactive_Power, V_WATT);
MyMessage Phase3_Reactive_Power (CHILD_ID_Phase1_Reactive_Power, V_VAR);
// Functions to restore measured values after modbus tranfer (The PM9C sends it's 32-bit signed and unsigned measurements as 2 16-bit words, the divider is to scale to the corrent unit)
float UnsignedValue (int reg, int divider) {
unsigned long msb = node.getResponseBuffer(reg);
msb = msb << 16;
unsigned int lsb = node.getResponseBuffer(reg + 1);
unsigned long total = msb | lsb;
float result = float (total) / divider;
return result;
}
float SignedValue (int reg, int divider) {
signed long msb = node.getResponseBuffer(reg);
msb = msb << 16;
unsigned int lsb = node.getResponseBuffer(reg + 1);
signed long total = msb | lsb;
float result = float (total) / divider;
return result;
}
void setup()
{
Serial3.begin (19200, SERIAL_8N1); // Use Serial 3 for Modbus RTU @ 19200 8N1 using Moxa RS232<->RS485 converter (Auto direction control)
node.begin(1, Serial3); // Communicate with Modbus slave ID 1
}
void presentation()
{
sendSketchInfo("RS485 gateway with Modbus", "0.1");
present(CHILD_ID_Phase1_Current, S_MULTIMETER);
present(CHILD_ID_Phase2_Current, S_MULTIMETER);
present(CHILD_ID_Phase3_Current, S_MULTIMETER);
present(CHILD_ID_Neutral_Current, S_MULTIMETER);
present(CHILD_ID_Phase12_Voltage, S_MULTIMETER);
present(CHILD_ID_Phase23_Voltage, S_MULTIMETER);
present(CHILD_ID_Phase31_Voltage, S_MULTIMETER);
present(CHILD_ID_Phase1_Voltage, S_MULTIMETER);
present(CHILD_ID_Phase2_Voltage, S_MULTIMETER);
present(CHILD_ID_Phase3_Voltage, S_MULTIMETER);
present(CHILD_ID_Total_Active_Power, S_POWER);
present(CHILD_ID_Total_Reactive_Power, S_POWER);
present(CHILD_ID_Total_Apparant_Power, S_POWER);
present(CHILD_ID_Total_Power_Factor, S_POWER);
present(CHILD_ID_Phase1_Active_Power, S_POWER);
present(CHILD_ID_Phase1_Reactive_Power, S_POWER);
present(CHILD_ID_Phase2_Active_Power, S_POWER);
present(CHILD_ID_Phase2_Reactive_Power, S_POWER);
present(CHILD_ID_Phase3_Active_Power, S_POWER);
present(CHILD_ID_Phase3_Reactive_Power, S_POWER);
}
void loop()
{
node.readHoldingRegisters(0x3E8, 56);
float Phase1_Current = UnsignedValue (0, 1000);
float Phase2_Current = UnsignedValue (2, 1000);
float Phase3_Current = UnsignedValue (4, 1000);
float Neutral_Current = UnsignedValue (6, 1000);
float Phase12_Voltage = UnsignedValue (8, 1000);
float Phase23_Voltage = UnsignedValue (10, 1000);
float Phase31_Voltage = UnsignedValue (12, 1000);
float Phase1_Voltage = UnsignedValue (14, 1000);
float Phase2_Voltage = UnsignedValue (16, 1000);
float Phase3_Voltage = UnsignedValue (18, 1000);
float Total_Active_Power = UnsignedValue (22, 100);
float Total_Reactive_Power = SignedValue (24, 100);
float Total_Apparant_Power = UnsignedValue (26, 100);
float Total_Power_Factor = SignedValue (28, 100);
float Phase1_Active_Power = SignedValue (44, 100);
float Phase2_Active_Power = SignedValue (46, 100);
float Phase3_Active_Power = SignedValue (48, 100);
float Phase1_Reactive_Power = SignedValue (50, 100);
float Phase2_Reactive_Power = SignedValue (52, 100);
float Phase3_Reactive_Power = SignedValue (54, 100);
send(Phase1_Current.set(Phase1_Current));
send(Phase2_Current.set(Phase1_Current));
send(Phase3_Current.set(Phase1_Current));
send(Neutral_Current.set(Phase1_Current));
send(Phase1_Voltage.set(Phase1_Voltage));
send(Phase2_Voltage.set(Phase1_Voltage));
send(Phase3_Voltage.set(Phase1_Voltage));
send(Total_Active_Power.set(Total_Active_Power));
}
I am only trying to send out a small subset of the available data, and i have not set up things like timing etc for the measurements yet, but i am stuck at the "send" part. The values created by the PM9C come in through modbus as 2 16-bit words. These are combined into 32-bit signed or unsigned longs which give the measured values, then converted to a float to be divided by a scaling factor to correct the measurements unit. The currents are given in mA, voltages in mV etc. These are brought back to A, V, kW etc.
So my measurements are all float values. (some signed, most of them unsigned)
Since the S_POWER type does not include voltage, currents etc, i have divided my data over both S_POWER and S_MULTIMETER types.
But this won't fly.. If i compile the code to check for errors, it produces numerous issues :
Arduino: 1.8.0 (Windows 10), Board: "Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"
Gateway-RS485andModBus.ino: In function 'void loop()':
Gateway-RS485andModBus:157: error: request for member 'set' in 'Phase1_Current', which is of non-class type 'float'
send(Phase1_Current.set(Phase1_Current));
^
Gateway-RS485andModBus:158: error: request for member 'set' in 'Phase2_Current', which is of non-class type 'float'
send(Phase2_Current.set(Phase1_Current));
^
Gateway-RS485andModBus:159: error: request for member 'set' in 'Phase3_Current', which is of non-class type 'float'
send(Phase3_Current.set(Phase1_Current));
^
Gateway-RS485andModBus:160: error: request for member 'set' in 'Neutral_Current', which is of non-class type 'float'
send(Neutral_Current.set(Phase1_Current));
^
Gateway-RS485andModBus:161: error: request for member 'set' in 'Phase12_Voltage', which is of non-class type 'float'
send(Phase12_Voltage.set(Phase12_Voltage));
^
Gateway-RS485andModBus:162: error: request for member 'set' in 'Phase23_Voltage', which is of non-class type 'float'
send(Phase23_Voltage.set(Phase23_Voltage));
^
Gateway-RS485andModBus:163: error: request for member 'set' in 'Phase31_Voltage', which is of non-class type 'float'
send(Phase31_Voltage.set(Phase31_Voltage));
^
Gateway-RS485andModBus:164: error: request for member 'set' in 'Phase1_Voltage', which is of non-class type 'float'
send(Phase1_Voltage.set(Phase1_Voltage));
^
Gateway-RS485andModBus:165: error: request for member 'set' in 'Phase2_Voltage', which is of non-class type 'float'
send(Phase2_Voltage.set(Phase1_Voltage));
^
Gateway-RS485andModBus:166: error: request for member 'set' in 'Phase3_Voltage', which is of non-class type 'float'
send(Phase3_Voltage.set(Phase1_Voltage));
^
Gateway-RS485andModBus:167: error: request for member 'set' in 'Total_Active_Power', which is of non-class type 'float'
send(Total_Active_Power.set(Total_Active_Power));
^
What am i doing wrong here ? Is the mysensors lib unable to handle floats as data ? did i forget something ? made a major f<censored>up ?