I have been trying to acquire electrical parameters from my energy meter using Arduino through Modbus communication. But my code fails to get the data from the meter. In this code, I'm trying to get the phase voltage value from the energy meter whose register address is 12.
#include<ModbusMaster.h>
#define MAX485_DE 3
#define MAX485_RE_NEG 2
ModbusMaster node;
void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
Serial.begin(9600);
//slave ID 1
node.begin(1, Serial);
Serial.println("Starting Modbus Transaction:");
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
static uint32_t i;
uint8_t j, result;
uint16_t data[10];
i++;
result = node.readInputRegisters(0x30012,2);
Serial.println("");
if (result == node.ku8MBSuccess) {
Serial.print("Success, Received data: ");
for (j = 0; j < 2; j++) {
data[j] = node.getResponseBuffer(j);
Serial.print(data[j], HEX);
Serial.print(" ");
}
Serial.println("");
} else {
Serial.print("Failed, Response Code: ");
Serial.print(result, HEX);
Serial.println("");
delay(5000);
}
delay(1000);
}
You are using the wrong Modbus function. You should be using function 0x03 readHoldingRegisters
(note the 0x03 at the beginning of the frame on the bottom side of the page).
Just change this line:
result = node.readInputRegisters(0x30012,2);
to:
result = node.readHoldingRegisters(12,2);
By the way, there must be something else wrong with your setup because the error code you are getting is 0xE2
and you should be getting 0x02
meaning Ilegal Data Address
or maybe 0x01
(Illegal Function
) depending on the meter's firmware. Maybe you should double-check the baud rate.
You might also need to set the ID of the node to 0xAA
in your setup loop with:
node.begin(170, Serial);
as someone commented above. The documentation is not very good...
If you look at what looks like an example data command at the bottom:
aa 03 0001 003C 0DC0
It looks like aa
is the slave address, 03
the function code as discussed above, and 003C
is the number of registers to read (60 to read all data from the meter in one go). The last two bytes 0DC0
should be the CRC.
If that's correct then you should consider reading register 11 and 12 instead of 12-13 if you want to get the phase voltage:
result = node.readHoldingRegisters(11,2);
Again, that's just my best guess to fill the gaps on the documentation.