Hi everyone,
I am using the MKR RS485 shield to read values like voltage and power from an energy meter. I have two scenarios, in first scenario, I have a single meter and I can read the values successfully. In the second scenario, I have two identical meters. I have shown the way I want to connect them in the attached image. Right now, I have only meter, so I don't know if I would be able to read the two meters the way I have shown and explained below.
For single meter, I use the code as that works correctly:
#include <ArduinoRS485.h>
#include <ArduinoModbus.h>
void setup() {
Serial.begin(115200);
while (!Serial) {
//
}
if (!ModbusRTUClient.begin(9600)) {
Serial.println("Failed to start Modbus RTU Client!");
while (1);
} else {
Serial.println("Connected");
}
}
void loop() {
float volt = readVoltage();
Serial.print("Voltage is: ");
Serial.print(volt, 1);
Serial.println(" V");
delay(500);
float L1 = readPower();
Serial.print("Power is: ");
Serial.print(L1, 2);
Serial.println(" W");
delay(500);
}
float readVoltage() {
float volt = 0.;
if (!ModbusRTUClient.requestFrom(0x01, HOLDING_REGISTERS, 0x00F3, 1)) { // make the call to the register
Serial.print("failed to read voltage! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
uint16_t word1 = ModbusRTUClient.read(); // read data from the buffer
volt = word1 / 10.0;
}
return volt;
}
float readPower() {
float watt = 0;
if (!ModbusRTUClient.requestFrom(0x01, HOLDING_REGISTERS, 0x00FD, 2)) { // make the call to the register
Serial.print("failed to read power! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
int16_t word1 = ModbusRTUClient.read(); // read data from the buffer
int16_t word2 = ModbusRTUClient.read();
int32_t WATT = word1 << 16 | word2; // bit math
watt = WATT * 1.2;
}
return watt;
}
For two meters, will the code work like that?
#include <ArduinoRS485.h>
#include <ArduinoModbus.h>
void setup() {
Serial.begin(115200);
while (!Serial) {
//
}
if (!ModbusRTUClient.begin(9600)) {
Serial.println("Failed to start Modbus RTU Client!");
while (1);
} else {
Serial.println("Connected");
}
}
void loop() {
// Meter 1
float volt = readVoltage();
Serial.print("Meter 1 Voltage is: ");
Serial.print(volt, 1);
Serial.println(" V");
delay(500);
float L1 = readPower();
Serial.print("Meter 1 Power is: ");
Serial.print(L1, 2);
Serial.println(" W");
delay(500);
// Meter 2
float V1 = read_Voltage();
Serial.print("Meter 2 Voltage is: ");
Serial.print(V1, 1);
Serial.println(" V");
delay(500);
float P1 = readPower_P1();
Serial.print("Meter 2 Power is: ");
Serial.print(P1, 2);
Serial.println(" W");
delay(500);
}
float readVoltage() {
float volt = 0.;
if (!ModbusRTUClient.requestFrom(0x01, HOLDING_REGISTERS, 0x00F3, 1)) { // make the call to the register
Serial.print("failed to read voltage! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
uint16_t word1 = ModbusRTUClient.read(); // read data from the buffer
volt = word1 / 10.0;
}
return volt;
}
float readPower() {
float watt = 0;
if (!ModbusRTUClient.requestFrom(0x01, HOLDING_REGISTERS, 0x00FD, 2)) { // make the call to the register
Serial.print("failed to read power! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
int16_t word1 = ModbusRTUClient.read(); // read data from the buffer
int16_t word2 = ModbusRTUClient.read();
int32_t WATT = word1 << 16 | word2; // bit math
watt = WATT * 1.2;
}
return watt;
}
float read_Voltage() {
float volt = 0.;
if (!ModbusRTUClient.requestFrom(0x02, HOLDING_REGISTERS, 0x00F3, 1)) { // make the call to the register
Serial.print("failed to read voltage! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
uint16_t word1 = ModbusRTUClient.read(); // read data from the buffer
volt = word1 / 10.0;
}
return volt;
}
float readPower_P1() {
float watt = 0;
if (!ModbusRTUClient.requestFrom(0x02, HOLDING_REGISTERS, 0x00FD, 2)) { // make the call to the register
Serial.print("failed to read power! ");
Serial.println(ModbusRTUClient.lastError()); // error handler
} else {
int16_t word1 = ModbusRTUClient.read(); // read data from the buffer
int16_t word2 = ModbusRTUClient.read();
int32_t WATT = word1 << 16 | word2; // bit math
watt = WATT * 1.2;
}
return watt;
}
Will it work if I just change the address of second meter to 0x02?
I just test made a test where I connected one energy meter and an another device having RS485 port. I connected the MKR shield to the other device first and from there I extended the connection my energy meter. I don't read anything from the first device. However, I tried to read the energy meter using the address 0x02 but I got this error:
failed to read voltage! Response not from requested slave
Meter 1 voltage is: 0.0 V
failed to read power! Response not from requested slave
Meter 1 Power is: 0.00 W
There is one difference between the energy meter and the other device I have. The energy meter has A, B, and GND connection for communication while the other device has only A and B. So, I connected the Y to A, Z to B on the device from the shield but didn't connect the GND. Then I gave the connection from other device to energy meter as: A to A and B to B and GND not connected.
So, I want to know if my connections are correct and if the code would work, or do I need to make some changes on the code and connection?
Looking forward to your help. Thank you very much.