dear developers, i am trying to astablish an rs485 connection with the use of the “rsuni-1h module” through eclipse. i don’t understand how it works, the best information is published in: “db_en_axl_f_rs_uni_1h_8533_en_04” they mention the pdi channel to comunicate, only accesable through iec61131? how to link it to eclypse? is there a tuturial/example on how to work with, and configure the module? kind regards nick peeters
Hello Nick, you can use the acyclic PDI Services for axioline mentioned in the hanbook of 2019.0 LTS https://d25bvexk2ts44g.cloudfront.net/108664_en_01/Section05/Section05.htm?rhhlterm=acyclic&rhsyns;=%20 These Services can be used like the IEC 61131 functionblocks but in C++
Maybe this is a good addition for an extensive example at the PLCnext GitHub Organisation?
kind regards,
Oliver
dear developers, i’ve bin trying all day long just to read a single register over modbus RTU using the RS UNI 1H module, i just can’t figure out how it is ment to do it. where to define the adres, where to define the registers to be read? the acyclic PDI Services makes use of a structure, going into the defined lybraries it says in PdiParam.hpp that it is not ment to be modified, in MyProgram::Execute() PdiParam.Slot = “some value” for example turns into a compiler error so how to modiefied from outside the librarie? furthermore the parameters do not have any relations with the modbus protocol (“slot” “subslot” “index” “SubIndex”) this is only to configure the module acording to the manuals, hence it does not configure much because i just get junk when defining a variable to be the value of pdiread (e.g. Result= PdiRead;) how does it work? the manuals don’t realy help me. is there some example on how to do it? kind regards nick
Hi Nick, I hope I can help. I understand that you want to set up the RS UNI module as a Modbus/RTU master, and exchange data with one or more Modbus/RTU slaves from your C++ program. While it is possible to exchange process data with the module via the PDI channel, it is probably simpler to use the Process Data channel, because then you can connect the process data directly from the module to IN and OUT ports of your C++ program. To do this: - in your C++ program, declare one IN port and one OUT port as follows (you can choose your own variable names):
//#port > //#attributes(Input) > uint8 inProcessData[20] = {0}; //#port > //#attributes(Output) > uint8 outProcessData[20] = {0};The OUT port will contain the data you transmit to the RS UNI, and the IN port will contain data you receive from the RS UNI. - after creating an instance of your C++ program in PLCnext Engineer, connect the ports on your C++ program to the process data ports on the RS UNI module The process data from the RS UNI is now available to your C++ program. Now - how to use this process data to communicate with a Modbus/RTU slave? This gets a little complicated, because we only have 20 bytes (in each direction) to communicate between the PLC and the RS UNI, but of course Modbus/RTU messages can be much longer than this. The RS UNI has an internal buffer that stores incoming and outgoing messages, so the RS UNI will send very long incoming message (for example) to our C++ program in 20-byte chunks, controlled by us. Section 11.5 in the user manual describes the “telegram structure” for Modbus/RTU messages. So, to read a register (FC3) from an RTU with address 42, you would set the Address byte to 0x2A , and the Function byte to 0x03., and then the remainder of the data to specify the register numbers in the slave. This telegram layout follows the standard Modbus format, but note that CRC will always be generated automatically (thank goodness!). Now we need to put these telegram bytes into our
outProcessDataarray … but where? Starting at byte 0, or … ? To answer this question - we need to look at section 12 of the user manual. This shows the layout of the 20 bytes of process input and output data, for the RS UNI. Here, we can see that our Modbus/RTU Telegram (which is the “Data” in the message we are sending) occupies bytes 3, 4, 5, … 19 in the 20-byte OUT array. So, in our C++ program, we must setoutProcessData[3] = 0x2A,outProcessData[4] = 0x03, etc. - but not including the CRC (which is generated automatically). But that’s not all … in order to tell the RS UNI how many bytes of data we are sending, we must setoutProcessData[2]to the number of bytes in the telegram, including the slave address but not including the CRC. In order to actually send the message, we must also set bytes 0 (command) and 1 (control) … and for this we look at section 13 of the user manual … In the case of sending a simple message, the command and control bytes are easy - the only bits that must be set are the three Command bits (set to binary 001). So in this caseoutProcessData[0] = 0x10andoutProcessData[1] = 0x00. The RS UNI only looks for a change in the Command bits, so to repeatedly request the same set of register values from the same slave, you can just toggle the MSB of the three command bits, and the RS UNI will send the same command over and over to the same slave. But you probably don’t want to send the next request until you’ve processed the first reply … and here is where theinProcessDataarray in your C++ program will be used. After sending the first message to the slave, you can start checking the Status byte from the RS UNI - i.e.inProcessData[1]. When you see the LSB on this bit go high, this indicates that a message has been received by the RS UNI. To read this message, you now must send command 011 (binary) to the RS UNI, i.e.outProcessData[0] = 0x30. (see section 14.4 of the user manual). Now you are looking for the RS UNI to reply with 0x30 ininProcessData[0], after which you can check the number of bytes that are available to read (byte 2), and the data itself (bytes 3-19). The rest of section 14.4 explains how to read the complete reply. Note that if the slave replies with more than 17 bytes of data, you will need to send multiple read requests to the RS UNI to get all the data from the input buffer. Phew. All the above assumes that you have configured the RS UNI module correctly in PLCnext Engineer, e.g. set the protocol of the module to “Modbus/RTU”. In case it helps, there is some sample code in this earlier post, which attempts to do something like I described above, but in C# and using the Transparent protocol, rather than the Modbus/RTU protocol, but its not a million miles from what you want to do, I think. One day I am sure that some enterprising software engineer will develop a C++ Component that hides all the details of these comms with the RS UNI, in a similar way to this function block library does in PLCnext Engineer … until then, please get back to us with any questions. Martin.