Modbus TCP READ & WRITE
Hello,
I am trying to Read the first 113 holding registers and then at some point I have to write to registers 1 and 2 to control a VFD. I have followed the FC3 example and I was able to read all the registers. Now, how do I write to a register? I tried to use FC23, but not exactly sure how to do it as I couldn't find any examples. Below is the code I am using. States kept switching when I tried to run it. Also Data Type MB2_TCP_ARR_W_1_125 for arrReadRegistersValue given in Modbus_TCP_7.pdf is not found. Should I use FC3 and FC10 separately instead?
========================================================================================================
CASE iState OF
0: (* Wait to state *)
IF SVFDWIND_01 = TRUE THEN
iState := 10;
END_IF;
10: (* Initialization of client and FC23 function block *)
(* Client *)
tcpClient.xActivate := FALSE;
tcpClient.xAutoAck := FALSE; //Do not Auto-Acknowledge errors
tcpClient.strServer_IP := '192.168.1.114'; //Device IP address
tcpClient.iPort := 502; //Default TCP port
(* FC23 function block *)
tcpMB_FC23.xActivate := FALSE;
tcpMB_FC23.iMT_ID := 1;
tcpMB_FC23.wReadStartingAddress := WORD#0;
tcpMB_FC23.uiQuantityToRead := UINT#113;
tcpMB_FC23.wWriteStartingAddress := WORD#0;
tcpMB_FC23.uiQuantityToWrite := UINT#2;
tcpClient.xActivate := TRUE;
iState := 100;
100: (* If client function block is active, then start FC23 block *)
IF (tcpClient.xError = TRUE) THEN
iState := 1001;
ELSIF (tcpClient.xActive = TRUE) THEN
tcpMB_FC23.xActivate := TRUE;
iState := 500;
END_IF;
(** Read registers **)
500: (* Now activate FC23 function block and set inputs *)
IF ((tcpMB_FC23.xActive = TRUE) AND (tcpMB_FC23.xError = FALSE)) THEN
(* Add specific data handling here *)
END_IF;
IF ((tcpMB_FC23.xError = TRUE) OR (tcpClient.xError = TRUE)) THEN
iState := 1001;
END_IF;
IF SVFDWIND_01 = FALSE THEN
iState := 1000;
END_IF;
(* Stopping comms and handling errors *)
1000: (* Finish *)
(* Deactivate client and FC23 function block *)
tcpMB_FC23.xActivate := FALSE;
tcpClient.xActivate := FALSE;
iState := 0;
1001: (*An Error has occured*)
wClientError := tcpClient.wDiagCode;
wClientAddErr := tcpClient.wAddDiagCode;
wFC23Error := tcpMB_FC23.wDiagCode;
wFC23AddErr := tcpMB_FC23.wAddDiagCode;
tcpClient.xAcknowledge := TRUE;
tcpMB_FC23.xAcknowledge := TRUE;
iState := 10;
END_CASE;
tcpClient(udtTCP_ComData := tComData);
tcpMB_FC23(udtTCP_ComData := tComData, arrReadRegistersValue => arrSVFDWIND_01_RegReturn);
=====================================================================================================
Comments
Hello,
You should be able to write Modbus registers using FC16.
Regards,
Martin.
Thank you for the quick response. Can you provide a sample code to use FC16? I can only see an example for FC3 in the pdf.
Hi,
Sorry, we don't have an example here for FC16. It is pretty much identical to FC3, but it writes registers instead of reading them.
What have you tried, and what diagnostics information do you see?
~ Martin.
I tried the code below, stuck at state 100. Please have a look at the attached images. Controller and PLCNext Engineer have the latest updates. I just need to write to the first two registers. And if I want to read the first 120 registers at the same time, how do I do it?
===========================================================================
CASE iState OF
0: (* Wait to state *)
IF SVFDWIND_01 = TRUE THEN
iState := 10;
END_IF;
10: (* Initialization of client and FC16 function block *)
(* Client *)
tcpClient.xActivate := FALSE;
tcpClient.xAutoAck := FALSE; //Do not Auto-Acknowledge errors
tcpClient.strServer_IP := '192.168.2.114'; //Device IP address
tcpClient.iPort := 502; //Default TCP port
(* FC16 function block *)
tcpMB_FC16.xActivate := FALSE;
tcpMB_FC16.iMT_ID := 1;
tcpMB_FC16.wStartRegister := WORD#0;
tcpMB_FC16.uiQuantityofRegisters := UINT#2;
tcpMB_FC16.arrRegisterValue := arrSVFDWIND_01_RegReturn;
tcpClient.xActivate := TRUE;
iState := 100;
100: (* If client function block is active, then start FC16 block *)
IF (tcpClient.xError = TRUE) THEN
iState := 1001;
ELSIF (tcpClient.xActive = TRUE) THEN
tcpMB_FC16.xActivate := TRUE;
iState := 500;
END_IF;
(** Read registers **)
500: (* Now activate FC16 function block and set inputs *)
IF ((tcpMB_FC16.xActive = TRUE) AND (tcpMB_FC16.xError = FALSE)) THEN
END_IF;
IF ((tcpMB_FC16.xError = TRUE) OR (tcpClient.xError = TRUE)) THEN
iState := 1001;
END_IF;
IF SVFDWIND_01 = FALSE THEN
iState := 1000;
END_IF;
(* Stopping comms and handling errors *)
1000: (* Finish *)
(* Deactivate client and FC16 function block *)
tcpMB_FC16.xActivate := FALSE;
tcpClient.xActivate := FALSE;
iState := 0;
1001: (*An Error has occured*)
wClientError := tcpClient.wDiagCode;
wClientAddErr := tcpClient.wAddDiagCode;
wFC16Error := tcpMB_FC16.wDiagCode;
wFC16AddErr := tcpMB_FC16.wAddDiagCode;
tcpClient.xAcknowledge := TRUE;
tcpMB_FC16.xAcknowledge := TRUE;
iState := 10;
END_CASE;
Got it now. I wasn't calling the functions. But I am still not able to write to the registers. I initially got ClientError C410 and then C020. I am able to write to the registers using MATLAB but not through the PLC. The error codes refer to timeout errors and TCP sockets. I have attached an image of my communication settings. Could you please tell me if there is something I need to change in these settings.
Hello,
If you are able to read all registers using FC3, then the communications settings are OK.
The error codes you listed are from the MB_TCP_Client instance, right? I'm afraid that this doesn't make sense to me - if you are able to read registers using FC3, then you must have established communication - without errors - using the MB_TCP_Client instance.
Please make sure that you are only using one instance of MB_TCP_Client for the device, i.e. FC3 and FC16 do not need (and should not use) two different instances of MB_TCP_Client.
If the communication is established successfully using MB_TCP_Client - which you have already done (?) - then the call to FC16 should work OK.
~ Martin.
Hello again,
For now I am just using FC3 and I am getting a timeout error C020. I have used the same code on EMPro smart meters and they work fine without any error. I used the same code on a bitronics smart meter I get C410 clienterror but still the data is being read continuously and the diagcode stays at 8000.
But, with ABB VFD I have C410 error code initially for 5 secs and I did get the right measurements, but after 5 secs I get C020 error.
I was able to get continuous readings without any errors on a different software (MATLAB).
I believe this is due to the difference in plc and vfd communication settings.
Also where do I find the communication parameters on axcf2152? (Baud rate, parity, stop bits,....etc)
I used the same communication parameters I have on EMPro smart meters but still no success.
Hi,
There are no serial comms settings on the AXC F 2152, because it doesn't have a serial port (unless you add an Axioline serial comms module). And since Modbus/TCP is not a serial comms protocol, there is no need to set serial comms parameters like baudrate etc. Perhaps I'm misunderstanding something in your setup?
In any case, this seems like an application-specific problem that should be solvable with the right client and server configuration settings.
If it's ok with you, I would like to refer you to the Phoenix Contact office in your country, where an engineer will be able to help you set up the PLC for your specific application. You can find the contact details for each country on the Phoenix Contact website. When you contact them, please ask for Automation Support.
If you have no luck there, please let us know and we'll see what we can do.
~ Martin.
Thank you Martin. You are right, we are using a serial to ethernet converter as a bridge to use Modbus/TCP and it is not a phoenix contact converter. It could be the reason for our issues. I am a student at Penn State Harrisburg and the USA headquarters are only a couple miles from us. I will contact them for help. Thanks a lot for your assistance.
so if i understand correctly, array of function blocks are not (yet..?) supported by plcnext?
Yes, that's correct, although that feature would not help in this case.
of course, I was just picking it up from your discussion as I am used to creating arrays of function blocks in other PLCs and have to convert my thinking when transitioning to PLCnext.