Modbus RTU Read Works But Write Doesn't
Hello everybody,
I am trying to read and write data from a Deye Inverter to an AXC F 2152 PLC using a RS485 Module for Modbus RTU communication. I am also using the Modbus RTU 15 Library.
With the current setup I am able to read data from the Deye inverter. The code I use for this is as follows:
CASE Inverter_RTU.iStateInverter OF
0: (* Wait for xStart *)
IF xStartInverter = TRUE THEN
Inverter_RTU.iStateInverter := 10;
END_IF;
10: (* Start Master *)
Inverter_RTU.udtMB_RTU_FC3.xActivate := FALSE;
Inverter_RTU.udtMB_RTU_FC3.xSendRequest := FALSE;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.tModbus_Timeout := TIME#2s;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.tPD_Timeout := TIME#2s;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.xActivate := TRUE;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.xMode := FALSE;
Inverter_RTU.iStateInverter := 20;
20: (* Wait for Master xActive *)
IF Inverter_RTU.udtMB_AXL_SE_RS485_Master.xError = TRUE THEN
Inverter_RTU.iStateInverter := 10;
ELSIF Inverter_RTU.udtMB_AXL_SE_RS485_Master.xActive = TRUE THEN
Inverter_RTU.iStateInverter := 30;
END_IF;
30: (* Activate FC3 *)
Inverter_RTU.udtMB_RTU_FC3.xActivate := TRUE;
Inverter_RTU.udtMB_RTU_FC3.xSendRequest := FALSE;
Inverter_RTU.udtMB_RTU_FC3.uiSlaveAddress := UINT#1;
Inverter_RTU.udtMB_RTU_FC3.xEnablePoll := FALSE;
Inverter_RTU.udtMB_RTU_FC3.tPollInterval := T#0.5s;
Inverter_RTU.udtMB_RTU_FC3.uiStartAddress := UINT#0;
Inverter_RTU.udtMB_RTU_FC3.iDataCount := 125;
IF Inverter_RTU.udtMB_RTU_FC3.xError = TRUE THEN
Inverter_RTU.iStateInverter := 10;
ELSIF Inverter_RTU.udtMB_RTU_FC3.xActive = TRUE AND Inverter_RTU.udtMB_RTU_FC3.xBusy = FALSE THEN
Inverter_RTU.iStateInverter := 40;
END_IF;
40: (* Start sendrequest FC3 *)
Inverter_RTU.udtMB_RTU_FC3.xSendRequest := TRUE;
IF Inverter_RTU.udtMB_RTU_FC3.xError = TRUE THEN
Inverter_RTU.udtMB_RTU_FC3.xActivate := FALSE;
Inverter_RTU.udtMB_RTU_FC3.xSendRequest := FALSE;
Inverter_RTU.iStateInverter := 30;
ELSIF Inverter_RTU.udtMB_RTU_FC3.xActive = TRUE AND Inverter_RTU.udtMB_RTU_FC3.xBusy = FALSE AND Inverter_RTU.udtMB_RTU_FC3.xDone = TRUE THEN
runState := Inverter_RTU.udtMB_RTU_FC3.arrReadData[63];
Inverter_RTU.udtMB_RTU_FC3.xSendRequest := FALSE;
Inverter_RTU.udtMB_RTU_FC3.xActivate := FALSE;
END_IF;
This code works and gives me the data I need. However, when I am trying to write to the Deye Inverter I get the error 16#C110 Modbus error: 16#0001 Modbus communication timeout from the FC6 function block. I have written the following code for a write request:
CASE Inverter_RTU.iStateInverterWrite OF
0: (* Wait for xStart *)
IF xStartInverterWrite = TRUE THEN
Inverter_RTU.iStateInverterWrite := 10;
END_IF;
10: (* Start Master *)
Inverter_RTU.udtMB_RTU_FC6.xActivate := FALSE;
Inverter_RTU.udtMB_RTU_FC6.xSendRequest := FALSE;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.tModbus_Timeout := TIME#2s;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.tPD_Timeout := TIME#2s;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.xActivate := TRUE;
Inverter_RTU.udtMB_AXL_SE_RS485_Master.xMode := FALSE;
Inverter_RTU.iStateInverterWrite := 20;
20: (* Wait for Master xActive *)
IF Inverter_RTU.udtMB_AXL_SE_RS485_Master.xError = TRUE THEN
Inverter_RTU.iStateInverterWrite := 10;
ELSIF Inverter_RTU.udtMB_AXL_SE_RS485_Master.xActive = TRUE THEN
Inverter_RTU.iStateInverterWrite := 30;
END_IF;
30: (* Prepare to send request *)
Inverter_RTU.udtMB_RTU_FC6.xActivate := TRUE;
Inverter_RTU.udtMB_RTU_FC6.xSendRequest := FALSE;
Inverter_RTU.udtMB_RTU_FC6.uiSlaveAddress := UINT#1;
Inverter_RTU.udtMB_RTU_FC6.xEnablePoll := FALSE;
Inverter_RTU.udtMB_RTU_FC6.tPollInterval := T#0.5s;
Inverter_RTU.udtMB_RTU_FC6.uiStartAddress := UINT#62;
Inverter_RTU.udtMB_RTU_FC6.wValue := WORD#2510;
IF Inverter_RTU.udtMB_RTU_FC6.xActive = TRUE AND Inverter_RTU.udtMB_RTU_FC6.xBusy = FALSE THEN
Inverter_RTU.iStateInverterWrite := 40;
END_IF;
40: (* Send the request *)
Inverter_RTU.udtMB_RTU_FC6.xSendRequest := TRUE;
END_CASE;
iStateInverterWrite := Inverter_RTU.iStateInverterWrite;
As you can see both codes are almost identical in logic and flow except for the function block I am using. I do not understand why I get an error. I believe that since I can read holding registers the issue is not hardware based but software based.
I am sure the slave adress, holding register and register value I am trying to write to are correct. I have tried different values for all that should or should not work but I keep getting the same error. I have attached the documentation of the register below.
I am also very new to PLC programming so maybe I am not seeing something obvious. Any help to solve this problem will be appreciated greatly😀.
Kind Regards, Rutger
Comments
Dear Rutger,
When you can read but cannot write with Modbus and the register address and Function Code are correct, often you have a watchdog problem.
Is there a Watchdog time set up in the inverter?
If you have PLCnext questions you can also contact us directly in the Netherlands.
Met vriendelijke groet / Mit freundlichen Grüßen / Best regards,
Henk Welgraven
Technical Sales Engineer
Industrial Electronics
PHOENIX CONTACT B.V.
Postbus 246
6900 AE ZEVENAAR
Tel. +31 (0)316 59 17 20
mailto:support@phoenixcontact.nl
www.phoenixcontact.nl
Hello mister Welgraven,
Thank you for your reply!
After some more testing I have figured out that this specific inverter does not support writing to a single holding register (Function block 6). I have changed to code to use the function block of writing multiple holding registers (Function Block 16) of the RTU library and now it works like a charm.
So If anybody else has this problem, read the manual of the device you are connecting to the PLC and make sure the function block of the RTU library you are trying to use is compatible with your device.
👍️